focus on cdc test, write lots more data, each trunk is 64 or less since examples having minimum 64 bytes fifo (fs)

This commit is contained in:
hathach
2025-11-22 18:26:43 +07:00
parent b98127fba2
commit 67ba8eab2e
3 changed files with 66 additions and 119 deletions

View File

@ -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

View File

@ -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

View File

@ -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):