summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-11-22 18:26:43 +0700
committerhathach <[email protected]>2025-11-26 13:54:04 +0700
commit67ba8eab2e346dc13cce3d0813de6370cb3cfa48 (patch)
tree5983e65b4c1b0437a15d8abb52138594cc9b6a77
parentb98127fba2b198130eb8868defcf117c6b5ea231 (diff)
focus on cdc test, write lots more data, each trunk is 64 or less since examples having minimum 64 bytes fifo (fs)
-rw-r--r--AGENTS.md50
-rw-r--r--CLAUDE.md78
-rwxr-xr-xtest/hil/hil_test.py57
3 files changed, 66 insertions, 119 deletions
diff --git a/AGENTS.md b/AGENTS.md
index a6163dd42..73bf1f599 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -18,34 +18,39 @@ information that does not match the info here.
- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi`
- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL.
-- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4)
+- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4), or
+ `python3 tools/get_deps.py -b BOARD_NAME`
- Dependencies are cached in `lib/` and `hw/mcu/` directories
## Build Examples
Choose ONE of these approaches:
-**Option 1: Individual Example with CMake (RECOMMENDED)**
+**Option 1: Individual Example with CMake and Ninja (RECOMMENDED)**
```bash
cd examples/device/cdc_msc
mkdir -p build && cd build
-cmake -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=MinSizeRel ..
-cmake --build . -j4
+cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ..
+cmake --build .
```
-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
-**CMake with Ninja (Alternative)**
+**Option 2: All Examples for a Board**
+
+different folder than Option 1
```bash
-cd examples/device/cdc_msc
-mkdir build && cd build
-cmake -G Ninja -DBOARD=raspberry_pi_pico ..
-ninja
+cd examples/
+mkdir -p build && cd build
+cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel ..
+cmake --build .
```
-**Option 2: Individual Example with Make**
+-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes.
+
+**Option 3: Individual Example with Make**
```bash
cd examples/device/cdc_msc
@@ -54,13 +59,6 @@ make BOARD=raspberry_pi_pico all
-- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes.
-**Option 3: All Examples for a Board**
-
-```bash
-python3 tools/build.py -b BOARD_NAME
-```
-
--- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes.
## Build Options
@@ -101,6 +99,17 @@ python3 tools/build.py -b BOARD_NAME
- Run specific test: `cd test/unit-test && ceedling test:test_fifo`
- Tests use Unity framework with CMock for mocking
+## Hardware-in-the-Loop (HIL) Testing
+
+- Run tests on actual hardware, one of following ways:
+ - test a specific board `python test/hil/hil_test.py -b BOARD_NAME -B examples local.json`
+ - test all boards in config `python test/hil/hil_test.py -B examples local.json`
+- In case of error, enabled verbose mode with `-v` flag for detailed logs. Also try to observe script output, and try to
+ modify hil_test.py (temporarily) to add more debug prints to pinpoint the issue.
+- Requires pre-built (all) examples for target boards (see Build Examples section 2)
+
+take 2-5 minutes. NEVER CANCEL. Set timeout to 20+ minutes.
+
## Documentation
- Install requirements: `pip install -r docs/requirements.txt`
@@ -145,11 +154,8 @@ python3 tools/build.py -b BOARD_NAME
- Install pre-commit: `pip install pre-commit && pre-commit install`
- Runs all quality checks, unit tests, spell checking, and formatting
- Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes.
-2. **Build validation**: Build at least one example that exercises your changes
- ```bash
- cd examples/device/cdc_msc
- make BOARD=raspberry_pi_pico all
- ```
+2. **Build validation**: Build at least one board with all example that exercises your changes, see Build Examples
+ section (option 2)
3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines.
### Manual Testing Scenarios
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index 6c6baa246..000000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# TinyUSB Development Guide
-
-## Build Commands
-
-### CMake Build System (Preferred)
-CMake with Ninja is the preferred build method for TinyUSB development.
-
-- Build example with Ninja:
- ```bash
- cd examples/device/cdc_msc
- mkdir build && cd build
- cmake -G Ninja -DBOARD=raspberry_pi_pico ..
- ninja
- ```
-- Debug build: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=Debug ..`
-- With logging: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DLOG=2 ..`
-- With RTT logger: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DLOG=2 -DLOGGER=rtt ..`
-- Flash with JLink: `ninja cdc_msc-jlink`
-- Flash with OpenOCD: `ninja cdc_msc-openocd`
-- Generate UF2: `ninja cdc_msc-uf2`
-- List all targets: `ninja -t targets`
-
-### Make Build System (Alternative)
-- Build example: `cd examples/device/cdc_msc && make BOARD=raspberry_pi_pico all`
-- For specific example: `cd examples/{device|host|dual}/{example_name} && make BOARD=raspberry_pi_pico all`
-- Flash with JLink: `make BOARD=raspberry_pi_pico flash-jlink`
-- Flash with OpenOCD: `make BOARD=raspberry_pi_pico flash-openocd`
-- Debug build: `make BOARD=raspberry_pi_pico DEBUG=1 all`
-- With logging: `make BOARD=raspberry_pi_pico LOG=2 all`
-- With RTT logger: `make BOARD=raspberry_pi_pico LOG=2 LOGGER=rtt all`
-- Generate UF2: `make BOARD=raspberry_pi_pico all uf2`
-
-### Additional Options
-- Select RootHub port: `RHPORT_DEVICE=1` (make) or `-DRHPORT_DEVICE=1` (cmake)
-- Set port speed: `RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` (make) or `-DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` (cmake)
-
-### Dependencies
-- Get dependencies: `python tools/get_deps.py rp2040`
-- Or from example: `cd examples/device/cdc_msc && make BOARD=raspberry_pi_pico get-deps`
-
-### Testing
-- Run unit tests: `cd test/unit-test && ceedling test:all`
-- Run specific test: `cd test/unit-test && ceedling test:test_fifo`
-
-### Pre-commit Hooks
-Before building, it's recommended to run pre-commit to ensure code quality:
-- Run pre-commit on all files: `pre-commit run --all-files`
-- Run pre-commit on staged files: `pre-commit run`
-- Install pre-commit hook: `pre-commit install`
-
-## Code Style Guidelines
-- Use C99 standard
-- Memory-safe: no dynamic allocation
-- Thread-safe: defer all interrupt events to non-ISR task functions
-- 2-space indentation, no tabs
-- Use snake_case for variables/functions
-- Use UPPER_CASE for macros and constants
-- Follow existing variable naming patterns in files you're modifying
-- Include proper header comments with MIT license
-- Add descriptive comments for non-obvious functions
-- When including headers, group in order: C stdlib, tusb common, drivers, classes
-- Always check return values from functions that can fail
-- Use TU_ASSERT() for error checking with return statements
-
-## Project Structure
-- src/: Core TinyUSB stack code
-- hw/: Board support packages and MCU drivers
-- examples/: Reference examples for device/host/dual
-- test/: Unit tests and hardware integration tests
-
-## Release Process
-To prepare a new release:
-1. Update the `version` variable in `tools/make_release.py` to the new version number
-2. Run the release script: `python tools/make_release.py`
- - This will update version numbers in `src/tusb_option.h`, `repository.yml`, and `library.json`
- - It will also regenerate documentation
-3. Update `docs/info/changelog.rst` with release notes
-4. Commit changes and create release tag
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index 238d452e8..6b7a5ee12 100755
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -32,6 +32,11 @@ import random
import re
import sys
import time
+import warnings
+
+# Suppress pkg_resources deprecation warning from fs module
+warnings.filterwarnings("ignore", message="pkg_resources is deprecated")
+
import serial
import subprocess
import json
@@ -51,6 +56,7 @@ STATUS_SKIPPED = "\033[33mSkipped\033[0m"
verbose = False
test_only = []
+build_dir = 'cmake-build'
WCH_RISCV_CONTENT = """
adapter driver wlinke
@@ -405,10 +411,17 @@ def test_device_cdc_dual_ports(board):
size = len(payload)
for s in ser:
s.reset_input_buffer()
- ser[writer].write(payload)
- ser[writer].flush()
- rd0 = ser[0].read(size)
- rd1 = ser[1].read(size)
+ rd0 = b''
+ rd1 = b''
+ offset = 0
+ # Write in chunks of random 1-64 bytes (device has 64-byte buffer)
+ while offset < size:
+ chunk_size = min(random.randint(1, 64), size - offset)
+ ser[writer].write(payload[offset:offset + chunk_size])
+ ser[writer].flush()
+ rd0 += ser[0].read(chunk_size)
+ rd1 += ser[1].read(chunk_size)
+ offset += chunk_size
assert rd0 == payload.lower(), f'Port0 wrong data ({size}): expected {payload.lower()[:16]}... was {rd0[:16]}'
assert rd1 == payload.upper(), f'Port1 wrong data ({size}): expected {payload.upper()[:16]}... was {rd1[:16]}'
@@ -434,21 +447,26 @@ def test_device_cdc_msc(board):
sizes = [32, 64, 128, 256, 512, random.randint(2000, 5000)]
for size in sizes:
test_str = rand_ascii(size)
- ser.write(test_str)
- ser.flush()
- rd_str = ser.read(len(test_str))
- assert rd_str == test_str, f'CDC wrong data ({size} bytes):\n expected: {test_str}\n was: {rd_str}'
-
+ rd_str = b''
+ offset = 0
+ # Write in chunks of random 1-64 bytes (device has 64-byte buffer)
+ while offset < size:
+ chunk_size = min(random.randint(1, 64), size - offset)
+ ser.write(test_str[offset:offset + chunk_size])
+ ser.flush()
+ rd_str += ser.read(chunk_size)
+ offset += chunk_size
+ assert rd_str == test_str, f'CDC wrong data ({size} bytes):\n expected: {test_str}\n received: {rd_str}'
ser.close()
# MSC Block test
data = read_disk_file(uid, 0, '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\
- issue at github.com/hathach/tinyusb"
+If you find any bugs or get any questions, feel free to file an\r\n\
+issue at github.com/hathach/tinyusb"
- assert data == readme, 'MSC wrong data'
+ assert data == readme, f'MSC wrong data in README.TXT\n expected: {readme.decode()}\n received: {data.decode()}'
def test_device_cdc_msc_freertos(board):
@@ -598,11 +616,11 @@ def test_device_mtp(board):
# note don't test 2 examples with cdc or 2 msc next to each other
device_tests = [
'device/cdc_dual_ports',
- 'device/dfu',
+ # 'device/dfu',
'device/cdc_msc',
- 'device/dfu_runtime',
+ # 'device/dfu_runtime',
'device/cdc_msc_freertos',
- 'device/hid_boot_interface',
+ # 'device/hid_boot_interface',
# 'device/mtp'
]
@@ -630,9 +648,7 @@ def test_example(board, f1, example):
if f1 != "":
f1_str = '-f1_' + f1.replace(' ', '_')
- fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{example}'
- if not os.path.exists(fw_dir):
- fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{example}'
+ fw_dir = f'{TINYUSB_ROOT}/{build_dir}/cmake-build-{name}{f1_str}/{example}'
fw_name = f'{fw_dir}/{os.path.basename(example)}'
print(f'{name+f1_str:40} {example:30} ...', end='')
@@ -644,7 +660,7 @@ def test_example(board, f1, example):
print(f'Flashing {fw_name}.elf')
# flash firmware. It may fail randomly, retry a few times
- max_rety = 3
+ max_rety = 1
start_s = time.time()
for i in range(max_rety):
ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name)
@@ -720,6 +736,7 @@ def main():
"""
global verbose
global test_only
+ global build_dir
duration = time.time()
@@ -728,6 +745,7 @@ def main():
parser.add_argument('-b', '--board', action='append', default=[], help='Boards to test, all if not specified')
parser.add_argument('-s', '--skip', action='append', default=[], help='Skip boards from test')
parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified')
+ parser.add_argument('-B', '--build', default='cmake-build', help='Build folder name (default: cmake-build)')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
args = parser.parse_args()
@@ -736,6 +754,7 @@ def main():
skip_boards = args.skip
verbose = args.verbose
test_only = args.test_only
+ build_dir = args.build
# if config file is not found, try to find it in the same directory as this script
if not os.path.exists(config_file):