Skip to content

Commit 37158ed

Browse files
authored
Merge pull request #2367 from hathach/add-hil-s3
Add esp32s3 to hardware in the loop test
2 parents 4c80f5a + f5f087e commit 37158ed

File tree

7 files changed

+133
-68
lines changed

7 files changed

+133
-68
lines changed

.github/workflows/build_esp.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ jobs:
3333
- 'espressif_kaluga_1'
3434
# ESP32-S3
3535
- 'espressif_s3_devkitc'
36-
3736
steps:
3837
- name: Setup Python
3938
uses: actions/setup-python@v4
@@ -48,3 +47,51 @@ jobs:
4847

4948
- name: Build
5049
run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32.py ${{ matrix.board }}
50+
51+
- name: Upload Artifacts for Hardware Testing
52+
if: matrix.board == 'espressif_s3_devkitc' && github.repository_owner == 'hathach'
53+
uses: actions/upload-artifact@v3
54+
with:
55+
name: ${{ matrix.board }}
56+
path: |
57+
cmake-build/cmake-build-${{ matrix.board }}/*/*/bootloader/bootloader.bin
58+
cmake-build/cmake-build-${{ matrix.board }}/*/*/*.bin
59+
cmake-build/cmake-build-${{ matrix.board }}/*/*/partition_table/partition-table.bin
60+
cmake-build/cmake-build-${{ matrix.board }}/*/*/config.env
61+
cmake-build/cmake-build-${{ matrix.board }}/*/*/flash_args
62+
63+
# ---------------------------------------
64+
# Hardware in the loop (HIL)
65+
# Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json
66+
# ---------------------------------------
67+
hil-test:
68+
# run only with hathach's commit due to limited resource on RPI4
69+
if: github.repository_owner == 'hathach'
70+
needs: build-esp
71+
runs-on: [self-hosted, esp32s3, hardware-in-the-loop]
72+
strategy:
73+
fail-fast: false
74+
matrix:
75+
board:
76+
- 'espressif_s3_devkitc'
77+
steps:
78+
- name: Clean workspace
79+
run: |
80+
echo "Cleaning up previous run"
81+
rm -rf "${{ github.workspace }}"
82+
mkdir -p "${{ github.workspace }}"
83+
84+
- name: Checkout test/hil
85+
uses: actions/checkout@v3
86+
with:
87+
sparse-checkout: test/hil
88+
89+
- name: Download Artifacts
90+
uses: actions/download-artifact@v3
91+
with:
92+
name: ${{ matrix.board }}
93+
path: cmake-build/cmake-build-${{ matrix.board }}
94+
95+
- name: Test on actual hardware
96+
run: |
97+
python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json

.github/workflows/build_iar.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
# Alphabetical order
3333
# Note: bundle multiple families into a matrix since there is only one self-hosted instance can
3434
# run IAR build. Too many matrix can hurt due to setup/teardown overhead.
35-
- 'lpc43 stm32f0 stm32f1 stm32f4 stm32f7 stm32g0 stm32g4 stm32h7 stm32l4'
35+
- 'lpc43 stm32f0 stm32f1 stm32f7 stm32g0 stm32g4 stm32l4'
3636
steps:
3737
- name: Clean workspace
3838
run: |

.github/workflows/cmake_arm.yml

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -86,34 +86,28 @@ jobs:
8686
# for rp2040, there is no harm if defined for other families
8787
PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk
8888

89-
# Upload binaries for hardware test with self-hosted
90-
- name: Prepare rp2040 Artifacts
91-
if: contains(matrix.family, 'rp2040') && github.repository_owner == 'hathach'
92-
working-directory: ${{github.workspace}}/cmake-build/cmake-build-raspberry_pi_pico
93-
run: |
94-
find device/ -name "*.elf" -exec mv {} ../../ \;
95-
# find host/ -name "*.elf" -exec mv {} ../../ \;
96-
# find dual/ -name "*.elf" -exec mv {} ../../ \;
97-
98-
- name: Upload Artifacts for rp2040
89+
- name: Upload Artifacts for Hardware Testing
9990
if: contains(matrix.family,'rp2040') && github.repository_owner == 'hathach'
10091
uses: actions/upload-artifact@v3
10192
with:
102-
name: rp2040
93+
name: raspberry_pi_pico
10394
path: |
104-
*.elf
95+
cmake-build/cmake-build-raspberry_pi_pico/*/*/*.elf
10596
10697
# ---------------------------------------
10798
# Hardware in the loop (HIL)
108-
# Current self-hosted instance is running on an RPI4.
109-
# For attached hardware checkout hil_pi4.json
99+
# Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json
110100
# ---------------------------------------
111-
hw-rp2040-test:
101+
hil-test:
112102
# run only with hathach's commit due to limited resource on RPI4
113103
if: github.repository_owner == 'hathach'
114104
needs: build-arm
115105
runs-on: [self-hosted, rp2040, hardware-in-the-loop]
116-
106+
strategy:
107+
fail-fast: false
108+
matrix:
109+
board:
110+
- 'raspberry_pi_pico'
117111
steps:
118112
- name: Clean workspace
119113
run: |
@@ -126,11 +120,12 @@ jobs:
126120
with:
127121
sparse-checkout: test/hil
128122

