tbottest.generic
This is an example approach for a hopefully easy to use lab and board support.
The configuration of a board is in two files, the lab configuration (lab host, build hosts, console, power control, …) and the board configuration (the settings of the board for the testcases). Both come in one of two formats, with the same sections and keys:
ini files,
tbot.iniandBOARDNAME.ini, read with configparser (https://docs.python.org/3/library/configparser.html, with all its limitations). Values that change from run to run are@@...@@placeholders, which boardspecific.py replaces at every start, see boardspecific runtime adaptions (ini files).JSON files,
tbot.jsonandBOARDNAME.json. Values that change from run to run are expressions like${flag:kasvariant:-musl}, so there is no boardspecific.py, see JSON configuration and expressions.
The flags inifile: and boardfile: (see tbot flags) name the two
files, and their extension selects the format. create_setup.sh sets up ini
files, or JSON files with --json.
The rest of this document calls the files tbot.ini and
BOARDNAME.ini and writes a section as [SECTION], as in an ini file.
With JSON these are tbot.json, BOARDNAME.json and the key
"SECTION" of the top level object.
generic testcases
With this configuration the testcases in tbottest.tc.generic_board
run without code of your own. What they check comes from keys of the board
configuration (see board configuration (BOARDNAME.ini or BOARDNAME.json)),
a value for one testcase only goes into its section
TC_BOARDNAME.TESTCASENAME. A testcase whose key is not set is skipped.
Start them like any other testcase, e.g. with the aliases and variables of
setup.sh
$ source setup.sh
$ tbBOARDNAME $tbtc.generic_board.generic_lnx_test_dmesg
The generic Linux testcases, all started by
tbottest.tc.generic_board.generic_lnx_all():
testcase |
keys |
what it checks |
|---|---|---|
regdump |
reads the registers with devmem2 and writes them with the register map of the SoC into generic_registerdump.txt in the workdir of the host tbot runs on; skipped if the SoC is not known |
|
iperf |
iperf between lab host and board, in both directions |
|
ping |
ping from the board |
|
beep |
the beeper |
|
lnx_commands |
the output of Linux commands |
|
dmesg, dmesg_false |
strings that must be in dmesg, and strings that must not |
|
leds |
switches the LEDs on and off |
generic_lnx_all() runs them one after
the other and logs at the end how many succeeded, were skipped or failed,
with the names of the skipped and the failed ones. It does not fail itself
when one of them failed, so read the summary.
$ tbBOARDNAME $tbtc.generic_board.generic_lnx_all
Further generic testcases:
testcase |
keys |
what it does |
|---|---|---|
|
lnx_dump_files |
write register dump files, and compare the registers with them later |
finds out which implementation and version of the commands tbottest uses lab host, build host and board have, and logs a line for the key cmd_versions of each, see command versions |
||
writes the configuration of a run as JSON, see JSON configuration and expressions |
||
kas, kas_check_files, kas_results |
builds with kas, calls generic_kas_checkout, generic_kas_build, generic_kas_check_build and generic_kas_copy, see kas settings |
There is no generic testcase for all U-Boot testcases. The template
tbotconfig/BOARDNAME/BOARDNAME.py has BOARDNAME_ub_all, which runs
the U-Boot testcases of the board listed in ub_testcases.
requirements for lab host
Commands that need root rights on the lab host (setting up the board’s
ethernet device, mounting an SD card, sd-mux, imx_usb, uuu, installing
packages) run with sudo when tbot is logged in to the lab host as a normal
user; sudo then has to work without entering a password. When tbot is
logged in as root, they run without sudo, so a lab host without sudo (for
example one built with Yocto) works as well. tbottest asks id -u once
per machine, see tbottest.tc.common.lnx_sudo(). Use it in your own
testcases instead of a fixed sudo:
from tbottest.tc.common import lnx_sudo
lab.exec0(*lnx_sudo(lab), "mkdir", "-p", path)
Commands you write into tbot.ini yourself (e.g. labinit) are run as
written, so leave out sudo there on a lab host you log in to as root.
You should be able to ssh between lab host, build host and board without entering a password or something else!
supported hardware/tools
Console access to the board with:
picocom, see [PICOCOM_BOARDNAME]
kermit, see [KERMIT_BOARDNAME]
telnet, see [TELNET_BOARDNAME]
a script of your own, see [SCRIPTCOM_BOARDNAME]
ssh into the running Linux of the board, flag ssh
Power control with:
sispmctl, see [SISPMCTRL_BOARDNAME]
Tinkerforge, see [TF_BOARDNAME]
a GPIO pin, see [GPIOPMCTRL_BOARDNAME]
a shell script, see [POWERSHELLSCRIPT_BOARDNAME]
a Shelly device through shelly-ctrl, see [SHELLY_BOARDNAME]
a tbox SYSTEM Controller Modul through tbox-ctrl (USB HID), see [TBOX_BOARDNAME]
a tbox lab host through hwdamon-dut-power, see [TBOX_HWDAEMON_BOARDNAME]
the DH electronics TM-021 relay module, see [TM021_BOARDNAME]
Loading SPL/U-Boot after power on, or a debugger, with:
uuu from NXP, see setup for uuu tool
dfu-util, see setup for dfu-util tool
sb, xmodem/ymodem over the serial line, see setup for sb tool
Lauterbach TRACE32, see setup for Lauterbacher debugger
Segger J-Link, see setup for Segger debugger
Abatron BDI2000, commands after power on and a telnet session, see setup for BDI2000 debugger
It should be easy to extend this! tbot does not prevent you to use other hardware (nor to make stupid stuff)!
configuration
Create a directory, e.g. tbotsetup, which holds the sources of tbot and tbottest and a subdirectory tbotconfig with all your project specific settings and testcases. The layout, file by file, is in file/directory overview; the example is tbottest/tbotconfig.
Note
You can simply use the script create_setup.sh in scripts, which will create all files and directories. Start it with the option “–inter” and you get asked some questions, which help to make a better basic setup.
$ ./scripts/create_setup.sh --inter
tbot comes from the branch v0.10.10-emb of
https://github.com/EmbLux-Kft/tbot: tbot v0.10.10 with the changes
tbottest needs on top, so nothing has to be patched after the clone.
tbottest comes from the branch master of
https://github.com/hsdenx/tbottest, another one with -b <branch>, a
fixed commit with -c <commit>.
If tbot or tbottest exist already, create_setup.sh brings them to
the current state of their branch: nothing happens if they are there
already, a fast forward if the clone has neither commits of its own nor
local changes; otherwise it only says why it left the clone alone, so no
local work is lost. tbottest is not updated when it is set to a commit
with -c, and neither clone is with --no-update. The environment
variables TBOT_URL, TBOT_BRANCH and TBOTTEST_URL replace the
sources, e.g. with a mirror.
start script
with the newbot_starter.py script you can start tbot and your setup without the need to install tbot and tbottest.
tbotconfig
contains the whole lab and board configuration.
README
README.BOARDNAME is not mandatory, but it is helpfull to collect/document at least some tbot usecases/commands.
file/directory overview
What scripts/create_setup.sh sets up, with tbotconfig for one board:
tbotsetup/
├── setup.sh aliases for starting tbot (source setup.sh)
├── tbot/ tbot, branch v0.10.10-emb of github.com/EmbLux-Kft/tbot
├── tbottest/ this repository; newtbot_starter.py starts tbot
└── tbotconfig/ your own repository: configuration and testcases
├── interactive.py testcases for interactive sessions
├── ci/ testcases of the tbottest CI on github (only with --ci)
├── tc_BOARDNAME.py testcases of the board
└── BOARDNAME/
├── args/ argumentfiles
│ ├── argsbase
│ ├── argsBOARDNAME
│ ├── argsBOARDNAME-noeth
│ └── argsBOARDNAME-noeth-ssh
├── boardspecific.py runtime adaptions of the configuration (ini files only)
├── BOARDNAME.ini board configuration as ini file
├── BOARDNAME.json board configuration as JSON file (instead of BOARDNAME.ini)
├── files/
│ └── dumpfiles/ files of the register dump testcases
├── README.BOARDNAME notes on the tbot setup of the board
├── tbot.ini lab configuration as ini file
└── tbot.json lab configuration as JSON file (instead of tbot.ini)
Name |
content |
fastlink to documentation |
|---|---|---|
setup.sh |
aliases for starting tbot |
|
tbotconfig/interactive.py |
testcases for interactive sessions: lab host, build host, kas shell, board, U-Boot, Linux, BDI2000 |
|
tbotconfig/ci |
testcases the github CI of tbottest runs; create_setup.sh copies them only with |
|
tbotconfig/tc_BOARDNAME.py |
testcases of the board, from tbottest/tbotconfig/BOARDNAME/BOARDNAME.py |
|
BOARDNAME/args |
argumentfiles: argsbase, argsBOARDNAME, and the variants -noeth (flags noethinit, noboardethinit) and -noeth-ssh (adds nopoweroff, always-on, ssh, nouboot) |
|
BOARDNAME/boardspecific.py |
functions that adapt the configuration at runtime, e.g. replace the @@…@@ placeholders; ini files only, not imported with JSON |
|
BOARDNAME/BOARDNAME.ini, BOARDNAME/BOARDNAME.json |
board configuration, the board specific settings for the generic testcases, as ini or JSON file |
|
BOARDNAME/files/dumpfiles |
reference files of the register dump testcases (lnx_dump_files in BOARDNAME.ini) |
|
BOARDNAME/README.BOARDNAME |
notes on the tbot setup of the board, not mandatory |
|
BOARDNAME/tbot.ini, BOARDNAME/tbot.json |
lab configuration, lab host, build hosts and how tbot reaches and controls the board, as ini or JSON file |
|
BOARDNAME/tbot.ini-<id>, BOARDNAME/BOARDNAME.ini-<id> |
copies tbot writes at every start, with the placeholders replaced; flag tmpfilepath:<dir> writes them elsewhere; ini files only, JSON files are read as they are |
boardspecific runtime adaptions (ini files)
The ini file approach is static, which means we cannot change configuration @runtime. With JSON files, use expressions instead, see JSON configuration and expressions. This generic approach searches in tbotconfig for a boardspecific.py file, which can contains several functions, the generic approach tries to call.
In this functions you can adapt settings dependend on the usecase. Or may do special stuff in machine shells.
In the default ini files there are placeholders beginning with @@ and ending with @@. You can easily replace them with helper functions.
Therefore the following functions are used:
set_board_cfg(temp: str = None, filename: str = None)
This file is called early in bootup before any ini file is parsed. So you can adapt the ini files for your needs
import tbot
from tbottest.generic.iniconfig import replace_in_file
tbot.selectable.printed = False
def print_log(msg):
if tbot.selectable.printed:
return
tbot.log.message(tbot.log.c(msg).yellow)
def set_board_cfg(temp: str = None, filename: str = None):
"""
setup board specific stuff in ini files before they get parsed
"""
# print tbot.flags, as tbot prints them not longer
print_log(f"TBOT.FLAGS {tbot.flags}")
replace_in_file(filename, "@@TBOTBOARD@@", "<boardname in your lab setup>")
replace_in_file(filename, "@@TBOTDATE@@", "20230221")
replace_in_file(filename, "@@TBOTMACHINE@@", "<yocto machine name>")
tbot.selectable.boardname = None
for f in tbot.flags:
if f.startswith("boardname:"):
tbot.selectable.boardname = f.split(":", 1)[1]
if tbot.selectable.boardname == None:
tbot.selectable.boardname = "wandboard"
board_set_boardname
called from initconfig.py generic_get_boardname()
import tbot
def board_set_boardname() -> str:
# do not use boardname flag
BOARDNAME = "foo"
for f in tbot.flags:
if "8G" in f:
if len(f) == 2:
BOARDNAME = "foo-8G"
return BOARDNAME
set_ub_board_specific
called from boardgeneric.py in init function.
setup U-Boot specific parts after entering the U-Boot shell
def set_ub_board_specific(self):
optargs = self.env("optargs")
optupd = False
if "bootchartd" in tbot.flags:
optargs = f"{optargs} init=/lib/systemd/systemd-bootchart"
optupd = True
if "debug_initcalls" in tbot.flags:
optargs = f"{optargs} initcall_debug"
optupd = True
if optupd == True:
self.env("optargs", optargs)
if "silent" in tbot.flags:
self.env("console", "silent")
JSON configuration and expressions
Instead of the two ini files, tbot reads the same configuration from two
JSON files, if the flags inifile: and boardfile: name files that
end in .json (both, mixing ini and JSON stops tbot):
-f inifile:tbotconfig/BOARDNAME/tbot.json -f boardfile:tbotconfig/BOARDNAME/BOARDNAME.json
A JSON file is an object of sections, each an object of keys, with the same names as in the ini file. A value may be a string, a number, true, false, null, a list or an object; tbot keeps it as the string the ini file would have (lists and objects as Python literal), so every testcase reads it as before.
With JSON, tbot reads the files as they are: no copies, no @@...@@
placeholders, and no boardspecific.py, which is not even imported.
What depended on flags or the environment is written as an expression
in the file. The expressions also work in ini files, after the
placeholders are replaced:
expression |
value |
|---|---|
|
environment variable NAME |
|
value of the tbot flag NAME:<value>, True for a flag NAME without value |
|
key of the lab section of tbot.ini or tbot.json (LABHOST or LABHOST_<labname>), in the board file |
|
key of SECTION of tbot.ini or tbot.json, in the board file |
A value that is not set and has no default stops tbot with the
expression and the file. The default is used only when the value is not
set. Expressions may be nested, and are replaced before configparser
interpolates ${key} and ${section:key} of the same file, so a
section can be selected by a flag:
{
"default": {
"kasvariant": "${flag:kasvariant:-musl}",
"kasymlname": "${KASVARIANT_${flag:kasvariant:-musl}:kasfile}",
"nfs_path": "${lab:nfs_base_path}/${vendor}/${machine}/${kasvariant}",
"serverip": "${tbot:IPSETUP_BOARDNAME_eth0:serverip}"
},
"KASVARIANT_musl": {"kasfile": "BOARDNAME-musl.yml"},
"KASVARIANT_glibc": {"kasfile": "BOARDNAME-glibc.yml"}
}
Without the flag boardname: the board name comes from the key
board of the lab section of tbot.json, e.g.
"board": "${flag:boardname:-BOARDNAME}". A U-Boot variable that depends on
a flag, what set_ub_board_specific() of boardspecific.py did,
is an entry of ub_env with "flag", set only with that flag:
{"name": "console", "val": "silent", "flag": "silent"}
The testcase tbottest.tc.generic_board.generic_config_to_json()
writes the configuration of a run with ini files as tbot.json and
<boardname>.json, as the start of a JSON configuration (flag
config_json_dir:<dir>, default config-json); with the flag
config_json_resolved it writes the values resolved, to compare two
configurations.
lab configuration (tbot.ini or tbot.json)
The lab configuration describes the lab host, the build hosts and how tbot reaches and controls the board. Find example files here: tbottest/tbotconfig/BOARDNAME/tbot.ini and tbottest/tbotconfig/BOARDNAME/tbot.json.
The same section in both formats, first as ini file
[LABHOST]
labname = mylab
username = pi
tmpdir = /tmp/tbot/${username}
and then as JSON file
{
"LABHOST": {
"labname": "mylab",
"username": "pi",
"tmpdir": "/tmp/tbot/${username}"
}
}
Currently there are the following sections:
[LABHOST]
here you configure common lab host setting. Mandatory.
You can select between ssh key login or password login into the lab host.
For login with ssh key set key ‘sshkeyfile’, for password login set key ‘password’.
key |
value |
example |
|---|---|---|
labname |
name of your lab |
lab7 |
hostname |
hostname of lab host |
192.168.1.123 |
username |
username on lab host |
pi |
port |
ssh port number |
22 |
sshkeyfile |
path to the ssh keyfile, tbot uses |
/home/USERNAME/.ssh/id_rsa |
password |
set password to login into lab host |
FooBar |
date |
subdirectory in boards tftp path |
20210803-ml |
board |
name of the board, used without the flag boardname:, see JSON configuration and expressions |
${flag:boardname:-foo} |
shelltype |
type of the linux shell (bash|ash) |
bash |
toolsdir |
where does tbot find tools installed on lab host |
/home/USERNAME/source |
tftproot |
rootpath to tftp directory on lab host. tbot stores there build results. |
/srv/tftpboot |
tftpsubdir |
boards subdir in tftproot |
BOARD/DATE |
workdir |
tbots workdirectory on lab host |
/work/USERNAME/tbot-workdir/BOARD |
tmpdir |
path to where tbot stores temporary data |
/tmp/tbot/USERNAME/BOARD |
testdir |
optional, path where testcases install or build things on the lab host, default workdir/tbottests |
/work/USERNAME/tbot-workdir/BOARD/tbottests |
proxyjump |
if set, proxyjump settings for ssh login on lab host |
|
labinit |
array of strings which contains commands, executed when you init the lab. They run once per boot of the lab host, marked by /tmp/tbotlabinitdone; the setup of the board’s ethernet devices on the lab host runs once per board, marked by /tmp/tbotlabinitdone-<boardname>. Remove a marker to run its part again |
[‘sudo systemctl –all –no-pager restart tftpd-hpa’] |
nfs_base_path |
base path to nfs share on lab host. For a board specific subdirectory use ${lab:nfs_base_path} in the board configuration, or in an ini file the placeholder @@TBOTLABBASENFSPATH@@, replaced in set_board_cfg |
/srv/nfs |
uselocking |
use board locking mechanism. You must pass correct locking id for the board with tbot flag lablocking:<lockingid> else tbot will fail. |
yes|no |
cmd_versions |
optional, preset of cmd_get_version() for the lab host, see command versions |
{“top”: “busybox:1.37.0”, “ip”: “iproute2:6.19.0”} |
The above labhost defintion is the default one, You can add more than one labhost, simply add them with the following section naming
[LABHOST_<NAME_OF_LAB>]
You can now select this lab by adding tbot flag
-f labname:<NAME_OF_LAB>
on start of tbot.
[BUILDHOST]
here you configure common build host setting. Only used, if you use a buildhost.
key |
value |
example |
|---|---|---|
name |
name of your build host |
threadripper-big-build |
username |
username on your build host |
hs |
hostname |
hostname of your build machine |
192.168.1.120 |
port |
portnumber of your build machine |
12004 |
docker |
porxy jump configuration |
|
dl_dir |
for yocto builds, sets DL_DIR |
/work/downloads |
sstate_dir |
for yocto builds, set SSTATE_DIR |
/work2/hs/tbot2go/yocto-sstate |
kas_ref_dir |
when using kas, path where kas finds git trees for reference cloning |
/work/hs/src |
workdir |
path to directory where tbot can work on |
/work/big/hs/tbot2go |
testdir |
optional, path where testcases install or build things on the build host, e.g. an SDK, default workdir/tbottests |
/work/big/hs/tbot2go/tbottests |
authenticator |
path to ssh id key file |
/home/hs/.ssh/id_rsa |
password |
password for ssh login. Unsure! |
CrazyPassword |
initcmd |
list of commands executed after login |
[“uname -a”, “cat /etc/os-release”] |
cmd_versions |
optional, preset of cmd_get_version() for the build host, see command versions |
{“tar””: “”tar:1.35””}” |
If you do not add authenticator or password, tbot uses NoneAuthenticator for ssh login. Hopefully than your ssh config is correct.
The above buidlhost defintion is the default one, You can add more than one buildhost, simply add them with the following section naming
[BUILDHOST_<NAME_OF_BUILDER>]
You can now select this builder by adding tbot flag
-f buildname:<NAME_OF_BUILDER>
on start of tbot.
The next sections depend on your board configuration
[BOOTMODE_BOARDNAME]
if you need to set a bootmode for your board, you can add this section.
You can give each bootmode a name and if you pass this name to tbot with the “-f” flag, the lab approach first sets all gpios you have defined for this bootmode to the respective states, before it powers on the board.
Find more information in
[PICOCOM_BOARDNAME]
if you want to use picocom for connecting to your boards console.
tbottest.connector.PicocomConnector()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
baudrate |
baudrate of the boards console |
115200 |
device |
linux device name for the serial device on lab host |
/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0 |
delay |
delay for power off |
3 |
noreset |
set picocom noreset parameter |
True |
slow_send_delay |
optional, seconds to wait after each chunk sent to the console |
0.01 |
slow_send_chunksize |
optional, maximum number of bytes sent at once |
1 |
Without slow_send_delay and slow_send_chunksize the channel sends
8 bytes and then waits 10 ms. Consoles that still drop characters (the
echo of a command misses letters) need smaller chunks, down to 1.
[KERMIT_BOARDNAME]
if you want to use kermit for connecting to your boards console
tbottest.connector.KermitConnector()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
cfgfile |
path to kermit config file, which is passed to kermit when starting |
/home/pi/kermrc_wandboard |
delay |
delay for poweroff |
3 |
kermit_options |
optional, additional command line options passed to kermit before the config file |
[‘-c’, ‘-y’] |
[SCRIPTCOM_BOARDNAME]
if you want to use a script for connecting to your boards console.
tbottest.connector.ScriptConnector()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
scriptname |
Name of the script |
connect |
exitstring |
string send to exit |
~~. |
[TELNET_BOARDNAME]
if you want to use telnet for connecting to your boards console (e.g. a terminal/console server exposing the serial line as a telnet port).
tbottest.connector.TelnetConnector()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
host |
optional, telnet host |
localhost |
port |
telnet port |
2013 |
delay |
optional, delay after exit |
3 |
[GPIOPMCTRL_BOARDNAME]
If you want to control boards power with gpio pins
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
gpiopmctl_pin |
pin number of gpio pin |
17 |
gpiopmctl_state |
on state |
1 |
[POWERSHELLSCRIPT_BOARDNAME]
If you want to control boards power with a shell script
tbottest.powercontrol.PowerShellScriptControl()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
script |
Name of shell script used to control board power |
/tmp/power.sh |
[SISPMCTRL_BOARDNAME]
If you want to control boards power with sispmctl
tbottest.powercontrol.SispmControl()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
device |
id of sispmctl device |
01:01:4f:d4:b1 |
port |
sispmctl port used for the boards power |
3 |
[SHELLY_BOARDNAME]
If you want to control boards power with a Shelly device. tbot calls
shelly-ctrl on the lab
host, which must reach the Shelly device. Without command tbot uses
shelly-ctrl.py from the PATH of the lab host, else shelly-ctrl in
shelly-ctrl in the toolsdir of the lab host. If it is in neither
place, tbot clones it into this directory and installs its python
dependencies into a virtual environment .venv in it, so the lab host
needs git and python3 with the venv module. With install = no tbot
stops instead. tbot looks for shelly-ctrl only once per run.
tbottest.powercontrol.ShellyControl()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
device |
Shelly device, given by IP, by MAC or by its mDNS name |
192.168.1.86 |
id |
optional channel of multi channel devices, default 0 |
0 |
command |
optional shelly-ctrl command on the lab host, it is not installed by tbot |
shelly-ctrl.py |
timeout |
optional maximum time in seconds to look up MAC or mDNS name |
5 |
install |
optional, no if tbot should not install shelly-ctrl, default yes |
no |
[TBOX_BOARDNAME]
If you want to control boards power with a tbox SYSTEM Controller Modul (talking to it over USB HID via tbox-ctrl)
tbottest.powercontrol.TboxCtrlControl()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
powerpin |
tbox-firmware pin to switch for this board |
P1_5V_EN |
vid |
optional USB VID override for tbox-ctrl |
0x1209 |
pid |
optional USB PID override for tbox-ctrl |
0x0001 |
[TBOX_HWDAEMON_BOARDNAME]
If you want to control boards power on a tbox lab host whose power outputs belong to hwdamon: tbot runs on the lab host
hwdamon-dut-power -f <configfile> on|off <boardname>
tbottest.powercontrol.TboxHwdaemonControl()
replace BOARDNAME with the name of your board! Here as example BOARDNAME.
key |
value |
example |
|---|---|---|
boardname |
name of the DUT in hwdamon, or its slot number (1-4) |
BOARDNAME |
configfile |
optional hwdamon configuration file on the lab host, default /etc/hwdaemon.json |
/etc/hwdaemon.json |
[TM021_BOARDNAME]
Set this section, If you want to control boards power with DH electronics “TM-021 4-fach Relaismodul”.
tbottest.powercontrol.TM021Control()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
device |
device node of used linux device |
/dev/relais |
baudrate |
baudrate for the linux device |
500000 |
timeout |
timeout in seconds for one command |
5 |
address |
address of the relais |
0 |
port |
port of the relais |
1 |
debug |
if you want to have debug traces set this to True |
False |
[TF_BOARDNAME]
If you want to control boards power with tinkerforge
tbottest.powercontrol.TinkerforgeControl()
replace BOARDNAME with the name of your board! Here as example wandboard.
key |
value |
example |
|---|---|---|
uid |
tinkerforges uid |
Nt2 |
channel |
channel |
1 |
ethernet config
ipsetup for an ethernetdevice on board, add section
[IPSETUP_BOARDNAME_<ethdevice_board>]
replace BOARDNAME with the name of your board! Here as example for setup eth0 on wandboard.
key |
value |
example |
|---|---|---|
labdevice |
device which is connected to eth0 on board |
eth0 |
netmask |
netmask |
255.255.255.0 |
ethaddr |
ethaddr (MAC) of the device on board |
00:1f:7b:b2:00:0e |
ipaddr |
ipaddr of the board for device on board |
192.168.3.21 |
serverip |
server ip, ip address of lab host |
192.168.3.1 |
[UBCFG_BOARDNAME]
if you need to specifiy in U-Boot which lab host ethernetinterface is should use, define this section.
replace BOARDNAME with the name of your board! Here as example for setup eth0 on wandboard.
key |
value |
example |
|---|---|---|
ethintf |
ethernetinterface used on lab host for u-boot, default is eth0 |
eth0 |
setup for dfu-util tool
if you need to load U-Boot binaries with dfu-util tool, use
tbottest.machineinit.DFUUTIL()
define the section
key |
value |
example |
|---|---|---|
cmds |
array of dictionary, format see example |
[{‘a’:’@FSBL /0x01/1*1Me’, ‘D’:’${LABHOST:tftproot}/${LABHOST:tftpsubdir}/u-boot-spl.stm32’}, {‘a’:’u-boot.itb’, ‘D’:’${LABHOST:tftproot}/${LABHOST:tftpsubdir}/u-boot.itb’}] |
setup for uuu tool
if you want to use NXPs uuu tool with class
tbottest.machineinit.UUULoad()
define the section
key |
value |
example |
|---|---|---|
cmd |
comma seperated list of uuu commands to load SPL/U-Boot with uuu tool. |
LBD/SPL,SDPV: delay 100,SDPV: write -f LBD/u-boot.img -addr 0x877fffc0,SDPV: jump -addr 0x877fffc0 |
setup for sb tool
if you need to use UART boot and xmodem / ymodem transfer for loading the bootloader onto the hardware use this class
tbottest.machineinit.XMODEMLoad()
define the section
key |
value |
example |
|---|---|---|
device |
serial device sb tool uses |
/dev/ttyUSB0 |
cmd |
list of commands to load SPL/U-Boot with sb tool. |
[“sb –xmodem TFTPDIR/tiboot3.bin > SERDEV < SERDEV”] |
SERDEV is replaced before executing the command with the value in device and TFTPDIR is replaced with the boards current tftp path.
setup for Lauterbacher debugger
if you want to use Lauterbacher debugger use this class
Currently we use the python script t32apicmd.py from lauterbach installation directory “install_path” in subdir “demo/api/python”. Later we will use this api directly.
tbottest.machineinit.LauterbachLoad()
define the section
key |
value |
example |
|---|---|---|
verbose |
1 = verbose output |
1 |
cmd |
/opt/t32/bin/pc_linux64/t32marm-qt |
|
install_path |
path to your installation of Lauterbacher tools |
/opt/t32 |
config |
path to config.t32 file |
/from_ftp/lauterbach-scripts/hsconfig.t32 |
script |
path to script which gets executed |
/from_ftp/lauterbach-scripts/autostart.cmm |
setup for Segger debugger
if you want to use Segger debugger use this class
tbottest.machineinit.SeggerLoad()
define the section
key |
value |
example |
|---|---|---|
install_path |
path to your installation of the Segger tools |
/opt/segger |
cmds |
list of commands executed in JLinkExe shell to bring up U-Boot |
[{‘cmd’:’go’, ‘prompt’:’J-Link>’}] |
setup for BDI2000 debugger
if your board has an Abatron BDI2000 attached, define its address. tbot
then provides the BDI2000 as a machine for the role
tbottest.bdi2000.BDI2000, a telnet session to the BDI’s command
line from the lab host, on which exec() runs one BDI command and
returns its output.
Open an interactive session on it with the testcase
tbottest.tc.bdi2000.bdi2000()
Leave it like any other interactive session, with CTRL+] three times within one second.
With poweron_cmds set, the board control runs these commands on the
BDI2000 every time it has powered the board on, for example reset run
when the BDI would otherwise hold the CPU in reset
(tbottest.machineinit.BDI2000Cmds). Right after power on the
BDI still waits for the target Vcc and a command sent then is lost; with
poweron_wait_state set, the commands are only sent once the BDI command
info reports that target state.
After reset the BDI works through the init list of its configuration
file, but prints its prompt before it is done. A command whose output shows
the init list started waits until the BDI reports it passed (and fails if
it reports failed), so poweron_cmds = ["reset", "go 0x40000100"]
starts the target only after the init list ran.
The BDI has no return codes and takes the next command even after one
failed. exec() therefore raises an error when the output contains one of
the messages in BDI_ERRORS (tbottest.bdi2000), for now
Cannot open file on host, and when a load does not report
Loading program file passed. The remaining poweron_cmds are not
sent then, so a go after a failed load does not start whatever is
in the target’s memory, and the testcase fails at once. A load of a
file that is not on the TFTP server:
[bdi2000] load 0x00100000 BOARDNAME/20261001/musl/u-boot-ram.bin bin
## Loading BOARDNAME/20261001/musl/u-boot-ram.bin , please wait ....
## # Cannot open file on host
poweron_cmds can also be a dictionary of named command lists, for a
board that is started in more than one way. The tbot flag
-f poweron_cmds:<name> selects the list to run; without the flag the
entry default is taken, and no commands at all if there is none.
-f poweron_cmds:None skips the BDI2000 after power on completely,
poweron_wait_state included, for example when the board is started by
hand on the BDI (tbottest.initconfig.bdi2000_poweron_cmds()).
poweron_cmds = {
"default": ["reset run"],
"nowdt": ["reset", "go 0x40000100"],
}
A list may contain the entry configname:<file>, the configuration
file the BDI has to run with for the other commands. It is not sent as a
command: before the other commands, the board control asks the BDI with
config which file it runs with. If it is <file>, the commands run
as usual. Otherwise it sets <file> with config <file> <host>, the
host being the one the BDI loads its current file from. The BDI answers
Updating configuration passed. Booting ....., boots with the new file
right away and ends the telnet session; tbot connects again until the BDI
answers, within poweron_timeout seconds, and checks that it runs with
<file> before it waits for
poweron_wait_state and sends the commands
(tbottest.bdi2000.ensure_config()). So each command list can
bring the configuration file it needs:
poweron_cmds = {
"default": ["configname:BOARDNAME/bdi/BOARDNAME-nowdt.cfg", "reset", "go 0x40000100"],
"reset": ["configname:BOARDNAME/bdi/BOARDNAME.cfg", "reset run"],
}
key |
value |
example |
|---|---|---|
ip |
IP address of the BDI2000, reached with telnet from the lab host |
192.168.3.101 |
poweron_cmds |
optional list of BDI commands run after each power on of the board, or a dictionary of such lists selected with -f poweron_cmds:<name>; an entry configname:<file> selects the configuration file of the BDI first |
[‘reset run’] |
poweron_wait_state |
optional target state, as info reports it, to wait for before poweron_cmds |
debug mode |
poweron_timeout |
seconds to wait for poweron_wait_state, and for the BDI to boot for configname:<file>, default 30 |
30 |
board configuration (BOARDNAME.ini or BOARDNAME.json)
The board configuration holds the settings of the board for the
testcases, in tbotconfig/BOARDNAME/BOARDNAME.ini or BOARDNAME.json (flag
boardfile:). Find example files here:
tbottest/tbotconfig/BOARDNAME/BOARDNAME.ini
and tbottest/tbotconfig/BOARDNAME/BOARDNAME.json.
It contains the sections TC and TC_BOARDNAME, and optionally a
section TC_BOARDNAME.TESTCASENAME for a testcase. While a testcase
decorated with tbottest.tc.generictestdef.tc_config() or
tbottest.tc.generictestdef.require_cfg() runs, a key is looked up
first in TC_BOARDNAME.TESTCASENAME, then in TC_BOARDNAME and then
in TC. Outside of such a testcase only the last two count. What
happens if no section has the key is described at
tbottest.initconfig.init_get_config().
There is deliberately no section TC_TESTCASENAME for a testcase on
all boards. A value for all boards goes into TC, so a key is never
searched in more than three places.
For example, the strings of the dmesg testcase for the board BOARDNAME only, as ini file
[TC_BOARDNAME.generic_lnx_test_dmesg]
dmesg = ["Linux version 6.18", "Found initrd at"]
and as JSON file
{
"TC_BOARDNAME.generic_lnx_test_dmesg": {
"dmesg": ["Linux version 6.18", "Found initrd at"]
}
}
The class GenericBoardConfig in tbottest/boardgeneric.py
holds what belongs to the board itself (tmpdir, shelltype). Its
instance cfggeneric is the cfg the generic testcases in
tbottest.tc.generic_board use. They read their keys when they
run, with cfg.get_config(), cfg.get_config_int(),
cfg.get_config_bool() and cfg.get_config_literal(), so they find
their own section. Testcases of your own do the same:
from tbottest.boardgeneric import cfggeneric
from tbottest.tc.generictestdef import tc_config
@tbot.testcase
@tc_config
def my_testcase() -> None:
count = cfggeneric.get_config_int("count", "1")
common settings
common settings for your board.
key |
description |
default |
example |
|---|---|---|---|
tmpdir |
path to place on board, which could be used for temporary data testcases need. |
/tmp |
/tmp/tbot |
death_strings |
array of strings, which should not ocur in stream |
[] |
[‘Kernel panic’] |
u-boot settings
settings needed for U-Boot testcases.
key |
description |
default |
example |
|---|---|---|---|
uboot_boot_timeout |
config boot_timeout, set None if None |
90 |
None |
uboot_autoboot_keys |
string with which U-Boot boot is interrupted. It is possible to set also a bytearray, see the table below |
None |
SPACE |
uboot_autoboot_prompt |
regular expression of the U-Boot autoboot prompt, None if U-Boot prints none |
autoboot:s{0,5}d{0,3}s{0,3}.{0,80} |
None |
uboot_autoboot_timeout |
UBootAutobootInterceptSimple timeout for waiting for U-Boot prompt |
0.1 |
0.05 |
uboot_has_retcode |
tbot reads the return code of every U-Boot command with echo $?, which only the hush parser supports. Set to False for a U-Boot without hush: exec() then skips that query and reports 0, so exec0() cannot detect a failing command |
True |
False |
rescueimage |
name of rescueimage |
None |
rescueimage-fit.itb |
qspiheader |
name of qspi header |
None |
qspiheader.bin |
splimage |
name of spl image |
None |
SPL |
fb_res_setup |
u-boot commands for setting up rescue image boot with fastboot and uuu tool |
None |
run ramargs addcon addmtd addopt |
fb_res_boot |
u-boot command for booting rescue image with fastboot and uuu tool |
None |
bootm 94000000 |
fb_cmd |
fastboot init command |
None |
fastboot usb 0 |
ub_env |
list dict of u-boot environment variables which get set after login into u-boot, always, before the ub_env_<name> groups. An entry with “flag” is set only with that tbot flag, see JSON configuration and expressions |
[] |
[{“name”:”optargs”, “val”:”earlycon clk_ignore_unused”}] |
ub_env_<name> |
a group of u-boot environment variables, same format as ub_env, set after ub_env when selected with the tbot flag ub_env (all groups without the flag), see ub_env groups |
None |
ub_env_setip = [{“name”:”ipaddr”, “val”:”192.168.3.20”}] |
ub_env_depends |
dictionary group name to the list of groups it needs; a selected group pulls them in, and they are set before it |
{} |
{“nfsboot”: [“setip”]} |
ub_env_bootcmd |
dictionary boot command to the list of groups it needs; the tbot flag bootcmd:<cmd> selects them, see ub_env groups |
{} |
{“net_fit”: [“fitboot”]} |
ub_env groups
Besides ub_env, which is always set, the board ini can hold groups
ub_env_<name> of U-Boot environment variables.
The tbot flag ub_env:<group>[,<group>...] selects the groups to set,
for example only the network settings, so the default environment of
U-Boot stays as it is otherwise. Without the flag all groups are set, as
if they were one ub_env. ub_env:none sets only ub_env.
ub_env_depends names the groups a group depends on. An unknown group,
in the flag or in ub_env_depends, and a cycle in the dependencies
stop tbot with an error that lists the known groups. Group names are
lower case, as configparser stores keys.
ub_env = [{"name":"console", "val":"ttyCPM0,115200"}]
ub_env_setip = [{"name":"serverip", "val":"192.168.3.1"}, \
{"name":"ipaddr", "val":"192.168.3.20"}]
ub_env_fitboot = [{"name":"load_fit", "val":"tftp 1000000 fitImage"}, \
{"name":"net_fit", "val":"run load_fit; bootm 1000000"}]
ub_env_depends = {"fitboot": ["setip"]}
With these, -f ub_env:setip sets console, serverip and
ipaddr; -f ub_env:fitboot sets console, then setip, then
fitboot.
ub_env_bootcmd names the groups a boot command needs, so the tbot
flag bootcmd:<cmd> selects them by itself:
ub_env_bootcmd = {"net_fit": ["fitboot"]}
-f bootcmd:net_fit then sets ub_env, setip and fitboot,
without a flag ub_env. With ub_env:<group> as well, both are set;
ub_env:none sets only ub_env, also with bootcmd. A boot
command that ub_env_bootcmd does not name leaves the selection as it
is: the groups of ub_env:<group>, or all of them.
configuration string |
sended bytes to console |
|---|---|
K |
x4b |
SPACE |
x03 |
bytearray:1b1b |
x1bx1b |
linux settings
settings needed for linux testcases.
key |
description |
default |
example |
|---|---|---|---|
linux_user |
username for linux login. Set to empty (linux_user = ) to just send Enter instead of a username, e.g. for boards that already auto-login |
root |
root |
linux_password |
password for linux login, None for no password required |
None |
None |
linux_login_prompt |
prompt that indicates tbot should send the username. Set this to match your board’s shell prompt if it logs in automatically and never shows a real login prompt. Matched as regex with optional trailing whitespace, no need to (and can’t, ini strips it) include a trailing space |
login: |
root@foobar:~# |
linux_login_delay |
login delay in seconds |
5 |
1 |
linux_boot_timeout |
Maximum time for Linux to reach the login prompt. |
None |
30 |
linux_init_timeout |
If not None, timeout in seconds after ethernetconfig |
None |
2.0 |
linux_netcmd |
command the ethernet setup after login uses: auto takes ip if the board has it (checked once with cmd_get_version(“ip”) of tbot), else ifconfig; ip or ifconfig always take that one. The flag useifconfig takes ifconfig in any case |
auto |
ifconfig |
cmd_versions |
preset of cmd_get_version() for the board, see command versions |
None |
{“top”: “procps-ng:4.0.6”, “devmem2”: “notfound”} |
linux_init |
list of commands send after login. mode = exec or exec0 |
[] |
[{“mode”:”exec0”, “cmd”:”echo Hallo”}] |
testdir |
directory on the board for what testcases put there; in the root filesystem if a testcase puts files there through an NFS root |
/run/tbot-testdata/tbottests |
/home/root/tbottests |
shelltype |
linux login shell type (bash|ash) |
ash |
bash |
linux_plain_prompt |
True gives the interactive linux shell a plain <name>> prompt, without the color escapes and the directory that an old busybox ash prints literally (tbot’s interactive_plain_prompt) |
False |
True |
linux_safe_init_prompt |
True reads the prompt while tbot sets up the linux shell with read_until_prompt_safe(), which sends an empty line when kernel messages tear the prompt apart (tbot’s safe_init_prompt) |
True |
False |
beep |
list of dictionary of commands for beep command |
[] |
[{“freq”: “440”, “length”:”1000”}] |
cyclictestmaxvalue |
maximum allowed value from stress-ng ‘Max’ colum |
100 |
cyclictestmaxvalue = 100 |
dmesg |
list of strings, which should be in dmesg output |
[] |
dmesg = [“OF: fdt: Machine model:”, “gpio-193 (eeprom-wc): hogged as output/low”,] |
dmesg_false |
list of strings, which should be not in dmesg output |
[] |
dmesg_false = [“crash”] |
iperf |
list of dictionary for iperf test |
[] |
iperf = [{“intervall”:”1”,”minval”:”290000000”,”cycles”:”30”}] |
leds |
list of dictionary for checking leds |
[] |
leds = [{“path”:”/sys/class/leds/led-orange”, “bootval”:”0”, “onval”:”1”},] |
lnx_commands |
list of dictionary for checking linux commands |
[] |
lnx_commands = [{“cmd”:”<your linux command>”, “val”:”<string which is in output of command> or undef”},] |
network_iperf_intervall |
iperf intervall |
1 |
network_iperf_intervall = 1 |
network_iperf_minval |
iperf minimum network throughput |
1 |
network_iperf_minval = 9000000 |
network_iperf_cylces |
iperf cycles |
1 |
network_iperf_cycles = 30 |
nvramdev |
nvram device |
6 |
nvramdev = 6 |
nvramcomp |
compatibility string of nvram device |
microchip,48l640 |
nvramcomp = ‘microchip,48l640’ |
nvramsz |
size of nvram device |
8192 |
nvramsz = 8192 |
ping |
list of dict for ping config. |
[] |
ping = [{“ip”:”${default:serverip}”,”retry”:”10”}] |
regdump |
list of dict for generic regdump |
[] |
regdump = [{“address”:”0x30340004”}, {“address”:”0x30330070”}] |
rs485labdev |
path to device |
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0PI210-if00-port0 |
rs485labdev = “/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0PI210-if00-port0” |
rs485baud |
baudrate used for test |
115200 |
rs485baud = “115200” |
rs485boarddev |
list of strings, each string contains a path to device which used in test |
[“/dev/ttymxc2”] |
rs485boarddev = [“/dev/ttymxc2”] |
rs485lengths |
list of strings. Each string is a length of data send over rs485 line |
[“20”, “100”, “1024”] |
rs485lengths = [“20”, “100”, “1024”] |
sensors |
list of dictionary for checking temperature sensors |
[] |
sensors = [{“path”:”/sys/class/hwmon/hwmon0”, “name”:”tmp102”, “tmpvalues”:[{“valname”:”temp1_input”, “min”:”0”, “max”:”100000”}]},] |
mtd_parts |
list of dictionary for MTD parts definition |
[] |
mtd_parts = [{“name”:”SPL”, “size”:”10000”},] |
ub_mtd_delete |
list of strings with MTD names which are allowed to delete |
[] |
ub_mtd_delete = [“SPL”, “uboot”] |
ssh_keyfile |
ssh setup: authentication using private key file ssh_keyfile |
None |
/home/{user}/.ssh/id_rsa |
ssh_password |
ssh setup: set password for password ssh login |
None |
foobar |
command versions
The output of a command depends on where it comes from. top of
busybox prints other columns than top of procps-ng, busybox has
devmem where a full system has devmem2. tbot finds this out with
cmd_get_version(cmd) of a linux machine, once per machine, and returns
a CmdVersion whose str() is <implementation>:<version>, for
example busybox:1.37.0, procps-ng:4.0.6 or notfound.
Testcases of tbottest use it instead of checks of their own (process
measurement with top and ps, lx_devmem2_get, iperf, lnx_netcmd).
Key cmd_versions presets the answers, so tbot does not have to find
them out on every run. It goes into section [LABHOST] (or
[LABHOST_<labname>]) of tbot.ini for the lab host, into [BUILDHOST]
(or [BUILDHOST_<name>]) of tbot.ini for the build host and into
[TC] (or [TC_<boardname>]) of the board ini for the board. A command that
is not in it is found out as before. A value a testcase sets with
cmd_versions_set() wins over the configuration.
cmd_versions = {
"top": "procps-ng:4.0.6",
"devmem": "busybox:1.37.0",
"devmem2": "notfound",
}
One command per line works, as configparser takes every line indented
deeper than the key as continuation of the value. In [TC] of the
board ini template the keys are indented by four spaces, so the commands
need eight. In a JSON file the value is an object:
{
"TC": {
"cmd_versions": {"top": "procps-ng:4.0.6", "devmem": "busybox:1.37.0"}
}
}
The testcase tbottest.tc.generic_board.generic_cmd_versions()
finds out the commands tbottest uses on the lab host, the build host (if
tbot.ini has a [BUILDHOST] section) and the board and logs the line
for each, ready to copy into the configuration. Run it again when the root
filesystem, the lab host or the build host changes.
cmd_get_version(cmd, autoinstall=True) installs a missing command on
Debian and Ubuntu (apt-get) and on Fedora (dnf), with sudo unless logged
in as root. A system without a known package manager, like a root
filesystem built with Yocto, keeps notfound. The tbot flag
cmd_versions_install makes generic_cmd_versions install missing
commands.
configuration and package installation for LinuxShell.cmd_get_version() of tbot
tbot finds out once per machine which implementation and version a command has (busybox, procps-ng, …). The generic machines of tbottest add two things:
key
cmd_versionsin the ini file presets the results, so tbot does not have to find them out on every run (section [LABHOST] or [LABHOST_<labname>] in tbot.ini for the lab host, [TC] or [TC_<boardname>] in <boardname>.ini for the board). The testcasetbottest.tc.common.lnx_cmd_versions()prints such a line,tbottest.tc.generic_board.generic_cmd_versions()for the lab host and the board.cmd_get_version(cmd, autoinstall=True)installs a missing command on Debian, Ubuntu (apt-get) and Fedora (dnf). A Yocto root filesystem has no package manager, there the command staysnotfound.
- tbottest.cmdversions.cmd_versions_to_config(versions: Dict[str, str], keyindent: str = '') str[source]
the ini key
cmd_versionsfor versions, one command per lineconfigparser takes a line as continuation of the value if it is indented deeper than the key, so the commands are indented by four spaces more than the key.
- Parameters:
versions – dictionary command -> version string
keyindent – indentation of the key in its section, e.g. four spaces in [TC] of the board ini template
- Returns:
the lines, starting with
cmd_versions = {
- tbottest.cmdversions.cmd_versions_from_config(value: str | None) Dict[str, str][source]
convert the value of the ini key
cmd_versionsinto a dictionary- Parameters:
value – python dictionary as string, for example
{"top": "busybox:1.37.0", "ps": "procps-ng:4.0.6"}; None or an empty string give an empty dictionary- Returns:
dictionary command -> version string
- tbottest.cmdversions.os_release_family(osrelease: str) str[source]
which package manager a system has, from its /etc/os-release
- Parameters:
osrelease – content of /etc/os-release
- Returns:
“debian” (Debian, Ubuntu and others with ID_LIKE=debian), “fedora” (Fedora and ID_LIKE=fedora) or “” for any other system
- tbottest.cmdversions.install_commands(family: str, cmd: str) List[List[str]][source]
the commands that install the package of cmd, to be tried one after the other until one succeeds
dnf takes a path as file provide (man dnf5-specs, “File Provides matching”), so Fedora needs no table.
- Parameters:
family – result of
os_release_family()cmd – the missing command
- Returns:
list of argument lists, empty if family is not supported
- tbottest.cmdversions.install_package(lnx, cmd: str) bool[source]
install the package that provides cmd on lnx
- Parameters:
lnx – linux machine
cmd – the missing command
- Returns:
True if an install command succeeded
- class tbottest.cmdversions.CmdVersionsMixin[source]
Bases:
objectmixin for the linux machines of tbottest, before the tbot shell class
cmd_versions_configis the value of the ini keycmd_versions; it is set as preset of cmd_get_version() before the first call of cmd_get_version() or cmd_versions_set(), so a value a testcase sets wins over the ini file.
swupdate settings
settings needed for swupdate testcases.
key |
description |
default |
example |
|---|---|---|---|
swuethdevice |
device which is used for getting ethernetconfiguration on lab host |
eth0 |
eth0 |
swuimage |
Name of swu image name which get installed on board |
mandatory, no fallback |
swu-image.swu |
kas settings
settings needed for yocto build with kas tool.
key |
description |
default |
example |
|---|---|---|---|
kas |
dictionary with values need for class KAS, see |
mandatory, no default |
see: tbottest/tbotconfig/BOARDNAME.ini |
kas_check_files |
list of files, which must exist after building |
[] |
[‘tmp/deploy/images/wandboard/SPL’] |
kas_results |
list of files, which get copied from build host to lab host for later use. Basepath is machine directory in tmp/deploy/images |
[] |
[‘SPL’] |
Inside the kas dictionary, kas_mounts adds directories of the build host to
the kas container, each as host:container or host:container:options, for
example a directory with build helper scripts. See
tbottest.tc.kas.KAS.
With tbot flag kaskeepconfig, kas keeps the repo checkouts and build/conf as they are (kas –keep-config-unchanged): tbot does no kas checkout and passes the option to kas shell and kas build. It needs one earlier run without the flag, which set the build tree up.
argumentfiles
it is convenient to collect tbot arguments in argumentsfile. As you will have a lot of tbot arguments. We start in this example with a base “argsBOARDNAME” file, which than other files include.
Note
You can use shell variables also in argumentfiles!
newtbot_starter.py sets TBOT_STARTTIME to the start time of the
run, YYYYMMDD-HHMMSS, if it is not set already. With it, every run
writes its log to a file of its own, here in log/ below the directory
tbot is started from, which has to exist:
--json-log-stream
log/${TBOT_STARTTIME}.log
The following example uses piccom for accessing serial console and sispmctl for boards power control.
If you have another setup, adapt this “base” argument file accordingly.
For example, if you want to use kermit for accessing console, remove the tbot flag piccom (as kermit is default).
If you want to use Tinkerforge for controlling boards power, add flag “tinkerforge”
$ cat tbotconfig/BOARDNAME/args/argsBOARDNAME
@tbotconfig/BOARDNAME/args/argsbase
-fpicocom
Note
argsbase is a simple copy from tbottest/tbotconfig/BOARDNAME/argsfiles/argsbase
With executing tbot on lab host, you do not need to ssh to lab host, so use local flag.
$ cat config/BOARDNAME/args/argsBOARDNAME-local
@config/BOARDNAME/args/argsBOARDNAME
-flocal
If you do not want that tbot always initialize ethernet configuration on your lab host, use
$ cat config/BOARDNAME/args/argsBOARDNAME-local-noeth
@config/BOARDNAME/args/argsBOARDNAME-local
-fnoethinit
If you want to login to a board, which is already on and runs linux
$ cat config/BOARDNAME/args/argsBOARDNAME-local-noeth-on
@config/BOARDNAME/args/argsBOARDNAME-local-noeth
-falways-on
-fnouboot
-fnopoweroff
Note
start tbot with flag “always-on” and tbot will not poweroff the board when ending, so if you have bootet into linux, and logout, linux will remain and tbot can logon again!
This helps a lot when developing testcases!
Argumentfile for ssh login
If you want to login per ssh into an already running linux on the board
$ cat config/BOARDNAME/args/argsBOARDNAME-local-noeth-on
@config/BOARDNAME/args/argsBOARDNAME-local-noeth
-fssh
And last but not least, if you have an imx6 based board and want to load SPL/U-Boot with tbot onto it, start tbot with:
$ cat config/BOARDNAME/args/argsBOARDNAME-local-uuu
@config/BOARDNAME/args/argsBOARDNAME-local
-fuuuloader
tbot call example
$ ./newtbot_starter.py @tbotconfig/BOARDNAME/args/argsBOARDNAME-asus-kirkstone-nfs -f kas tbottest.inter.uboot
tbot starting ...
├─TBOT.FLAGS {'boardfile:tbotconfig/BOARDNAME/BOARDNAME.ini', 'useifconfig', 'bootcmd:tftp_nfs', 'noboardethinit', 'noethinit', 'kas', 'do_power', 'kaslayerbranch:kirkstone', 'inifile:tbotconfig/BOARDNAME/tbot.ini', 'bootmode:emmc', 'picocom'}
├─boardname now BOARDNAME
├─Using kas file kas-denx-withdldir.yml
├─Calling uboot ...
│ ├─[local] ssh -o BatchMode=yes -i /home/pi/.ssh/id_rsa -p 22 pi@tbotlab
│ ├─set bootmode bootmode:emmc
│ ├─[lab8] test -d /sys/class/gpio/gpio14
│ ├─[lab8] cat /sys/class/gpio/gpio14/direction
│ │ ## out
│ ├─[lab8] printf %s 1 >/sys/class/gpio/gpio14/value
│ ├─[local] ssh -o BatchMode=yes -i /home/pi/.ssh/id_rsa -p 22 pi@BOARDNAMElab
│ ├─set bootmode bootmode:emmc
│ ├─[lab8] test -d /sys/class/gpio/gpio14
│ ├─[lab8] cat /sys/class/gpio/gpio14/direction
│ │ ## out
│ ├─[lab8] printf %s 1 >/sys/class/gpio/gpio14/value
│ ├─[lab8] picocom -r -b 115200 -l /dev/serial/by-id/usb-FTDI_C232HM-EDHSL-0_FT57MR3U-if00-port0
│ ├─POWERON (board-control-full)
│ ├─[lab8] sispmctl -D 01:01:4f:09:5b -o 1
│ │ ## Accessing Gembird #0 USB device 012
│ │ ## Switched outlet 1 on
│ ├─UBOOT (BOARDNAME-uboot)
│ │ <> picocom v3.1
│ │ <>
│ │ <> port is : /dev/serial/by-id/usb-FTDI_C232HM-EDHSL-0_FT57MR3U-if00-port0
│ │ <> flowcontrol : none
│ │ <> baudrate is : 115200
│ │ <> parity is : none
│ │ <> databits are : 8
│ │ <> stopbits are : 1
│ │ <> escape is : C-a
│ │ <> local echo is : no
│ │ <> noinit is : no
│ │ <> noreset is : yes
│ │ <> hangup is : no
│ │ <> nolock is : yes
│ │ <> send_cmd is : sz -vv
│ │ <> receive_cmd is : rz -vv -E
│ │ <> imap is :
│ │ <> omap is :
│ │ <> emap is : crcrlf,delbs,
│ │ <> logfile is : none
│ │ <> initstring : none
│ │ <> exit_after is : not set
│ │ <> exit is : no
│ │ <>
│ │ <> Type [C-a] [C-h] to see available commands
│ │ <> Terminal ready
│ │ <>
│ │ <> U-Boot SPL 2023.04 (Apr 03 2023 - 20:38:50 +0000)
│ │ <> Trying to boot from MMC1
│ │ <>
│ │ <>
│ │ <> U-Boot 2023.04 (Apr 03 2023 - 20:38:50 +0000)
│ │ <>
│ │ <> CPU : AM335X-GP rev 2.1
│ │ <> Model: XXX
│ │ <> DRAM: 512 MiB
│ │ <> Core: 172 devices, 20 uclasses, devicetree: separate
│ │ <> MMC: OMAP SD/MMC: 0
│ │ <> Loading Environment from MMC... OK
│ │ <> In: serial@0
│ │ <> Out: serial@0
│ │ <> Err: serial@0
│ │ <> Net: eth2: ethernet@4a100000
│ │ <> Press SPACE to abort autoboot in 2 seconds
│ │ <> => <INTERRUPT>
│ │ <> =>
│ ├─[BOARDNAME-uboot] setenv serverip 192.168.3.1
│ ├─[BOARDNAME-uboot] printenv serverip
│ │ ## serverip=192.168.3.1
[...]
│ ├─[BOARDNAME-uboot] printenv optargs
│ │ ## optargs=consoleblank=0 vt.global_cursor_default=0 lpj=2988032 quiet rauc.slot=A
│ ├─Entering interactive shell...
│ ├─Press CTRL+] three times within 1 second to exit.
=>
tbot flags
The generic lab and board approach defines some tbot flags, so tbot can handle different usage challenges. It is recommended to collect arguments in so called argumentsfiles, else you are lost in tbot flags…
tbot flag |
Description |
|---|---|
always-on |
board is already on, log into linux |
boardfile |
format boardfile:<path>, the board configuration, an ini file or, if the name ends in .json, a JSON file, relative to the tbotconfig directory or absolute; default the BOARDNAME.ini template |
boardname |
format boardname:<name>, name of the board, used when boardspecific.py does not define board_set_boardname() |
bootcmd |
format bootcmd:<real bootcmd>, example bootcmd:net_nfs will execute “run net_nfs” |
buildername |
format buildername:<name>, select the used build host, section BUILDHOST_<name> in tbot.ini; buildername:local builds on the host tbot runs on |
cmd_versions_install |
generic_cmd_versions installs missing commands where the system can (Debian, Ubuntu, Fedora), see command versions |
cmdtimestamp |
prefix each command log line with a H:M:S timestamp, e.g. [boardname 07:22:26] |
config_json_dir |
format config_json_dir:<dir>, where generic_config_to_json writes tbot.json and <boardname>.json, default config-json |
config_json_resolved |
generic_config_to_json writes the values resolved, as tbot reads them |
dfuutilloader |
load SPL/U-Boot with dfu-util tool |
do_power |
tbot handles boards power |
docker |
if you need to login to a docker container with proxyjump |
emmc |
u-boot bootcmd “run boot_emmc” (deprecated, use flag bootcmd) |
enterinitramfs |
enter initramfs, add enterinitramfs to miscargs (deprecated, use set_ub_board_specific) |
gpiopower |
use a gpio pin for boards power control |
ignore_loglevel |
add ignore_loglevel to miscargs (deprecated, use set_ub_board_specific) |
inifile |
format inifile:<path>, the lab configuration, an ini file or, if the name ends in .json, a JSON file, relative to the tbotconfig directory or absolute; default the tbot.ini template |
kas |
u-boot bootcmd “run bootcmdkas” |
kaskeepconfig |
keep the repo checkouts and build/conf of the kas build as they are, like kas –keep-config-unchanged |
kasskipcheckout |
skip the kas checkout step |
lablockid |
format lablockid:<yourlockid>, the lock id for board locking |
labname |
format labname:<name of lab host>, select the used lab host (configure in tbot.ini with LABHOST_<name> section) |
lauterbachloader |
load SPL/U-Boot with Lauterbach TRACE32 |
lauterbachusesshmachine |
with lauterbachloader, run TRACE32 on the SSH machine of tbot.ini instead of the lab host |
linux_no_cmd_after_login |
set nothing after linux login (beside disable clutter) |
local |
enable if labhost and tbot host are the same (use SubprocessConnector) |
no-bootfit |
with ssh, read the board’s IP address from “ip route get 1” output that has two spaces before “src” |
noboardethinit |
do no board ethinit in linux after login |
nobootcon |
set console to silent (deprecated, use set_ub_board_specific) |
noethinit |
do not set up the lab host’s ethernet devices for the board (lab init) |
nopoweroff |
do not power the board off |
nouboot |
boot into linux without U-Boot interaction; with ssh also without a login on the console |
outside |
if lab host is only reachable with proxyjump |
panic |
add death string “Kernel panic” |
picocom |
use picocom for serial console |
poweroffonstart |
if set, power off board before powering on |
poweron_cmds |
format poweron_cmds:<name>, select an entry of the dictionary poweron_cmds in the BDI2000 section of tbot.ini; poweron_cmds:None runs no BDI2000 commands after power on |
powershellscript |
use a shellscript for boards power control |
rescue |
boot rescue system (deprecated, use flag bootcmd) |
rescuetftp |
boot rescue system, rescue image loaded through tftp (deprecated, use flag bootcmd) |
rescueuuu |
load the bootloader with the uuu tool and boot into the rescue image loaded with fastboot |
scriptcom |
use a script for serial console |
sdcard |
u-boot bootcmd “run boot_mmc” (deprecated, use flag bootcmd) |
seggerloader |
use segger debugger for breathing life into board |
set-ethconfig |
setup ip config in U-Boot |
ssh |
login to linux console through ssh (only possible if board already on and in linux) |
telnet |
use telnet for serial console |
tftpfit |
u-boot bootcmd “run tftp_mmc” (deprecated, use flag bootcmd) |
tinkerforge |
use tinkerforge for boards power control |
tmpfilepath |
format tmpfilepath:<directory>, where tbot writes its copies of tbot.ini and the board ini; default next to them; ini files only |
ub_env |
format ub_env:<group>[,<group>…], set ub_env and only these ub_env_<group> groups of the board ini, with the groups they depend on (ub_env_depends) and those ub_env_bootcmd names for the flag bootcmd; ub_env:none sets none of the groups; default the groups of the boot command, else all groups, see ub_env groups |
uboot_no_env_set |
do not set any U-Boot Environment after U-Boot login |
usbloader |
load SPL/U-Boot with imx_usb_loader |
useifconfig |
use ifconfig instead of ip on every machine, also over linux_netcmd of the board ini |
uuuloader |
load SPL/U-Boot with uuu tool from NXP |
xmodemloader |
load SPL/U-Boot with sb tool (xmodem/ymodem) |