mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
docs(superpowers): esp-target-debug design spec + executed implementation plan
Spec (brainstormed): own-skill backend decision, PHY-conflict map, six verification gates, external-JTAG TODO. Plan executed same-day: all gates run on the rig; apptrace resolved per its own gate rule as (untested).
This commit is contained in:
74
docs/superpowers/plans/2026-07-23-esp-target-debug-skill.md
Normal file
74
docs/superpowers/plans/2026-07-23-esp-target-debug-skill.md
Normal file
@ -0,0 +1,74 @@
|
||||
# esp-target-debug Skill Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Create `.claude/skills/esp-target-debug/SKILL.md` (Espressif built-in USB-Serial-JTAG debug backend) with every recipe verified on the rig's P4, the S3 PHY boundary verified both ways, plus pointer edits in `target-debug` and the `target-debugger` agent.
|
||||
|
||||
**Architecture:** Per spec `docs/superpowers/specs/2026-07-23-esp-target-debug-design.md`. Verification-first: hardware gates 1–6 run before the skill text lands, so only proven content ships unmarked. One lock session per board.
|
||||
|
||||
**Tech Stack:** ESP-IDF at `$HOME/code/esp-idf` (`export.sh` → `openocd-esp32`, `riscv32-esp-elf-gdb`, `xtensa-esp32s3-elf-gdb`, `esptool.py`), rig boards `espressif_p4_function_ev` (uid 6055F9F98715), `espressif_s3_devkitm` (uid 84F703C084E4).
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Worktree `/home/hathach/code/tinyusb/.claude/worktrees/improve-debug-skill-agent`, branch `claude/improve-debug-skill-agent`.
|
||||
- Board-lock discipline per `hil` skill; reflash pristine firmware before release; evidence (command + output snippet) in commit message bodies.
|
||||
- Formatting: aligned table columns, skill-name-only cross-references.
|
||||
- Unverified content ships tagged `(untested)` or not at all.
|
||||
- Espressif anything requires `. $HOME/code/esp-idf/export.sh` in that shell first.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: P4 recon + coexistence gate (spec gates 1)
|
||||
|
||||
- [x] **Step 1: Environment + firmware recon**
|
||||
|
||||
```bash
|
||||
ls $HOME/code/esp-idf/export.sh && source $HOME/code/esp-idf/export.sh && which openocd riscv32-esp-elf-gdb
|
||||
ls /home/hathach/code/tinyusb/examples/cmake-build-espressif_p4_function_ev 2>/dev/null || echo "no prebuilt"
|
||||
lsusb -d 303a:1001 # USB-SJ devices present
|
||||
```
|
||||
If no prebuilt firmware: build `device/cdc_msc_freertos` for the P4 (`idf.py -DBOARD=espressif_p4_function_ev build` in that example, per CLAUDE.md), else use the prebuilt binary. Identify the ELF path for gdb symbolization.
|
||||
|
||||
- [x] **Step 2: Lock P4, ensure known firmware, confirm DUT traffic**
|
||||
|
||||
```bash
|
||||
python3 test/hil/board_lock.py hold espressif_p4_function_ev --reason "esp-target-debug verify: coexistence"
|
||||
# flash known build (esptool/idf.py flash -p <port-by-uid>), settle, then confirm enumeration:
|
||||
lsusb | grep -i cafe # TinyUSB VID on the DUT port
|
||||
# generate traffic: echo > /dev/ttyACM<N> of the cdc, or timeout 5s cat
|
||||
```
|
||||
|
||||
- [x] **Step 3: Attach openocd over USB-SJ while the device runs**
|
||||
|
||||
```bash
|
||||
openocd -f board/esp32p4-builtin.cfg -c 'adapter serial 6055F9F98715' & # gdb :3333
|
||||
riscv32-esp-elf-gdb -batch -ex 'target extended-remote :3333' -ex 'monitor halt' \
|
||||
-ex bt -ex 'monitor resume' <p4 elf>
|
||||
```
|
||||
Expected: backtrace with symbols; after resume the CDC device still answers (re-run the traffic check). Record: does the DUT drop off the bus during halt (host URB timeouts — expected per target-debug) and does it recover on resume without re-enumeration?
|
||||
|
||||
- [x] **Step 4: Release-or-continue checkpoint** — keep the lock for Task 2 (same session). No commit yet; evidence to `/tmp/esp_evidence.txt`.
|
||||
|
||||
### Task 2: P4 budget, watchpoint, threads, console (spec gates 2–4)
|
||||
|
||||
- [x] **Step 1: Breakpoint/watchpoint budget** — RISC-V trigger count: in gdb `monitor riscv info` or set watchpoints until rejection; verify a hardware watchpoint on a TinyUSB variable (e.g. `watch -l` on a usbd counter) reports and hits.
|
||||
- [x] **Step 2: FreeRTOS threads** — `info threads` after halt; expect ESP-IDF tasks incl. the USB task; note whether it works at attach or needs run→stop (mirror the ARM finding).
|
||||
- [x] **Step 3: Console during traffic** — capture the USB-SJ console tty (the 303a:1001 CDC function) for a few seconds while DUT traffic runs; expect ESP-IDF log lines. Record the /dev node mapping by serial.
|
||||
- [x] **Step 4: Reflash pristine, release P4 lock.** Evidence appended to `/tmp/esp_evidence.txt`.
|
||||
|
||||
### Task 3: P4 apptrace spike — GATED (spec gate 5)
|
||||
|
||||
Budget 30 min. `openocd -c 'esp apptrace start ...'` against a firmware built with apptrace enabled? Stock HIL firmware has no apptrace init — if a code change would be required, that's the gate answer: land apptrace as `(untested — needs CONFIG_APPTRACE + firmware init)` with the recipe sketch. Only a working capture lands unmarked.
|
||||
|
||||
### Task 4: S3 boundary (spec gate 6)
|
||||
|
||||
- [x] **Step 1: Lock S3, flash `board_test`** (no TinyUSB → PHY free). Attach `openocd -f board/esp32s3-builtin.cfg -c 'adapter serial 84F703C084E4'` + `xtensa-esp32s3-elf-gdb`: halt + bt works.
|
||||
- [x] **Step 2: Flash a USB device example** — record the exact failure: does 303a:1001 vanish from lsusb (PHY switched), does openocd fail to attach or die mid-session? Capture verbatim error.
|
||||
- [x] **Step 3: Reflash pristine (a USB example — that is the CI-expected state), release.**
|
||||
|
||||
### Task 5: Write the skill + integration edits + commit
|
||||
|
||||
- [x] **Step 1: Write `.claude/skills/esp-target-debug/SKILL.md`** per spec section order (role/defer, PHY map with verified boundary symptoms, toolchain+attach with the real commands from Tasks 1–4, technique mapping table with verified annotations, rig deltas, external-JTAG TODO). Aligned tables.
|
||||
- [x] **Step 2: `target-debug` pointer** (2 lines, after probe-mapping bullets) + `target-debugger` agent table row.
|
||||
- [x] **Step 3: pre-commit, single commit** with evidence summary from `/tmp/esp_evidence.txt`.
|
||||
- [x] **Step 4: Retrieval sanity** — one fresh-subagent scenario: "debug a TinyUSB hang on the rig's P4" routes to esp-target-debug (not JLink recipes); "same on S3 while cdc_msc runs" routes to the PHY boundary + external-JTAG TODO.
|
||||
102
docs/superpowers/specs/2026-07-23-esp-target-debug-design.md
Normal file
102
docs/superpowers/specs/2026-07-23-esp-target-debug-design.md
Normal file
@ -0,0 +1,102 @@
|
||||
# esp-target-debug Skill Design
|
||||
|
||||
Backend skill for debugging TinyUSB firmware on Espressif targets (rig:
|
||||
`espressif_p4_function_ev`, `espressif_s3_devkitm`) via the chips' **built-in
|
||||
USB-Serial-JTAG**, with external JTAG documented as a TODO until the rig has
|
||||
an adapter. Companion to `target-debug`, which keeps the architecture-neutral
|
||||
methodology (intrusiveness ladder, board locks, dual-side capture, diagnosis
|
||||
standards) — this skill is the Espressif toolchain/probe backend, the same
|
||||
boundary that makes `usb-kernel-debug` its own skill.
|
||||
|
||||
## Goals
|
||||
|
||||
- An agent can attach, halt, backtrace, set breakpoints/watchpoints, list
|
||||
FreeRTOS threads, and capture logs on the rig's P4 **while TinyUSB device
|
||||
traffic is live** — every recipe hardware-verified before landing unmarked
|
||||
(the `target-debug` ethos).
|
||||
- The S3's USB-SJ/OTG PHY conflict is mapped precisely, not hand-waved:
|
||||
verified working via `board_test` (TinyUSB off — PHY free), verified failure
|
||||
mode with a USB device example, external-JTAG escape hatch documented as
|
||||
TODO.
|
||||
|
||||
## Non-goals (deferred)
|
||||
|
||||
- External JTAG bring-up (no adapter on the rig) — TODO section with S3 JTAG
|
||||
pin notes (GPIO39-42) and openocd-esp32 adapter support pointers.
|
||||
- Xtensa/S3 full parity under live USB traffic (needs external JTAG).
|
||||
- ETM-class instruction trace; SystemView tooling beyond an apptrace spike.
|
||||
|
||||
## Architecture
|
||||
|
||||
New skill `.claude/skills/esp-target-debug/SKILL.md`; two integration edits:
|
||||
|
||||
- `target-debug` gains a 2-line pointer under the probe-mapping bullets:
|
||||
Espressif boards use a different toolchain, probe model, and trace story —
|
||||
read `esp-target-debug`.
|
||||
- `target-debugger` agent table gains an `esp-target-debug` row (name-only,
|
||||
aligned columns, per the established conventions).
|
||||
|
||||
Skill content (order):
|
||||
|
||||
1. **Role + defer line** — methodology lives in `target-debug`; this file is
|
||||
the Espressif backend. Built-in USB-SJ now; external JTAG TODO.
|
||||
2. **PHY-conflict map** —
|
||||
- S3: USB-SJ and OTG share one PHY (GPIO19/20). TinyUSB claiming the PHY
|
||||
drops JTAG-over-USB mid-session: JTAG works for non-USB examples
|
||||
(`board_test`), dies for USB device examples (verified boundary, exact
|
||||
symptom recorded). External JTAG = the future escape hatch (TODO).
|
||||
- P4: OTG-HS has a dedicated HS PHY; USB-SJ is separate — JTAG and the
|
||||
TinyUSB DUT port coexist (verified). USB-SJ doubles as a live log
|
||||
console during device traffic — the TU_LOG-equivalent channel.
|
||||
3. **Toolchain & attach** — `. $HOME/code/esp-idf/export.sh` provides
|
||||
`openocd-esp32` + `riscv32-esp-elf-gdb` (P4) / `xtensa-esp32s3-elf-gdb`
|
||||
(S3). Rig path is raw openocd (HIL firmware isn't an idf project on disk):
|
||||
`openocd -f board/esp32p4-builtin.cfg` with `adapter serial <uid>` (USB-SJ
|
||||
is VID 303A:1001; uid = the `flasher.uid` already in `tinyusb.json`), gdb
|
||||
on :3333. `idf.py openocd` / `idf.py gdb` noted for idf-project work.
|
||||
4. **Technique mapping table** (aligned) — ARM technique → Espressif
|
||||
equivalent:
|
||||
|
||||
| target-debug technique | Espressif backend |
|
||||
|---|---|
|
||||
| GDB autopsy, bp/wp | same flow; RISC-V trigger module (P4) / Xtensa 2 bp + 2 wp (S3); budget read verified on P4 |
|
||||
| Vector catch | none — breakpoint the panic handler; decode `mcause`/`mepc`/`mtval` (P4) |
|
||||
| SWO / DWT data trace | none — apptrace over JTAG is the analog (gated spike; lands `(untested)` if it fails) |
|
||||
| RTT / TU_LOG | USB-SJ console — on P4 it coexists with DUT traffic |
|
||||
| FreeRTOS threads | native in openocd-esp32 — `info threads` out of the box |
|
||||
| verifybin | `esptool.py verify_flash` |
|
||||
|
||||
5. **Rig discipline deltas** — same `board_lock.py` protocol; flasher is
|
||||
esptool (serial-port-by-uid); reflash pristine before release; one client
|
||||
per USB-SJ device.
|
||||
6. **External JTAG — TODO** — S3 JTAG pins, adapter classes openocd-esp32
|
||||
supports, and the efuse caveat (JTAG pin selection), unverified.
|
||||
|
||||
## Verification gates (execution order)
|
||||
|
||||
All under board locks, serial, evidence in commit messages:
|
||||
|
||||
1. **P4 coexistence (headline)**: flash a device example, confirm enumeration
|
||||
+ traffic on the DUT port, then attach openocd+gdb over USB-SJ →
|
||||
halt, `bt`, resume — device stays functional after resume.
|
||||
2. **P4 budget**: read trigger/watchpoint counts via openocd/gdb; set a
|
||||
hardware watchpoint on a TinyUSB variable, confirm hit.
|
||||
3. **P4 threads**: `info threads` lists ESP-IDF tasks (usbd task visible).
|
||||
4. **P4 console**: capture USB-SJ console log output during device traffic.
|
||||
5. **P4 apptrace spike (gated)**: bounded attempt; verified recipe or
|
||||
`(untested)` tag.
|
||||
6. **S3 boundary**: `board_test` flashed → attach works (halt+bt); then a USB
|
||||
device example → record the exact JTAG failure symptom when the PHY
|
||||
switches. No further S3 work (external JTAG TODO).
|
||||
|
||||
## Constraints
|
||||
|
||||
- Worktree `claude/improve-debug-skill-agent`; commit per gate; pre-commit
|
||||
before each; no Co-Authored-By trailers.
|
||||
- Formatting conventions already established: aligned table columns,
|
||||
skill-name-only cross references, bullets over run-on paragraphs.
|
||||
- Espressif builds need `export.sh` first (CLAUDE.md); P4/S3 examples build
|
||||
via idf.py — reuse existing HIL-built firmware where possible instead of
|
||||
rebuilding.
|
||||
- Hardware-verify-before-landing: unverified content ships tagged
|
||||
`(untested)` or not at all.
|
||||
Reference in New Issue
Block a user