2

I am using GNU gdb (GNU Tools for STM32 13.3.rel1.20240926-1715) 14.2.90.20240526-git connected to pyocd 0.39.0 with an STM32H573MIYxQ MCU. Normally I can set breakpoints in GDB and they work.

Sometimes I can't start GDB right at target power-up, so I reset the MCU (via physical reset pin) after starting GDB, in order to hit a breakpoint early in the application startup. This also works.

However some of my debugging setups don't have this physical pin, so I'd like to use a soft reset instead. Currently I use pyocd's target.reset() method. It definitely resets the target, but seems to cause breakpoints not to halt. GDB at first thinks the program has halted, but soon runs into trouble:

(gdb) break Sys.c:79
Breakpoint 2 at 0x8003894: file Sys.c, line 79.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) cont
Continuing.

[target.reset() invoked here by a separate path]

Breakpoint 2, Sys_Init () at Sys.c:79
79        if (!res)
(gdb) next
PC register is not available
(gdb)

pyocd gives a bit more characterization of the problem, by printing the following line soon after I type next in gdb:

ERROR:pyocd.coresight.cortex_m:cannot step: core not halted

What I take from this is that GDB was notified that the breakpoint was reached, but the MCU blew right past it (and continues running the application as if nothing had happened).

Does anyone have thoughts on what might cause the MCU to behave in this way?

Note: I've also tried target.reset_and_halt(); target.resume() and the result is the same. Also tried compiling the entire project with -O0 and -Og and the result is the same either way.

Update

I noticed that sometimes breakpoints still work after target.reset(). As a test, I set a delay after startup and before the breakpoint, and found a striking correlation between this delay and breakpoint operation:

10ms  - fail
50ms  - fail, fail
70ms  - fail
85ms  - fail, fail
90ms  - success, fail
95ms  - success, success
100ms - success, success

I can't think of anything in my application or pyocd scripts that would kick in after 90ms or so. I disabled all scripting actions except target.reset() and there is still this 90ms threshold. There are no interrupts in my application, nothing that would happen during this programmed wait. I tried the delay before or after peripheral initialization, but the effect is the same and the threshold is still around 90ms.

Update

Gemini suggested a partial workaround that seems to enable me to reset the target and hit early breakpoints:

(gdb) break Sys.c:79
Breakpoint 1 at 0x8003894: file Sys.c, line 79.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) monitor reset halt
Resetting target with halt
Successfully halted device on reset
(gdb) cont
Continuing.

Breakpoint 1, Sys_Init () at Sys.c:79
79        if (!res)
(gdb) next
80          INFO("SysInit() successful.");
(gdb)

The theory here is that the "GDB session" (maybe Gemini means the GDBserver module in pyocd?) needs to do something to "re-attach" but Gemini didn't give me details.

However it doesn't answer why target.reset() isn't working, and requires the reset command to be given from gdb rather than pyocd.

1
  • There are registers that control behavior of the hardware breakpoints. You need to enable them (both clocking the module and enabling it) to allow debugging and stepping from Flash (read-only memory). Have you investigated this or are you aware it is an issue? Trying to step through init code can be problematic as even in debug builds, the module clocking and enables can be toggled as the init code tries to setup the environment. Commented May 6 at 14:33

1 Answer 1

0

The failure only occurs after the breakpoint event, when GDB attempts to step and pyOCD reports that the core is not halted. This strongly suggests a loss of synchronization between the debug server and the target core state following a software‑initiated reset, rather than an issue with breakpoint or module clock enable.

This is further supported by the fact that monitor reset halt from GDB consistently works, whereas invoking target.reset() externally does not, indicating that the problem is related to debug session state re‑attachment and halt ownership rather than breakpoint configuration during init.

Sign up to request clarification or add additional context in comments.

Your Answer

Draft saved
Draft discarded

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.