Describe the bug
When ending a Cortex-Debug session that uses pyOCD, a hardware breakpoint can remain programmed in the target's FPB comparator even though Cortex-Debug has issued break-delete and GDB reports success.
This reproduces with both Stop and Disconnect and Suspend. After the debug session has ended, asserting the board's hardware NRST still causes the target to halt at the old breakpoint. A later non-initializing SWD diagnostic read shows that the halt is a breakpoint event and that the old FPB comparator remains enabled.
As a diagnostic control, I manually issued a DAP disconnect request equivalent to:
{
"terminateDebuggee": false,
"suspendDebuggee": false
}
This exact plain-disconnect action is not exposed by the VS Code UI in this setup. It follows the detach path and does not reproduce the issue. This is evidence that distinguishes the two shutdown paths, not a user-accessible UI workaround.
Steps to reproduce
- Start a Cortex-Debug session using
"servertype": "pyocd" and a CMSIS-DAP probe.
- Set a code breakpoint and continue until it is hit.
- End the session using Stop or Disconnect and Suspend.
- Assert hardware NRST after the debug session has ended.
- Observe that the target halts again at the old breakpoint location.
- Read the Cortex-M debug registers without target initialization. The stale FPB comparator is still enabled.
Expected behavior
All breakpoint removals should be committed to the target before the managed pyOCD process is terminated. After the session ends, no FPB comparator from that session should remain enabled, and NRST should not cause the target to halt at the old breakpoint.
Observed command sequence
The following is a shortened and sanitized sequence. Probe identifiers have been removed.
VS Code -> disconnect { terminateDebuggee: true }
Cortex-Debug -> <N>-break-delete
GDB -> <N>^done
GDB -> pyOCD: z1,<BREAKPOINT_ADDRESS>,2
pyOCD -> GDB: OK
Cortex-Debug -> terminates the managed pyOCD server process
No subsequent breakpoint insertion was observed after break-delete.
The evidence suggests that pyOCD updates its pending breakpoint state and replies OK, but the physical write that clears FP_COMP is not flushed before the process is terminated.
Hardware register evidence
After the session had ended and hardware NRST had been asserted, a non-initializing diagnostic read showed:
PC = 0x08000804
DFSR.BKPT = 1
FP_COMP0 = 0x08000805
After explicitly clearing the stale comparator, a second read showed no enabled FPB comparator and the old breakpoint no longer remained.
Related issues
Environment
- OS: Windows 11
- VS Code: 1.125.1
- Cortex-Debug: 1.12.1
- pyOCD: 0.45.1
- Arm GNU GDB: GNU Tools for STM32 13.3.rel1.20240926-1715 / GDB 14.2.90.20240526-git
- Target: STM32C552CCU6 / Cortex-M33
- Probe: CMSIS-DAP; serial number intentionally omitted
- Session request: attach
Additional logs
Full sanitized Cortex-Debug, pyOCD, and GDB RSP traces can be provided if needed. Probe identifiers, user names, and local paths will be omitted.
Could Cortex-Debug allow the managed pyOCD process to complete its graceful cleanup before force termination, or use a pyOCD-specific graceful termination mechanism? If the current termination sequence is intentional, please confirm so the same trace can be followed up in pyOCD.
Describe the bug
When ending a Cortex-Debug session that uses pyOCD, a hardware breakpoint can remain programmed in the target's FPB comparator even though Cortex-Debug has issued
break-deleteand GDB reports success.This reproduces with both Stop and Disconnect and Suspend. After the debug session has ended, asserting the board's hardware NRST still causes the target to halt at the old breakpoint. A later non-initializing SWD diagnostic read shows that the halt is a breakpoint event and that the old FPB comparator remains enabled.
As a diagnostic control, I manually issued a DAP
disconnectrequest equivalent to:{ "terminateDebuggee": false, "suspendDebuggee": false }This exact plain-disconnect action is not exposed by the VS Code UI in this setup. It follows the detach path and does not reproduce the issue. This is evidence that distinguishes the two shutdown paths, not a user-accessible UI workaround.
Steps to reproduce
"servertype": "pyocd"and a CMSIS-DAP probe.Expected behavior
All breakpoint removals should be committed to the target before the managed pyOCD process is terminated. After the session ends, no FPB comparator from that session should remain enabled, and NRST should not cause the target to halt at the old breakpoint.
Observed command sequence
The following is a shortened and sanitized sequence. Probe identifiers have been removed.
No subsequent breakpoint insertion was observed after
break-delete.The evidence suggests that pyOCD updates its pending breakpoint state and replies
OK, but the physical write that clearsFP_COMPis not flushed before the process is terminated.Hardware register evidence
After the session had ended and hardware NRST had been asserted, a non-initializing diagnostic read showed:
After explicitly clearing the stale comparator, a second read showed no enabled FPB comparator and the old breakpoint no longer remained.
Related issues
z1,FP_COMP, or stale hardware-breakpoint evidence.Environment
Additional logs
Full sanitized Cortex-Debug, pyOCD, and GDB RSP traces can be provided if needed. Probe identifiers, user names, and local paths will be omitted.
Could Cortex-Debug allow the managed pyOCD process to complete its graceful cleanup before force termination, or use a pyOCD-specific graceful termination mechanism? If the current termination sequence is intentional, please confirm so the same trace can be followed up in pyOCD.