Skip to content

stlink-lib: Disarm vector-catch-on-reset on debug detach#1500

Merged
Nightwalker-87 merged 1 commit into
stlink-org:testingfrom
jameswalmsley:jw/fix-reset-vector-catch
Jul 10, 2026
Merged

stlink-lib: Disarm vector-catch-on-reset on debug detach#1500
Nightwalker-87 merged 1 commit into
stlink-org:testingfrom
jameswalmsley:jw/fix-reset-vector-catch

Conversation

@jameswalmsley

@jameswalmsley jameswalmsley commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

st-flash --connect-under-reset arms DEMCR.VC_CORERESET (halt-on-reset) via stlink_soft_reset(). That bit lives in the debug power domain and survives NRST, so once armed the core halts at its reset vector on every reset -- including NVIC_SystemReset() from firmware and the board's reset button -- which makes a freshly flashed board appear bricked until it is power-cycled.

stlink_exit_debug_mode() only wrote DHCSR.DBGKEY on detach and never cleared the vector catch. Worse, that write (and thus any cleanup) was gated behind core_stat != TARGET_RESET, which is precisely the state connect-under-reset leaves the target in -- so the cleanup was skipped exactly when it was needed.

Split the two: keep the DBGKEY write gated on core_stat, but always disarm DEMCR.VC_CORERESET (when a target was identified), preserving the other DEMCR bits and clearing the stale DFSR.VCATCH status. The DEMCR read return already guards against a dead debug link; a failed disarm write is logged via WLOG rather than failing the detach.

This mirrors the existing AP1 flash-size fallback, which already disarms VC_CORERESET.

(Closes #1489)

st-flash --connect-under-reset arms DEMCR.VC_CORERESET (halt-on-reset) via
stlink_soft_reset(). That bit lives in the debug power domain and survives
NRST, so once armed the core halts at its reset vector on *every* reset --
including NVIC_SystemReset() from firmware and the board's reset button --
which makes a freshly flashed board appear bricked until it is power-cycled.

stlink_exit_debug_mode() only wrote DHCSR.DBGKEY on detach and never cleared
the vector catch. Worse, that write (and thus any cleanup) was gated behind
core_stat != TARGET_RESET, which is precisely the state connect-under-reset
leaves the target in -- so the cleanup was skipped exactly when it was needed.

Split the two: keep the DBGKEY write gated on core_stat, but always disarm
DEMCR.VC_CORERESET (when a target was identified), preserving the other DEMCR
bits and clearing the stale DFSR.VCATCH status. The DEMCR read return already
guards against a dead debug link; a failed disarm write is logged via WLOG
rather than failing the detach.

This mirrors the existing AP1 flash-size fallback, which already disarms
VC_CORERESET.

Signed-off-by: James Walmsley <james@fullfat-fs.co.uk>
@Nightwalker-87 Nightwalker-87 changed the title common: disarm vector-catch-on-reset on debug detach [stlink-lib] Disarm vector-catch-on-reset on debug detach Jul 10, 2026
@Nightwalker-87 Nightwalker-87 changed the title [stlink-lib] Disarm vector-catch-on-reset on debug detach stlink-lib: Disarm vector-catch-on-reset on debug detach Jul 10, 2026
@Nightwalker-87 Nightwalker-87 merged commit 0f3f721 into stlink-org:testing Jul 10, 2026
12 checks passed
@stlink-org stlink-org locked as resolved and limited conversation to collaborators Jul 10, 2026
@jameswalmsley jameswalmsley deleted the jw/fix-reset-vector-catch branch July 10, 2026 19:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Calling NVIC_SystemReset post flashing with st-flash causes STM32 MCU to hang

2 participants