Skip to content

Commit 67ba8ea

Browse files
committed
focus on cdc test, write lots more data, each trunk is 64 or less since examples having minimum 64 bytes fifo (fs)
1 parent b98127f commit 67ba8ea

File tree

3 files changed

+66
-119
lines changed

3 files changed

+66
-119
lines changed

AGENTS.md

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,39 @@ information that does not match the info here.
1818

1919
- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi`
2020
- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL.
21-
- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4)
21+
- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4), or
22+
`python3 tools/get_deps.py -b BOARD_NAME`
2223
- Dependencies are cached in `lib/` and `hw/mcu/` directories
2324

2425
## Build Examples
2526

2627
Choose ONE of these approaches:
2728

28-
**Option 1: Individual Example with CMake (RECOMMENDED)**
29+
**Option 1: Individual Example with CMake and Ninja (RECOMMENDED)**
2930

3031
```bash
3132
cd examples/device/cdc_msc
3233
mkdir -p build && cd build
33-
cmake -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=MinSizeRel ..
34-
cmake --build . -j4
34+
cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ..
35+
cmake --build .
3536
```
3637

3738
-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
3839

39-
**CMake with Ninja (Alternative)**
40+
**Option 2: All Examples for a Board**
41+
42+
different folder than Option 1
4043

4144
```bash
42-
cd examples/device/cdc_msc
43-
mkdir build && cd build
44-
cmake -G Ninja -DBOARD=raspberry_pi_pico ..
45-
ninja
45+
cd examples/
46+
mkdir -p build && cd build
47+
cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ..
48+
cmake --build .
4649
```
4750

48-
**Option 2: Individual Example with Make**
51+
-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes.
52+
53+
**Option 3: Individual Example with Make**
4954

5055
```bash
5156
cd examples/device/cdc_msc
@@ -54,13 +59,6 @@ make BOARD=raspberry_pi_pico all
5459

5560
-- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
5661

57-
**Option 3: All Examples for a Board**
58-
59-
```bash
60-
python3 tools/build.py -b BOARD_NAME
61-
```
62-
63-
-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes.
6462

6563
## Build Options
6664

@@ -101,6 +99,17 @@ python3 tools/build.py -b BOARD_NAME
10199
- Run specific test: `cd test/unit-test && ceedling test:test_fifo`
102100
- Tests use Unity framework with CMock for mocking
103101

102+
## Hardware-in-the-Loop (HIL) Testing
103+
104+
- Run tests on actual hardware, one of following ways:
105+
- test a specific board `python test/hil/hil_test.py -b BOARD_NAME -B examples local.json`
106+
- test all boards in config `python test/hil/hil_test.py -B examples local.json`
107+
- In case of error, enabled verbose mode with `-v` flag for detailed logs. Also try to observe script output, and try to
108+
modify hil_test.py (temporarily) to add more debug prints to pinpoint the issue.
109+
- Requires pre-built (all) examples for target boards (see Build Examples section 2)
110+
111+
take 2-5 minutes. NEVER CANCEL. Set timeout to 20+ minutes.
112+
104113
## Documentation
105114

106115
- Install requirements: `pip install -r docs/requirements.txt`
@@ -145,11 +154,8 @@ python3 tools/build.py -b BOARD_NAME
145154
- Install pre-commit: `pip install pre-commit && pre-commit install`
146155
- Runs all quality checks, unit tests, spell checking, and formatting
147156
- Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes.
148-
2. **Build validation**: Build at least one example that exercises your changes
149-
```bash
150-
cd examples/device/cdc_msc
151-
make BOARD=raspberry_pi_pico all
152-
```
157+
2. **Build validation**: Build at least one board with all example that exercises your changes, see Build Examples
158+
section (option 2)
153159
3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines.
154160

155161
### Manual Testing Scenarios

CLAUDE.md

Lines changed: 0 additions & 78 deletions
This file was deleted.

test/hil/hil_test.py

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
import re
3333
import sys
3434
import time
35+
import warnings
36+
37+
# Suppress pkg_resources deprecation warning from fs module
38+
warnings.filterwarnings("ignore", message="pkg_resources is deprecated")
39+
3540
import serial
3641
import subprocess
3742
import json
@@ -51,6 +56,7 @@
5156

5257
verbose = False
5358
test_only = []
59+
build_dir = 'cmake-build'
5460

