#3945·tinyusb

HIL: pinned openocd recovery flasher for J-Link boards, bounded reset_jlink

Author: hathachCreated Sep 21, 2026Updated Sep 21, 2026
LabelsPrio 📌followup

In-run HUNG recovery (test/hil/usbtest.py:649-700) only runs for a convoy-safe flasher: openocd pinned with vid_pid, or esptool (hil_flash.convoy_safe, test/hil/hil_flash.py:199). JLinkExe selects probes by serial, which opens every usbfs node and blocks on the wedged one, so J-Link boards skip recovery and stay wedged for the rest of the run and every run after (#3944).

Remaining work

  • Roster pass on test/hil/tinyusb.json: for every J-Link board whose probe openocd can drive, add a flasher_recover entry pinned with vid_pid (hil_flash.recover_flasher, :187). Both hil_test.py:1558-1578 gates read it already.
  • reset_jlink (test/hil/hil_flash.py:50-57) takes no timeout and inherits the default command timeout of 180 s (test/hil/helper/hil_util.py:92) while recovery_reserve() budgets 30 s for the reset (usbtest.py:47). Bound it before enabling recovery on those boards.
  • Boards that cannot take an openocd recovery flasher are listed as still unrecoverable until the shield primitive lands.

Verification

Per board: deliberate wedge on ci.lan under the board flock, hil_test.py -b <board>, expect the reset-first recovery in the log and a passing re-enumeration; report row shows the recovery outcome. One run each for a J-Link board with the new entry and an existing openocd board as the control.

Why deferred

Agreed in the 2026-09-21 HIL review with Codex as step two of five, after admission (#3944). It stays useful after the shield lands: a pinned openocd recovery avoids touching shared root-hub attributes at all.