mirror of
https://github.com/hathach/tinyusb.git
synced 2026-03-01 04:58:35 +00:00
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:
50
AGENTS.md
50
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
|
||||
|
||||
78
CLAUDE.md
78
CLAUDE.md
@ -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
|
||||
@ -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):
|
||||
|
||||
Reference in New Issue
Block a user