STM32 gotchas
80.When processor stopped in debugger, peripherals (and DMA if used by those peripherals) keep running

As debuggers allow to stop code execution (whether "manually" upon pressing the appropriate "button", or at a previously set breakpoint) and display a static snapshot of memory (and peripheral registers') content, users sometimes expect that the whole mcu is in a completely stopped state. They may find with surprise, that a single step, or even just making the debugger to re-display content of memory or peripheral registers, results in large changes.

Explanation again lies in the SoC character of these chips. Debugger is part of the processor, and stopping execution means exactly that: the processor stops processing instructions. The rest of the chip still continues to do what it is set to do: clocks keep clocking, memory system keeps working (e.g. prefetch/caches keep prefetching/linefilling/evicting until they stop due to processor inactivity), peripheral keep working1.

Consider for example a fully configured UART, with its Rx set to trigger DMA, transferring received data to memory. As long as characters keep arriving at the UART_Rx pin, the UART receiver deserializes them, upon completion triggers the DMA which then moves them to the memory. This happens regardless of whether the processor is stopped by debugger or not.

As with some peripherals this would lead to surprising and hard to debug states, STM32 provide a mechanism to stop certain peripherals - usually timers, CAN, I2C, watchdogs - while the processor is stopped by debugger. This can be done by setting respective bits in DBGMCU_APBx_FZ or similarly named register in the MCU submodule of DBG module (ST is not good at maintaining register naming consistent across STM32 models).

This may also lead to a "reverse" surprise: some debuggers may have settings which allow to set bits in this register when connecting. If user of such debugger is not aware of that feature (or has used it, setting some of the bits, and later has forgotten about it), it may find by surprise that some peripheral is not working while the debugger is in stopped mode.


1. Don't confuse running peripheral with interrupt service routine (ISR) which is intended to serve it. When processor is stopped, the running peripheral keeps setting flags resulting in interrupts, but the ISR cannot be executed (so its actions cannot have visible consequences) as the processor is stopped. When single-stepping, the interrupt flags being set would result in ISR being entered immediately; this would in most practical cases prevent single-stepping non-interrupt code thus defeat the purpose of single-stepping, which is why debuggers have a switch in hardware wich prevents interrupts to be entered during single stepping (except in the flawed versions of Cortex-M7 core).