129-
- name: Download rp2040 Artifacts
123+
- name: Download Artifacts
130124
uses: actions/download-artifact@v3
131125
with:
132-
name: rp2040
126+
name: ${{ matrix.board }}
127+
path: cmake-build/cmake-build-${{ matrix.board }}
133128

134-
- name: Test on actual hardware (hardware in the loop)
129+
- name: Test on actual hardware
135130
run: |
136-
python3 test/hil/hil_test.py hil_pi4.json
131+
python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json

hw/bsp/espressif/boards/family.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) {
158158

159159
void board_led_write(bool state) {
160160
#ifdef NEOPIXEL_PIN
161-
strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00);
161+
strip->set_pixel(strip, 0, state ? 0x08 : 0x00, 0x00, 0x00);
162162
strip->refresh(strip, 100);
163163
#endif
164164
}

test/hil/hil_hfp.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
{
44
"name": "stm32l412nucleo",
55
"uid": "41003B000E504E5457323020",
6-
"debugger": "jlink",
7-
"debugger_sn": "774470029",
8-
"cpu": "STM32L412KB"
6+
"flasher": "jlink",
7+
"flasher_sn": "774470029",
8+
"flasher_args": "-device STM32L412KB"
99
},
1010
{
1111
"name": "stm32f746disco",
1212
"uid": "210041000C51343237303334",
13-
"debugger": "jlink",
14-
"debugger_sn": "770935966",
15-
"cpu": "STM32F746NG"
13+
"flasher": "jlink",
14+
"flasher_sn": "770935966",
15+
"flasher_args": "-device STM32F746NG"
1616
},
1717
{
1818
"name": "lpcxpresso43s67",
1919
"uid": "08F000044528BAAA8D858F58C50700F5",
20-
"debugger": "jlink",
21-
"debugger_sn": "728973776",
22-
"cpu": "LPC43S67_M4"
20+
"flasher": "jlink",
21+
"flasher_sn": "728973776",
22+
"flasher_args": "-device LPC43S67_M4"
2323
}
2424
]
2525
}

test/hil/hil_pi4.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,19 @@
33
{
44
"name": "raspberry_pi_pico",
55
"uid": "E6614C311B764A37",
6-
"debugger": "openocd",
7-
"debugger_sn": "E6614103E72C1D2F",
8-
"debugger_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
6+
"flasher": "openocd",
7+
"flasher_sn": "E6614103E72C1D2F",
8+
"flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
9+
},
10+
{
11+
"name": "espressif_s3_devkitc",
12+
"uid": "7CDFA1E073CC",
13+
"tests": [
14+
"cdc_msc_freertos", "hid_composite_freertos"
15+
],
16+
"flasher": "esptool",
17+
"flasher_sn": "461cb8d7decdeb119be9b506e93fd3f1",
18+
"flasher_args": "-b 1500000"
919
}
1020
]
1121
}

test/hil/hil_test.py

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import os
2929
import sys
3030
import time
31+
import click
3132
import serial
3233
import subprocess
3334
import json
@@ -42,7 +43,7 @@ def get_serial_dev(id, vendor_str, product_str, ifnum):
4243
# known vendor and product
4344
return f'/dev/serial/by-id/usb-{vendor_str}_{product_str}_{id}-if{ifnum:02d}'
4445
else:
45-
# just use id: mostly for cp210x/ftdi debugger
46+
# just use id: mostly for cp210x/ftdi flasher
4647
pattern = f'/dev/serial/by-id/usb-*_{id}-if{ifnum:02d}*'
4748
port_list = glob.glob(pattern)
4849
return port_list[0]
@@ -99,34 +100,34 @@ def read_disk_file(id, fname):
99100

100101

