summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-04-29 11:09:48 +0700
committerhathach <[email protected]>2026-04-29 11:09:48 +0700
commit47f2228cedfb216411c1ac50c4f10a30907cdb51 (patch)
tree68f3820823019391f8ca61060af3b726e6252d47
parent8010366808656937ed684af6fedb899a7130e9ba (diff)
address review feedback for AGENTS.md and hil skill
AGENTS.md: - fix build dir to cmake-build-<board> (matches hil_test.py expectation) - reformat flash section to avoid shell-pipe ambiguity, use <board> - mention board.mk for Make-based builds - complete OpenOCD jlink interface example - update stale "Build Option 2" references to "All examples for a board" - split PVS-Studio command so it is copy-pasteable .claude/skills/hil/SKILL.md: - clarify local.json is user-supplied, not tracked in repo - use python3 consistently - add all-boards variant for remote execution - delegate remote execution to test/hil/hil_ci.sh test/hil/hil_ci.sh: - portable shebang (/usr/bin/env bash) - set -euo pipefail - env overrides for REMOTE, REMOTE_DIR, CONFIG, ROOT_DIR - --prune-empty-dirs on rsync to skip empty subdirs - fail-fast sanity check on repo layout Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
-rw-r--r--.claude/skills/hil/SKILL.md47
-rw-r--r--AGENTS.md51
-rw-r--r--test/hil/hil_ci.sh37
3 files changed, 80 insertions, 55 deletions
diff --git a/.claude/skills/hil/SKILL.md b/.claude/skills/hil/SKILL.md
index 638b34b2d..1f3d7d072 100644
--- a/.claude/skills/hil/SKILL.md
+++ b/.claude/skills/hil/SKILL.md
@@ -9,7 +9,7 @@ Run TinyUSB HIL tests against real boards. Two execution modes — **local** (bo
## Prerequisites
-- Examples must already be built for the target board(s). See AGENTS.md "Build" section, Option 2 (all examples for a board), which produces `examples/cmake-build-BOARD_NAME/`.
+- Examples must already be built for the target board(s). See AGENTS.md "Build" → "All examples for a board", which produces `examples/cmake-build-<board>/`.
- `-B examples` tells `hil_test.py` that `examples/` is the parent folder containing the per-board build outputs.
## Choosing arguments
@@ -17,51 +17,42 @@ Run TinyUSB HIL tests against real boards. Two execution modes — **local** (bo
Infer from the user's request:
- **Mode:** `local` (default) or `remote`. Only switch to `remote` if the user explicitly says so or names `ci.lan`.
-- **Board:** if the user names a specific board, pass `-b BOARD_NAME`. Otherwise run all boards in the config.
+- **Board:** if the user names a specific board, pass `-b BOARD_NAME`. Otherwise omit `-b` to run all boards in the config.
- **Pass-through flags:** `-v` (verbose), `-r N` (retry count), etc. — pass through unchanged.
Config file follows from mode:
-- **Local** → `local.json`
-- **Remote** → `tinyusb.json`
+- **Local** → `test/hil/local.json` (user-supplied; not tracked in repo — describes boards attached locally)
+- **Remote** → `test/hil/tinyusb.json` (tracked; describes the `ci.lan` test rig)
+
+If `local.json` is missing, fall back to `tinyusb.json` only when explicitly told to; otherwise stop and ask the user to supply one.
## Local execution
Boards attached to this machine:
```bash
-python test/hil/hil_test.py -b BOARD_NAME -B examples local.json $EXTRA_ARGS
-# or for all boards in the config:
-python test/hil/hil_test.py -B examples local.json $EXTRA_ARGS
+# Specific board:
+python3 test/hil/hil_test.py -b BOARD_NAME -B examples test/hil/local.json $EXTRA_ARGS
+# All boards in the config (no -b):
+python3 test/hil/hil_test.py -B examples test/hil/local.json $EXTRA_ARGS
```
## Remote execution (ci.lan)
-Copy only the minimal files needed (firmware binaries + test script + config), then run remotely:
+Use `test/hil/hil_ci.sh` — it handles dir setup, scp of test scripts, rsync of firmware artifacts (`.elf` / `.bin` / `.hex` only), and running `hil_test.py` on `ci.lan`:
```bash
-REMOTE=ci.lan
-REMOTE_DIR=/tmp/tinyusb-hil
-
-# Create remote working directory
-ssh $REMOTE "rm -rf $REMOTE_DIR && mkdir -p $REMOTE_DIR/test/hil"
-
-# Copy HIL test script and its dependency
-scp test/hil/hil_test.py test/hil/pymtp.py test/hil/tinyusb.json $REMOTE:$REMOTE_DIR/test/hil/
-
-# Copy firmware binaries
# Specific board:
-scp -r examples/cmake-build-$BOARD_NAME $REMOTE:$REMOTE_DIR/examples/
-# Or all built boards:
-# for dir in examples/cmake-build-*/; do scp -r "$dir" $REMOTE:$REMOTE_DIR/examples/; done
-
-# Run the test remotely
-ssh $REMOTE "cd $REMOTE_DIR && python3 test/hil/hil_test.py -b $BOARD_NAME -B examples tinyusb.json $EXTRA_ARGS"
+bash test/hil/hil_ci.sh -b raspberry_pi_pico2
+# All boards in tinyusb.json:
+bash test/hil/hil_ci.sh
+# Pass-through extra args (any non -b flag is forwarded to hil_test.py):
+bash test/hil/hil_ci.sh -b raspberry_pi_pico2 -t host/cdc_msc_hid -r 1
```
-The remote machine (`ci.lan`) must have:
-- Python 3 with `pyserial` installed (`pip install pyserial`)
-- Flasher tools: `JLinkExe`, `openocd`, etc. as needed by the board
-- USB access to the boards (udev rules configured)
+Overrides via env vars: `REMOTE=ci.lan`, `REMOTE_DIR=/tmp/tinyusb-hil`, `CONFIG=test/hil/tinyusb.json`.
+
+The script fails fast if the build dir or repo layout is missing.
## Timing
diff --git a/AGENTS.md b/AGENTS.md
index 13e5af66d..37fac2b05 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -38,10 +38,11 @@ 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):
+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:
```bash
-cd examples && mkdir -p build && cd build
-cmake -DBOARD=raspberry_pi_pico -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel .. && cmake --build .
+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:
@@ -65,16 +66,28 @@ idf.py -DBOARD=espressif_s3_devkitc build
## Flash
```bash
-ninja cdc_msc-jlink | make BOARD=… flash-jlink # JLink
-ninja cdc_msc-openocd | make BOARD=… flash-openocd # OpenOCD
-ninja cdc_msc-uf2 | make BOARD=… all uf2 # UF2
+# 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
-idf.py -DBOARD=… flash|monitor # Espressif (after export.sh)
+
+# Espressif (after . $HOME/code/esp-idf/export.sh)
+idf.py -DBOARD=<board> flash
+idf.py -DBOARD=<board> monitor
```
## GDB Debugging
-Look up `JLINK_DEVICE` / `OPENOCD_OPTION` in `hw/bsp/*/boards/*/board.cmake`.
+Look up `JLINK_DEVICE` / `OPENOCD_OPTION` in `hw/bsp/*/boards/*/board.cmake` (CMake builds) or `board.mk` (Make builds).
**JLink — Terminal 1:**
```bash
@@ -83,7 +96,9 @@ JLinkGDBServer -device stm32h743xi -if SWD -speed 4000 -port 2331 -swoport 2332
**OpenOCD — Terminal 1:**
```bash
-openocd -f interface/stlink.cfg -f target/stm32h7x.cfg # or interface/jlink.cfg
+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"
```
@@ -108,7 +123,7 @@ 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 (Build Option 2).
+**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".
## Documentation
@@ -146,20 +161,30 @@ python3 tools/metrics.py combine -j -m -f tinyusb/src cmake-build/cmake-build-*/
Requires `compile_commands.json` (CMake `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`).
```bash
+# 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 path/to/file.c ...] \
+ -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
```
-Add `-S <file>` (repeatable) to restrict to specific sources. ~10-30 s.
+Takes ~10-30 s.
## Validation After Changes
1. `pre-commit run --all-files` — format, spell, unit tests (10-15 s).
-2. Build at least one board's full example set (Build Option 2) for modules you touched.
+2. Build at least one board's full example set (Build → "All examples for a board") for modules you touched.
3. Run relevant unit tests; add fuzz/HIL coverage for parsers or protocol state machines.
**Boards good for local testing:**
diff --git a/test/hil/hil_ci.sh b/test/hil/hil_ci.sh
index fa8bb0245..d1b5f7def 100644
--- a/test/hil/hil_ci.sh
+++ b/test/hil/hil_ci.sh
@@ -1,15 +1,24 @@
-#!/bin/bash
+#!/usr/bin/env bash
# Run HIL test remotely on ci.lan
# Usage: test/hil/hil_ci.sh [-b BOARD] [-t TEST] [extra hil_test.py args...]
# Example:
# test/hil/hil_ci.sh -b stm32f723disco
# test/hil/hil_ci.sh -b stm32f723disco -t host/cdc_msc_hid -r 1
+#
+# Env overrides: REMOTE, REMOTE_DIR, CONFIG (path to HIL config json),
+# ROOT_DIR (tinyusb checkout to test; defaults to the script's own checkout).
-set -e
+set -euo pipefail
-REMOTE=ci.lan
-REMOTE_DIR=/tmp/tinyusb-hil
-SCRIPT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
+REMOTE=${REMOTE:-ci.lan}
+REMOTE_DIR=${REMOTE_DIR:-/tmp/tinyusb-hil}
+ROOT_DIR=${ROOT_DIR:-$(cd "$(dirname "$0")/../.." && pwd)}
+CONFIG=${CONFIG:-$ROOT_DIR/test/hil/tinyusb.json}
+
+[[ -f "$ROOT_DIR/test/hil/hil_test.py" && -d "$ROOT_DIR/examples" ]] || {
+ echo "error: $ROOT_DIR does not look like a tinyusb checkout" >&2
+ exit 1
+}
# Parse -b BOARD from arguments to know which build to copy
BOARD=""
@@ -34,22 +43,21 @@ ssh "$REMOTE" "rm -rf $REMOTE_DIR && mkdir -p $REMOTE_DIR/test/hil $REMOTE_DIR/e
# Copy HIL test script and config
echo "==> Copying test scripts"
-scp -q "$SCRIPT_DIR/test/hil/hil_test.py" \
- "$SCRIPT_DIR/test/hil/pymtp.py" \
- "$SCRIPT_DIR/test/hil/tinyusb.json" \
+scp -q "$ROOT_DIR/test/hil/hil_test.py" \
+ "$ROOT_DIR/test/hil/pymtp.py" \
+ "$CONFIG" \
"$REMOTE:$REMOTE_DIR/test/hil/"
# Copy only firmware binaries (elf/bin/hex), preserving directory structure
copy_board_binaries() {
local src="$1"
- local board_name
- board_name=$(basename "$src")
- rsync -a --include='*/' --include='*.elf' --include='*.bin' --include='*.hex' --exclude='*' \
+ rsync -a --prune-empty-dirs \
+ --include='*/' --include='*.elf' --include='*.bin' --include='*.hex' --exclude='*' \
"$src" "$REMOTE:$REMOTE_DIR/examples/"
}
if [ -n "$BOARD" ]; then
- BUILD_DIR="$SCRIPT_DIR/examples/cmake-build-$BOARD"
+ BUILD_DIR="$ROOT_DIR/examples/cmake-build-$BOARD"
if [ ! -d "$BUILD_DIR" ]; then
echo "Error: build directory not found: $BUILD_DIR"
echo "Build first with: cd examples && cmake -DBOARD=$BOARD -G Ninja -B cmake-build-$BOARD .. && cmake --build cmake-build-$BOARD"
@@ -59,11 +67,12 @@ if [ -n "$BOARD" ]; then
copy_board_binaries "$BUILD_DIR"
else
echo "==> Copying all built binaries"
- for dir in "$SCRIPT_DIR"/examples/cmake-build-*/; do
+ for dir in "$ROOT_DIR"/examples/cmake-build-*/; do
[ -d "$dir" ] && copy_board_binaries "$dir"
done
fi
# Run test
+CONFIG_BASENAME="$(basename "$CONFIG")"
echo "==> Running HIL test on $REMOTE"
-ssh -t "$REMOTE" "cd $REMOTE_DIR && python3 -u test/hil/hil_test.py -B examples ${ARGS[*]} tinyusb.json"
+ssh -t "$REMOTE" "cd $REMOTE_DIR && python3 -u test/hil/hil_test.py -B examples ${ARGS[*]} test/hil/$CONFIG_BASENAME"