HIL: pinned openocd recovery flasher for J-Link boards, bounded reset_jlink
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 aflasher_recoverentry pinned withvid_pid(hil_flash.recover_flasher,:187). Bothhil_test.py:1558-1578gates 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) whilerecovery_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.
Source: hathach/tinyusb