5561
WCH_RISCV_CONTENT = """
5662
adapter driver wlinke
@@ -405,10 +411,17 @@ def write_and_check(writer, payload):
405411
size = len(payload)
406412
for s in ser:
407413
s.reset_input_buffer()
408-
ser[writer].write(payload)
409-
ser[writer].flush()
410-
rd0 = ser[0].read(size)
411-
rd1 = ser[1].read(size)
414+
rd0 = b''
415+
rd1 = b''
416+
offset = 0
417+
# Write in chunks of random 1-64 bytes (device has 64-byte buffer)
418+
while offset < size:
419+
chunk_size = min(random.randint(1, 64), size - offset)
420+
ser[writer].write(payload[offset:offset + chunk_size])
421+
ser[writer].flush()
422+
rd0 += ser[0].read(chunk_size)
423+
rd1 += ser[1].read(chunk_size)
424+
offset += chunk_size
412425
assert rd0 == payload.lower(), f'Port0 wrong data ({size}): expected {payload.lower()[:16]}... was {rd0[:16]}'
413426
assert rd1 == payload.upper(), f'Port1 wrong data ({size}): expected {payload.upper()[:16]}... was {rd1[:16]}'
414427

@@ -434,21 +447,26 @@ def rand_ascii(length):
434447
sizes = [32, 64, 128, 256, 512, random.randint(2000, 5000)]
435448
for size in sizes:
436449
test_str = rand_ascii(size)
437-
ser.write(test_str)
438-
ser.flush()
439-
rd_str = ser.read(len(test_str))
440-
assert rd_str == test_str, f'CDC wrong data ({size} bytes):\n expected: {test_str}\n was: {rd_str}'
441-
450+
rd_str = b''
451+
offset = 0
452+
# Write in chunks of random 1-64 bytes (device has 64-byte buffer)
453+
while offset < size:
454+
chunk_size = min(random.randint(1, 64), size - offset)
455+
ser.write(test_str[offset:offset + chunk_size])
456+
ser.flush()
457+
rd_str += ser.read(chunk_size)
458+
offset += chunk_size
459+
assert rd_str == test_str, f'CDC wrong data ({size} bytes):\n expected: {test_str}\n received: {rd_str}'
442460
ser.close()
443461

444462
# MSC Block test
445463
data = read_disk_file(uid, 0, 'README.TXT')
446464
readme = \
447465
b"This is tinyusb's MassStorage Class demo.\r\n\r\n\
448-
If you find any bugs or get any questions, feel free to file an\r\n\
449-
issue at github.com/hathach/tinyusb"
466+
If you find any bugs or get any questions, feel free to file an\r\n\
467+
issue at github.com/hathach/tinyusb"
450468

451-
assert data == readme, 'MSC wrong data'
469+
assert data == readme, f'MSC wrong data in README.TXT\n expected: {readme.decode()}\n received: {data.decode()}'
452470

453471

454472
def test_device_cdc_msc_freertos(board):
@@ -598,11 +616,11 @@ def test_device_mtp(board):
598616
# note don't test 2 examples with cdc or 2 msc next to each other
599617
device_tests = [
600618
'device/cdc_dual_ports',
601-
'device/dfu',
619+
# 'device/dfu',
602620
'device/cdc_msc',
603-
'device/dfu_runtime',
621+
# 'device/dfu_runtime',
604622
'device/cdc_msc_freertos',
605-
'device/hid_boot_interface',
623+
# 'device/hid_boot_interface',
606624
# 'device/mtp'
607625
]
608626

@@ -630,9 +648,7 @@ def test_example(board, f1, example):
630648
if f1 != "":
631649
f1_str = '-f1_' + f1.replace(' ', '_')
632650

633-
fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{example}'
634-
if not os.path.exists(fw_dir):
635-
fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{example}'
651+
fw_dir = f'{TINYUSB_ROOT}/{build_dir}/cmake-build-{name}{f1_str}/{example}'
636652
fw_name = f'{fw_dir}/{os.path.basename(example)}'
637653
print(f'{name+f1_str:40} {example:30} ...', end='')
638654

@@ -644,7 +660,7 @@ def test_example(board, f1, example):
644660
print(f'Flashing {fw_name}.elf')
645661

646662
# flash firmware. It may fail randomly, retry a few times
647-
max_rety = 3
663+
max_rety = 1
648664
start_s = time.time()
649665
for i in range(max_rety):
650666
ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name)
@@ -720,6 +736,7 @@ def main():
720736
"""
721737
global verbose
722738
global test_only
739+
global build_dir
723740

724741
duration = time.time()
725742

@@ -728,6 +745,7 @@ def main():
728745
parser.add_argument('-b', '--board', action='append', default=[], help='Boards to test, all if not specified')
729746
parser.add_argument('-s', '--skip', action='append', default=[], help='Skip boards from test')
730747
parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified')
748+
parser.add_argument('-B', '--build', default='cmake-build', help='Build folder name (default: cmake-build)')
731749
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
732750
args = parser.parse_args()
733751

@@ -736,6 +754,7 @@ def main():
736754
skip_boards = args.skip
737755
verbose = args.verbose
738756
test_only = args.test_only
757+
build_dir = args.build
739758

740759
# if config file is not found, try to find it in the same directory as this script
741760
if not os.path.exists(config_file):

0 commit comments

Comments
 (0)