Skip to content

Add rescue lane for targets whose firmware steals the SWD pins#119

Open
sensoryelectronics wants to merge 1 commit into
ch32-rs:mainfrom
sensoryelectronics:rescue-attach
Open

Add rescue lane for targets whose firmware steals the SWD pins#119
sensoryelectronics wants to merge 1 commit into
ch32-rs:mainfrom
sensoryelectronics:rescue-attach

Conversation

@sensoryelectronics

Copy link
Copy Markdown

Problem

On boards where the debug pins are muxed with a peripheral that the running firmware enables, the target becomes permanently undebuggable: AttachChip is refused with protocol error 0x55 within milliseconds of every boot, and the condition survives power cycles because it lives in flash.

Concrete case: the WeAct nanoCH32H417 routes SWCLK/SWDIO to PB8/PB9, which are also USB2 D+/D-. Flashing any USBHS device firmware kills SWD on the next boot — every subsequent attach fails 0x55, through replugs, full power-offs, and probe mode-switch round-trips. The same trap exists for CH32V003 users who remux SWIO as GPIO.

What this adds

  • wlink reset force — fires the raw 0x0b reset ladder (chip/soft/normal) without attaching. Diagnostic: separates probe-alive from target-unresponsive (the resets are visibly acknowledged by the board while attach still refuses).
  • wlink reset rescue and a global --rescue flag — hammers AttachChip for 15 s while the operator taps the target RESET, catching the brief post-reset window before user code runs, then immediately halts the core. With the global flag, any command (flash, erase, dump) can attach this way.
  • ProbeSession::reset_mcu_and_halt() — ndmreset with haltreq held, so the caught core comes back with clean peripheral/clock state while still never executing a user instruction (activated from the commented reference block).
  • wlink erase --method dmi — erases the first 64 K via direct FLASH-register access over DMI (also activated from the reference block; register map verified against the CH32H417 RM ch. 46). Needed because the probe firmware's own flash stub aborts (fastprogram 0x05) on a rescue-halted core; blanking the vectors kills the pin-stealing firmware permanently, after which the normal attach + flash lane works again.
  • Rescue sessions skip unprotect_flash — its reattach_chip() detaches (resuming the CPU), which re-steals the pins mid-operation.

Field test

Recovered a nanoCH32H417 (CH32H417QEU, ChipID 0x4170052d) that USBHS CDC firmware had made undebuggable: --rescue attach caught the boot window on the first try, erase --method dmi blanked the vectors, and a plain wlink flash then restored the board. Attach has been reliable since.

🤖 Generated with Claude Code

On boards where the debug pins are muxed with a peripheral the running
firmware enables (e.g. nanoCH32H417: PB8/PB9 = SWCLK/SWDIO = USB2 D+/D-),
AttachChip is refused with protocol error 0x55 within milliseconds of
every boot, and the condition survives power cycles because it lives in
flash. This adds the tooling to recover such a target without ISP:

- `reset force`: fire the raw 0x0b reset ladder without attaching
  (diagnoses probe-alive vs target-unresponsive)
- `reset rescue` + global `--rescue`: hammer AttachChip for 15 s while
  the operator taps the target RESET, catching the boot window, then
  halt the core before user code runs; any command (flash, erase, dump)
  can attach this way
- ProbeSession::reset_mcu_and_halt(): ndmreset with haltreq held, so the
  caught core comes back with clean peripheral state but never executes
  a user instruction (activated from the commented reference block)
- `erase --method dmi`: erase the first 64K via direct FLASH-register
  access over DMI (activated from the reference block; verified against
  the CH32H417 RM ch46 register map) - the probe's own flash stub fails
  on a rescue-halted core, and blanking the vectors permanently frees
  the SWD pins
- rescue sessions skip unprotect_flash (its reattach resumes the CPU,
  which re-steals the pins mid-operation)

Field-tested on a nanoCH32H417 whose USBHS CDC firmware had made the
board undebuggable: rescue attach + DMI erase + normal reflash restored
the stock debug lane.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant