TinyUSB is a cross-platform USB Host/Device stack for embedded systems: memory-safe (no dynamic allocation) and thread-safe (ISR events deferred to task context).
Reference these instructions first; fall back to search/bash only when reality diverges.
Bias toward caution over speed. For trivial tasks, use judgment.
step → verify plan.UPPER_CASE macros. Public APIs use tud_/tuh_; macros use TU_. Headers self-contained with #if CFG_TUSB_MCU guards.TU_ASSERT() for error checks; always check return values; include order: C stdlib → tusb common → drivers → classes.src/ core, hw/{mcu,bsp}/ MCU+BSP, examples/{device,host,dual}/, test/{unit-test,fuzz,hil}/, docs/, tools/.clang-format (.clang-format), codespell (.codespellrc), run pre-commit run --all-files before submitting.sudo apt-get install -y gcc-arm-none-eabi # ARM toolchain (2-5 min, one-time) python3 tools/get_deps.py [FAMILY|-b BOARD] # fetch deps into lib/, hw/mcu/ (<1 s) . $HOME/code/esp-idf/export.sh # Espressif only: before any build/flash/monitor
Single example (CMake+Ninja, recommended, 1-3 s):
cd examples/device/cdc_msc && mkdir -p build && cd build cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel .. cmake --build .
All examples for a board (15-20 s; some objcopy failures are non-critical). Use cmake-build-<board> as the build dir — HIL tests expect that exact name:
cd examples cmake -B cmake-build-raspberry_pi_pico -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel . cmake --build cmake-build-raspberry_pi_pico
Single example with Make:
cd examples/device/cdc_msc && make BOARD=raspberry_pi_pico all
Espressif (only ESP-IDF examples like cdc_msc_freertos):
. $HOME/code/esp-idf/export.sh cd examples/device/cdc_msc_freertos idf.py -DBOARD=espressif_s3_devkitc build
Build options (CMake -D… / Make …=…):
CMAKE_BUILD_TYPE=Debug / DEBUG=1LOG=2 (add LOGGER=rtt for RTT)RHPORT_DEVICE=1RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED# JLink ninja cdc_msc-jlink # CMake make BOARD=<board> flash-jlink # Make # OpenOCD ninja cdc_msc-openocd # CMake make BOARD=<board> flash-openocd # Make # UF2 ninja cdc_msc-uf2 # CMake make BOARD=<board> all uf2 # Make ninja -t targets # list CMake targets # Espressif (after . $HOME/code/esp-idf/export.sh) idf.py -DBOARD=<board> flash idf.py -DBOARD=<board> monitor
Look up JLINK_DEVICE / OPENOCD_OPTION in hw/bsp/*/boards/*/board.cmake (CMake builds) or board.mk (Make builds).
JLink — Terminal 1:
JLinkGDBServer -device stm32h743xi -if SWD -speed 4000 -port 2331 -swoport 2332 -telnetport 2333 -nogui
OpenOCD — Terminal 1:
openocd -f interface/stlink.cfg -f target/stm32h7x.cfg # or with a J-Link interface: openocd -f interface/jlink.cfg -f target/stm32h7x.cfg # rp2040/rp2350 via CMSIS-DAP: openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"
Terminal 2 — connect GDB (replace <port> with 2331 for JLinkGDBServer or 3333 for OpenOCD):
arm-none-eabi-gdb /tmp/build/firmware.elf (gdb) target remote :<port> (gdb) monitor reset halt (gdb) load (gdb) break main # optional, to stop at entry (gdb) continue
RTT logging: build with LOG=2 LOGGER=rtt, flash, then run JLinkGDBServer with -RTTTelnetPort 19021, and in another terminal JLinkRTTClient (pipe to tee rtt.log or use timeout 20s JLinkRTTClient > rtt.log for non-interactive capture).
Unit (Ceedling, Unity+CMock, ~4 s):
sudo gem install ceedling cd test/unit-test && ceedling test:all # or ceedling test:test_fifo
HIL (2-5 min): invoke the hil skill (.claude/skills/hil/SKILL.md) for the full procedure (local vs remote mode, config selection, SSH copy steps, debugging tips). Requires pre-built examples — see Build → “All examples for a board”.
pip install -r docs/requirements.txt cd docs && sphinx-build -b html . _build # ~2.5 s
Verify size impact before committing. Invoke the code-size skill (.claude/skills/code-size/SKILL.md) — it wraps tools/metrics_compare_base.py to handle the base-vs-branch worktree + build + compare flow.
Quick reference:
# Single example, one board: python3 tools/metrics_compare_base.py -b raspberry_pi_pico -e device/cdc_msc # Add --bloaty for section/symbol breakdown. # All examples, one board: python3 tools/metrics_compare_base.py -b raspberry_pi_pico # All arm-gcc CI families combined (pre-merge sweep, 4-8 min): python3 tools/metrics_compare_base.py --ci
Reports land in cmake-metrics/<board>/metrics_compare.md (per-board) and cmake-metrics/_combined/metrics_compare.md (with --combined/--ci).
Requires compile_commands.json (CMake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON).
# Whole project: pvs-studio-analyzer analyze \ -f examples/cmake-build-raspberry_pi_pico/compile_commands.json \ -R .PVS-Studio/.pvsconfig \ -o pvs-report.log -j12 --dump-files \ --misra-c-version 2023 --misra-cpp-version 2008 --use-old-parser # Specific files (add one or more `-S <file>`): pvs-studio-analyzer analyze \ -f examples/cmake-build-raspberry_pi_pico/compile_commands.json \ -R .PVS-Studio/.pvsconfig \ -S src/foo.c -S src/bar.c \ -o pvs-report.log -j12 --dump-files \ --misra-c-version 2023 --misra-cpp-version 2008 --use-old-parser plog-converter -a GA:1,2 -t errorfile pvs-report.log # view results
Takes ~10-30 s.
pre-commit run --all-files — format, spell, unit tests (10-15 s).Boards good for local testing:
stm32f407disco — no external SDKraspberry_pi_pico — Pico SDK requiredhw/bsp/FAMILY/boards/Device examples need real hardware to validate runtime behavior; must at least build.
Do not commit automatically — leave changes for maintainer review.
tools/make_release.py.python3 tools/make_release.py to refresh: src/tusb_option.h, repository.yml, library.json, sonar-project.properties, docs/reference/boards.rst, hw/bsp/BoardPresets.json.docs/info/changelog.rst:git log <last-tag>..HEAD --oneline for commit list.gh pr view, or github MCP tools).====== underline, italic date, sections (General, API Changes, DCD & HCD, Device Stack, Host Stack, Testing), RST inline code for symbols.ceedling test:all, build cdc_msc for stm32f407disco, review git diff --stat.Bump version to X.Y.Z, then: git tag -a vX.Y.Z -m "Release X.Y.Z" && git push origin <branch> vX.Y.Z. Create GitHub release from tag.$HOME/Documents/Calibre Library.hw/bsp/ and docs/reference/boards.rst.src/class/{cdc,hid,msc,audio,…}/ — each has *_device.c and *_host.c.src/tusb.h, src/tusb_config.h, tools/get_deps.py, tools/build.py, test/unit-test/project.yml.gcc-arm-none-eabi.python3 tools/get_deps.py FAMILY.hw/bsp/FAMILY/boards/.objcopy errors in full builds are often non-critical; retry the single example.