STM32 gotchas
19.Debugger keeps jumping into interrupt when single stepping

Of the features of debugger perceived by users as one of the most useful, is the ability to stop at breakpoints or upon command from the host PC, and then single-step code and observe changes as individual code lines are executed. Of course this has limitations, especially when it comes to optimized code; most users are aware of that and we are not going to discuss these principial limitations here.

Now during single-stepping, the processor is stopped between the individual steps. However, only the code execution in the processor itself is stopped, the rest of the mcu - its peripherals and interconnections - keep ticking and working1. So, most of the interrupt sources work, too, and indeed, they trigger interrupts in NVIC. This would make the program very likely jump directly into an interrupt when taking the first step, and that would make the whole single-stepping unusable. To avoid this, the built-in debugging interface (which is part of the processor core) has a direct link to NVIC (which is also part of the processor core), using which it can disable interrupts while the processor is stopped and is being single-stepped.

Unfortunately, this link is broken in the early versions of the Cortex-M7 (revision r0p1), see erratum #702596 in ARM's Cortex-M7 (AT610) and Cortex-M7 with FPU (AT611) Software Developer Errata Notice. In mcus using this revision of Cortex-M7, single-stepping is a pain, and users have to jump through hoops (essentially stopping all interrupts and/or avoiding connecting peripherals causing them) to be able to single-step some particularly intricate piece of code. Debugger makers also tried hard to work around the problem (see e.g. here and here), basically by issuing a global interrupt disable when the processor is stopped before single-stepping; however, contrary to the direct link between the debugging interface and NVIC, here it takes time until the host PC issues the interrupt disable command and it propagates all the way through NVIC, so if an interrupt happens to trigger in that time window, the first single-step steps into that ISR anyway, so the outward experience may be of a not very reliable operation.

In STM32, only the first Cortex-M7-based model, the 'F746 (and its crypt-enabled counterpart 'F756) are affected by this bug. The 'F72x and 'F76x subfamilies, as well as the 'H7 family, use newer revisions of the processor core, where the bug has already been fixed.

1. Timers and some other peripherals can be made to stop during debugging by settings in DBGMCU registers, but that's another story. That indirectly can mitigate issues with timer-based interrupts. There are still many interrupt sources e.g. external interrupts, which generally can't be avoided during single-stepping.