summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/hil/hil_pi4.json11
-rw-r--r--test/hil/hil_test.py229
2 files changed, 163 insertions, 77 deletions
diff --git a/test/hil/hil_pi4.json b/test/hil/hil_pi4.json
new file mode 100644
index 000000000..d613f8da8
--- /dev/null
+++ b/test/hil/hil_pi4.json
@@ -0,0 +1,11 @@
+{
+ "boards": [
+ {
+ "name": "raspberry_pi_pico",
+ "uid": "E6614C311B764A37",
+ "debugger": "openocd",
+ "debugger_sn": "E6614103E72C1D2F",
+ "debugger_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
+ }
+ ]
+}
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index 6bcde36c6..b307a45f6 100644
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -31,59 +31,123 @@ import time
import serial
import subprocess
import json
+import glob
+ENUM_TIMEOUT = 10
-def get_serial_dev(id, product, ifnum):
- # get usb serial by id
- return f'/dev/serial/by-id/usb-TinyUSB_{product}_{id}-if{ifnum:02d}'
+# get usb serial by id
+def get_serial_dev(id, vendor_str, product_str, ifnum):
+ if vendor_str and product_str:
+ # known vendor and product
+ return f'/dev/serial/by-id/usb-{vendor_str}_{product_str}_{id}-if{ifnum:02d}'
+ else:
+ # just use id: mostly for cp210x/ftdi debugger
+ pattern = f'/dev/serial/by-id/usb-*_{id}-if{ifnum:02d}*'
+ port_list = glob.glob(pattern)
+ return port_list[0]
-def get_disk_dev(id, lun):
+
+# Currently not used, left as reference
+def get_disk_dev(id, vendor_str, lun):
# get usb disk by id
- return f'/dev/disk/by-id/usb-TinyUSB_Mass_Storage_{id}-0:{lun}'
+ return f'/dev/disk/by-id/usb-{vendor_str}_Mass_Storage_{id}-0:{lun}'
+
+
+def get_hid_dev(id, vendor_str, product_str, event):
+ return f'/dev/input/by-id/usb-{vendor_str}_{product_str}_{id}-{event}'
+
+
+def open_serial_dev(port):
+ timeout = ENUM_TIMEOUT
+ ser = None
+ while timeout:
+ if os.path.exists(port):
+ try:
+ # slight delay since kernel may occupy the port briefly
+ time.sleep(0.5)
+ timeout = timeout - 0.5
+ ser = serial.Serial(port, timeout=1)
+ break
+ except serial.SerialException:
+ pass
+ time.sleep(0.5)
+ timeout = timeout - 0.5
+ assert timeout, 'Device not available or Cannot open port'
+ return ser
-def get_hid_dev(id, product, event):
- return f'/dev/input/by-id/usb-TinyUSB_{product}_{id}-{event}'
+def read_disk_file(id, fname):
+ # on different self-hosted, the mount point is different
+ file_list = [
+ f'/media/blkUSB_{id[-8:]}.02/{fname}',
+ f'/media/{os.getenv("USER")}/TinyUSB MSC/{fname}'
+ ]
+ timeout = ENUM_TIMEOUT
+ while timeout:
+ for file in file_list:
+ if os.path.isfile(file):
+ with open(file, 'rb') as f:
+ data = f.read()
+ return data
+
+ time.sleep(1)
+ timeout = timeout - 1
+
+ assert timeout, 'Device not available'
+ return None
-def flash_jlink(sn, dev, firmware):
+# -------------------------------------------------------------
+# Flash with debugger
+# -------------------------------------------------------------
+def flash_jlink(board, firmware):
script = ['halt', 'r', f'loadfile {firmware}', 'r', 'go', 'exit']
- f = open('flash.jlink', 'w')
- f.writelines(f'{s}\n' for s in script)
- f.close()
- ret = subprocess.run(f'JLinkExe -USB {sn} -device {dev} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink',
- shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- stdout = ret.stdout.decode()
+ with open('flash.jlink', 'w') as f:
+ f.writelines(f'{s}\n' for s in script)
+ ret = subprocess.run(
+ f'JLinkExe -USB {board["debugger_sn"]} -device {board["cpu"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink',
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
os.remove('flash.jlink')
- assert ret.returncode == 0, 'Flash failed\n' + stdout
+ return ret
+
+
+def flash_openocd(board, firmware):
+ ret = subprocess.run(
+ f'openocd -c "adapter serial {board["debugger_sn"]}" {board["debugger_args"]} -c "program {firmware} reset exit"',
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ return ret
+
+def flash_esptool(board, firmware):
+ port = get_serial_dev(board["debugger_sn"], None, None, 0)
+ dir = os.path.dirname(firmware)
+ with open(f'{dir}/config.env') as f:
+ IDF_TARGET = json.load(f)['IDF_TARGET']
+ with open(f'{dir}/flash_args') as f:
+ flash_args = f.read().strip().replace('\n', ' ')
+ command = (f'esptool.py --chip {IDF_TARGET} -p {port} {board["debugger_args"]} '
+ f'--before=default_reset --after=hard_reset write_flash {flash_args}')
+ ret = subprocess.run(command, shell=True, cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ return ret
+
+# -------------------------------------------------------------
+# Tests
+# -------------------------------------------------------------
def test_board_test(id):
# Dummy test
pass
-def test_cdc_dual_ports(id):
- port1 = get_serial_dev(id, "TinyUSB_Device", 0)
- port2 = get_serial_dev(id, "TinyUSB_Device", 2)
- # Wait device enum
- timeout = 10
- while timeout:
- if os.path.exists(port1) and os.path.exists(port2):
- break
- time.sleep(1)
- timeout = timeout - 1
+def test_cdc_dual_ports(id):
+ port1 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0)
+ port2 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 2)
- assert timeout, 'Device not available'
+ ser1 = open_serial_dev(port1)
+ ser2 = open_serial_dev(port2)
# Echo test
- ser1 = serial.Serial(port1)
- ser2 = serial.Serial(port2)
-
- ser1.timeout = 1
- ser2.timeout = 1
-
str1 = b"test_no1"
ser1.write(str1)
ser1.flush()
@@ -98,32 +162,17 @@ def test_cdc_dual_ports(id):
def test_cdc_msc(id):
- port = get_serial_dev(id, "TinyUSB_Device", 0)
- file = f'/media/blkUSB_{id[-8:]}.02/README.TXT'
- # Wait device enum
- timeout = 10
- while timeout:
- if os.path.exists(port) and os.path.isfile(file):
- break
- time.sleep(1)
- timeout = timeout - 1
-
- assert timeout, 'Device not available'
-
# Echo test
- ser1 = serial.Serial(port)
-
- ser1.timeout = 1
+ port = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0)
+ ser = open_serial_dev(port)
str = b"test_str"
- ser1.write(str)
- ser1.flush()
- assert ser1.read(100) == str, 'CDC wrong data'
+ ser.write(str)
+ ser.flush()
+ assert ser.read(100) == str, 'CDC wrong data'
# Block test
- f = open(file, 'rb')
- data = f.read()
-
+ data = read_disk_file(id, 'README.TXT')
readme = \
b"This is tinyusb's MassStorage Class demo.\r\n\r\n\
If you find any bugs or get any questions, feel free to file an\r\n\
@@ -131,12 +180,17 @@ issue at github.com/hathach/tinyusb"
assert data == readme, 'MSC wrong data'
+
+def test_cdc_msc_freertos(id):
+ test_cdc_msc(id)
+
+
def test_dfu(id):
# Wait device enum
- timeout = 10
+ timeout = ENUM_TIMEOUT
while timeout:
ret = subprocess.run(f'dfu-util -l',
- shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout = ret.stdout.decode()
if f'serial="{id}"' in stdout and 'Found DFU: [cafe:4000]' in stdout:
break
@@ -161,10 +215,10 @@ def test_dfu(id):
assert ret.returncode == 0, 'Upload failed'
with open('dfu0') as f:
- assert 'Hello world from TinyUSB DFU! - Partition 0' in f.read(), 'Wrong uploaded data'
+ assert 'Hello world from TinyUSB DFU! - Partition 0' in f.read(), 'Wrong uploaded data'
with open('dfu1') as f:
- assert 'Hello world from TinyUSB DFU! - Partition 1' in f.read(), 'Wrong uploaded data'
+ assert 'Hello world from TinyUSB DFU! - Partition 1' in f.read(), 'Wrong uploaded data'
os.remove('dfu0')
os.remove('dfu1')
@@ -172,10 +226,10 @@ def test_dfu(id):
def test_dfu_runtime(id):
# Wait device enum
- timeout = 10
+ timeout = ENUM_TIMEOUT
while timeout:
ret = subprocess.run(f'dfu-util -l',
- shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout = ret.stdout.decode()
if f'serial="{id}"' in stdout and 'Found Runtime: [cafe:4000]' in stdout:
break
@@ -186,11 +240,11 @@ def test_dfu_runtime(id):
def test_hid_boot_interface(id):
- kbd = get_hid_dev(id, 'TinyUSB_Device', 'event-kbd')
- mouse1 = get_hid_dev(id, 'TinyUSB_Device', 'if01-event-mouse')
- mouse2 = get_hid_dev(id, 'TinyUSB_Device', 'if01-mouse')
+ kbd = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'event-kbd')
+ mouse1 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-event-mouse')
+ mouse2 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse')
# Wait device enum
- timeout = 10
+ timeout = ENUM_TIMEOUT
while timeout:
if os.path.exists(kbd) and os.path.exists(mouse1) and os.path.exists(mouse2):
break
@@ -200,6 +254,14 @@ def test_hid_boot_interface(id):
assert timeout, 'Device not available'
+def test_hid_composite_freertos(id):
+ # TODO implement later
+ pass
+
+
+# -------------------------------------------------------------
+# Main
+# -------------------------------------------------------------
if __name__ == '__main__':
if len(sys.argv) != 2:
print('Usage:')
@@ -209,13 +271,14 @@ if __name__ == '__main__':
with open(f'{os.path.dirname(__file__)}/{sys.argv[1]}') as f:
config = json.load(f)
- # all possible tests, board_test is last to disable board's usb
+ # all possible tests
all_tests = [
- 'cdc_dual_ports', 'cdc_msc', 'dfu', 'dfu_runtime', 'hid_boot_interface', 'board_test'
+ 'cdc_dual_ports', 'cdc_msc', 'dfu', 'dfu_runtime', 'hid_boot_interface',
]
for board in config['boards']:
print(f'Testing board:{board["name"]}')
+ debugger = board['debugger'].lower()
# default to all tests
if 'tests' in board:
@@ -223,6 +286,9 @@ if __name__ == '__main__':
else:
test_list = all_tests
+ # board_test is added last to disable board's usb
+ test_list.append('board_test')
+
# remove skip_tests
if 'tests_skip' in board:
for skip in board['tests_skip']:
@@ -230,21 +296,30 @@ if __name__ == '__main__':
test_list.remove(skip)
for test in test_list:
- mk_elf = f'examples/device/{test}/_build/{board["name"]}/{test}.elf'
- cmake_elf = f'cmake-build/cmake-build-{board["name"]}/device/{test}/{test}.elf'
- if os.path.isfile(cmake_elf):
- elf = cmake_elf
- elif os.path.isfile(mk_elf):
- elf = mk_elf
- else:
+ # cmake, make, download from artifacts
+ elf_list = [
+ f'cmake-build/cmake-build-{board["name"]}/device/{test}/{test}.elf',
+ f'examples/device/{test}/_build/{board["name"]}/{test}.elf',
+ f'{test}.elf'
+ ]
+
+ elf = None
+ for e in elf_list:
+ if os.path.isfile(e):
+ elf = e
+ break
+
+ if elf is None:
print(f'Cannot find firmware file for {test}')
sys.exit(-1)
- if board['debugger'].lower() == 'jlink':
- flash_jlink(board['debugger_sn'], board['cpu'], elf)
- else:
- # ToDo
- pass
print(f' {test} ...', end='')
+
+ # flash firmware
+ ret = locals()[f'flash_{debugger}'](board, elf)
+ assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode()
+
+ # run test
locals()[f'test_{test}'](board['uid'])
+
print('OK')