From be86281b81b70adc1ce3746d620c912bf032fac2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Aug 2026 16:45:32 +0700 Subject: hil-pool-check: document the probe power-cycle escalation; name the env script directly A probe whose firmware has wedged reports flash-failed with the probe present and "probe toggle unconfirmed". The tool's own recovery cannot fix that: an authorized toggle re-enumerates but never removes power, and hil_pool_check.py:304 already notes that ST-Link, WCH-Link, CP210x and picoprobe keep their sysfs kobject across one. So the check correctly gives up, and the operator was left to invent the next rung. Write it down, as what this rig's hardware actually does rather than what uhubctl advertises: the Renesas cards list their root hubs as ppps-capable but do not implement it (owner-confirmed - VBUS never drops, only D+/D-), so a root-port cycle is a harder forced re-enumeration that a wedged probe can ride out, worth exactly one attempt; and the AMD 0000:02:00.0, where the WCH-Links live, has no port-power switching at all - nothing to cycle, straight to a physical replug. Which card a probe hangs off decides which case applies, so the procedure starts from readlink. The ordering rules encode the shared-rig protocol: let the full run finish (a bounce re-enumerates siblings and corrupts checks still in flight), hold --all with this host's --config before the cycle (hil_lock.py hold validates nothing against the roster and nothing maps a sysfs busport to a board name, so a narrower hand-listed hold reserves nothing while reporting success - and --all defaults to tinyusb.json, which on the tusb rig would reserve 27 boards that do not exist there), release BEFORE the re-check (hil_pool_check.py self-locks every board it checks, so a hold still in place makes the verification report locked against your own hold and verify nothing), and drive the cycle through usb_recover.sh root-cycle by its full in-repo path - it is on no PATH and sudo's secure_path excludes the checkout. Never a bare `uhubctl -a cycle`: without -S it writes sysfs disable, whose disable_store takes the root hub's lock uninterruptibly and then usb_disconnect()s the wedged child - the one input that turns a probe wedge into a bus-wide wedge. Give the script the wedged probe's own busport, not the hub path: the serial guard and the success check both read the path you pass, and the hub's inode always changes when its own port cycles. Reporting asks for both passes: a final table showing every board healthy hides that a probe needed power-cycling to get there, which is the signal that it will recur. Also: the ESP-IDF env hints name `. $HOME/code/esp-idf/export.sh` instead of the `get-idf` alias, which lives only in interactive shells and fails from scripts. --- .claude/skills/hil-pool-check/SKILL.md | 75 +++++++++++++++++++++++++++++++++- test/hil/helper/hil_pool_check.py | 6 ++- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/.claude/skills/hil-pool-check/SKILL.md b/.claude/skills/hil-pool-check/SKILL.md index 6a8f66087..3c056c16b 100644 --- a/.claude/skills/hil-pool-check/SKILL.md +++ b/.claude/skills/hil-pool-check/SKILL.md @@ -41,7 +41,10 @@ ssh ci.lan 'bash -lc "cd ~/code/tinyusb && python3 test/hil/helper/hil_pool_chec Missing firmware is **built on the spot** — never skipped (`--no-build` opts out; those boards then report `flash-failed`). Builds need the family env, exported on the rig in `~/.profile`/`~/.bashrc`: `PICO_SDK_PATH` for rp2040/rp2350 (`~/code/pico/pico-sdk`), the -ESP-IDF env (`get-idf`) for espressif — which also needs `esptool` on PATH (pip's +ESP-IDF env for espressif — source it as `. $HOME/code/esp-idf/export.sh`, NOT as `get-idf`: +that is an interactive shell alias (`~/.bashrc`), and aliases are not expanded in non-interactive +shells, so scripts and agents get `get-idf: command not found` even under `bash -lc`. It also +needs `esptool` on PATH (pip's `~/.local/bin/esptool`; a non-login shell may lack it — run via `bash -lc`). An explicit `-B` is searched exclusively for *existing* firmware; builds still land in `cmake-build/` and are noted `built `. Espressif boards park too when the IDF env is present. A first run on an @@ -57,8 +60,78 @@ are *unverified*, not healthy — read the footer, not just `$?`. A `⚠ pid … means stale firmware or a silent flash no-op (J-Link lore); a device off the bus entirely needs the usb-kernel-recover skill or a physical replug. +## When the tool's probe recovery fails + +`flash-failed` with the probe ✅ present and a `probe toggle unconfirmed` note means the probe's +own firmware is wedged, not the board. The tool's recovery is an `authorized` toggle, which is a +USB re-enumeration and never removes power, so probes that keep their sysfs kobject across it +(ST-Link, WCH-Link, CP210x, picoprobe) survive the toggle still wedged. Confirm with the flasher's +own list — `STM32_Programmer_CLI -l st-link`, or `JLinkExe -CommandFile