101102
# -------------------------------------------------------------
102-
# Flash with debugger
103+
# Flashing firmware
103104
# -------------------------------------------------------------
104105
def flash_jlink(board, firmware):
105106
script = ['halt', 'r', f'loadfile {firmware}', 'r', 'go', 'exit']
106107
with open('flash.jlink', 'w') as f:
107108
f.writelines(f'{s}\n' for s in script)
108109
ret = subprocess.run(
109-
f'JLinkExe -USB {board["debugger_sn"]} -device {board["cpu"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink',
110+
f'JLinkExe -USB {board["flasher_sn"]} {board["flasher_args"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink',
110111
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
111112
os.remove('flash.jlink')
112113
return ret
113114

114115

115116
def flash_openocd(board, firmware):
116117
ret = subprocess.run(
117-
f'openocd -c "adapter serial {board["debugger_sn"]}" {board["debugger_args"]} -c "program {firmware} reset exit"',
118+
f'openocd -c "adapter serial {board["flasher_sn"]}" {board["flasher_args"]} -c "program {firmware} reset exit"',
118119
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
119120
return ret
120121

121122

122123
def flash_esptool(board, firmware):
123-
port = get_serial_dev(board["debugger_sn"], None, None, 0)
124+
port = get_serial_dev(board["flasher_sn"], None, None, 0)
124125
dir = os.path.dirname(firmware)
125126
with open(f'{dir}/config.env') as f:
126127
IDF_TARGET = json.load(f)['IDF_TARGET']
127128
with open(f'{dir}/flash_args') as f:
128129
flash_args = f.read().strip().replace('\n', ' ')
129-
command = (f'esptool.py --chip {IDF_TARGET} -p {port} {board["debugger_args"]} '
130+
command = (f'esptool.py --chip {IDF_TARGET} -p {port} {board["flasher_args"]} '
130131
f'--before=default_reset --after=hard_reset write_flash {flash_args}')
131132
ret = subprocess.run(command, shell=True, cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
132133
return ret
@@ -262,64 +263,76 @@ def test_hid_composite_freertos(id):
262263
# -------------------------------------------------------------
263264
# Main
264265
# -------------------------------------------------------------
265-
if __name__ == '__main__':
266-
if len(sys.argv) != 2:
267-
print('Usage:')
268-
print('python hitl_test.py config.json')
269-
sys.exit(-1)
270-
271-
with open(f'{os.path.dirname(__file__)}/{sys.argv[1]}') as f:
266+
@click.command()
267+
@click.argument('config_file')
268+
@click.option('-b', '--board', multiple=True, default=None, help='Boards to test, all if not specified')
269+
def main(config_file, board):
270+
"""
271+
Hardware test on specified boards
272+
"""
273+
config_file = os.path.join(os.path.dirname(__file__), config_file)
274+
with open(config_file) as f:
272275
config = json.load(f)
273276

274277
# all possible tests
275278
all_tests = [
276279
'cdc_dual_ports', 'cdc_msc', 'dfu', 'dfu_runtime', 'hid_boot_interface',
277280
]
278281

279-
for board in config['boards']:
280-
print(f'Testing board:{board["name"]}')
281-
debugger = board['debugger'].lower()
282+
if len(board) == 0:
283+
config_boards = config['boards']
284+
else:
285+
config_boards = [e for e in config['boards'] if e['name'] in board]
286+
287+
for item in config_boards:
288+
print(f'Testing board:{item["name"]}')
289+
flasher = item['flasher'].lower()
282290

283291
# default to all tests
284-
if 'tests' in board:
285-
test_list = board['tests']
292+
if 'tests' in item:
293+
test_list = item['tests']
286294
else:
287295
test_list = all_tests
288296

289297
# board_test is added last to disable board's usb
290298
test_list.append('board_test')
291299

292300
# remove skip_tests
293-
if 'tests_skip' in board:
294-
for skip in board['tests_skip']:
301+
if 'tests_skip' in item:
302+
for skip in item['tests_skip']:
295303
if skip in test_list:
296304
test_list.remove(skip)
297305

298306
for test in test_list:
299-
# cmake, make, download from artifacts
300-
elf_list = [
301-
f'cmake-build/cmake-build-{board["name"]}/device/{test}/{test}.elf',
302-
f'examples/device/{test}/_build/{board["name"]}/{test}.elf',
303-
f'{test}.elf'
307+
fw_list = [
308+
# cmake: esp32 use .bin file
309+
f'cmake-build/cmake-build-{item["name"]}/device/{test}/{test}.elf',
310+
f'cmake-build/cmake-build-{item["name"]}/device/{test}/{test}.bin',
311+
# make
312+
f'examples/device/{test}/_build/{item["name"]}/{test}.elf'
304313
]
305314

306-
elf = None
307-
for e in elf_list:
308-
if os.path.isfile(e):
309-
elf = e
315+
fw = None
316+
for f in fw_list:
317+
if os.path.isfile(f):
318+
fw = f
310319
break
311320

312-
if elf is None:
313-
print(f'Cannot find firmware file for {test}')
321+
if fw is None:
322+
print(f'Cannot find binary file for {test}')
314323
sys.exit(-1)
315324

316325
print(f' {test} ...', end='')
317326

318327
# flash firmware
319-
ret = locals()[f'flash_{debugger}'](board, elf)
328+
ret = globals()[f'flash_{flasher}'](item, fw)
320329
assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode()
321330

322331
# run test
323-
locals()[f'test_{test}'](board['uid'])
332+
globals()[f'test_{test}'](item['uid'])
324333

325334
print('OK')
335+
336+
337+
if __name__ == '__main__':
338+
main()

0 commit comments

Comments
 (0)