cancel
Showing results for 
Search instead for 
Did you mean: 

DBGMCU: The STM32 Debug Superpower You’re Probably Not Using

__Mohamed__Ayman__Dev
Associate II

Red and Yellow Bold Portrait Album Cover_00000.png

 

DBGMCU is the STM32 debug controller that lets the debugger stay useful while the MCU is sleeping/stopped/standby and provides “freeze” bits so peripherals (timers, watchdogs, I²C timeouts…) stop when the core is halted — great to inspect state and avoid unwanted resets during breakpoints. Always check your chip’s RM because register names & behavior vary by family.

 

Purpose & when to use it

  • Keep debug access in low-power modes. If your MCU enters Sleep/Stop/Standby and you still want to attach or keep the debugger alive, set DBGMCU low-power debug bits so the debug clocks stay available. Without this you may lose the debug connection or be forced to connect under reset (which destroys runtime state).

  • Freeze peripherals during a halt. When you hit a breakpoint, you often want timers, watchdogs, DMA timeouts, RTC, I²C SMBus timeouts etc. to be frozen — DBGMCU provides APB/AHB freeze registers for that (so peripheral clocks are gated or counters paused while core is halted).

 

The key registers & bits (conceptual)

Names and layout differ across families, but conceptually:

  1. DBGMCU_CR (or similar) — contains low-power debug bits:

    • DBG_SLEEP — keep debug in SLEEP mode

    • DBG_STOP — keep debug in STOP mode

    • DBG_STANDBY — keep debug in STANDBY mode
      Setting these allows debug access / appropriate clocking while in those low-power states.

  2. DBGMCU_APBxFZ / DBGMCU_AHBxFZ / APB1FZR1 / APB1LFZ1 / APB3FZ1 ... — freeze registers that contain bits such as:

    • DBG_TIM2_STOP, DBG_TIM3_STOP, ... — freeze timer counters when core halted

    • DBG_IWDG_STOP, DBG_WWDG_STOP — freeze watchdogs

    • DBG_RTC_STOP / DBG_I2C*_STOP — freeze RTC or SMBus timeouts
      The register names and bit positions vary by series (F0/F1/F3/F4/L4/H7/U5/...); HAL/LL provides macros.

Rule: Always open your device RM (Reference Manual) and search “DBGMCU” and “debug” chapters — they show exact register names for your part.

 

Common HAL / LL macros

ST HAL/LL already wrap these; use them when you want readable code that follows family conventions.

Example (HAL style; works on F4/L4 families with the Cube HAL):

// Enable debug during low-power modes
__HAL_RCC_DBGMCU_CLK_ENABLE();      // make sure DBGMCU APB clock is enabled (if required)
HAL_DBGMCU_EnableDBGSleepMode();   // enable debug in Sleep (or)
HAL_DBGMCU_EnableDBGStopMode();    // enable debug in Stop
HAL_DBGMCU_EnableDBGStandbyMode(); // enable debug in Standby

// Freeze TIM2 and IWDG while core halted
__HAL_DBGMCU_FREEZE_TIM2();        // macro sets DBGMCU->APB1FZ |= DBGMCU_APB1FZ_DBG_TIM2_STOP
__HAL_DBGMCU_FREEZE_IWDG();        // freeze IWDG (if supported)

Or LL (Low-Layer), which is explicit and available on many families:

LL_DBGMCU_EnableDBGSleepMode();
LL_DBGMCU_EnableDBGStopMode();
LL_DBGMCU_EnableDBGStandbyMode();

Use the corresponding Disable... calls to revert. These HAL/LL helpers are implemented in the Cube packages.

 

Direct register examples

(portable pattern — check register names for your RM)

This is a generic direct-register approach (replace bit names with the exact ones in your RM):

// Example: enable debug in Stop and Sleep modes (pseudo / family-dependent names)
DBGMCU->CR |= (DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY);

// Example: freeze TIM2 and I2C1 timeouts on halt
DBGMCU->APB1FZ |= (DBGMCU_APB1FZ_DBG_TIM2_STOP | DBGMCU_APB1FZ_DBG_I2C1_STOP);

Important: exact register field names differ (APB1FZ, APB1FZR1, APB1LFZ1, APB3FZ1, etc.). Use the RM or the <family>xx_hal.h macros to avoid typos.

 

Practical examples & scenarios

A — You lose debugger when MCU goes to STOP

Symptom: the debug probe disconnects or cannot halt the CPU after STOP.
Fix: before entering STOP, enable DBG_STOP (via HAL/LL or DBGMCU->CR). That keeps an internal RC oscillator / debug clock path active so the debug interface can reattach without resetting the part. (Family notes: on some parts the debugger still needs to set these bits; some debuggers do it automatically.)

B — You want to inspect timer registers when hitting a breakpoint

Symptom: TIMx counter keeps running while CPU halted, so you can’t inspect exact counter value at breakpoint.
Fix: set the DBGMCU freeze bit for that timer (DBG_TIMx_STOP), so hardware stops the timer when CPU is halted. Use HAL macro __HAL_DBGMCU_FREEZE_TIM2() or write the freeze bit directly.

C — Avoid watchdog reset during debug

Symptom: IWDG/WDT resets while you step in the debugger.
Fix: freeze the watchdog (DBG_IWDG_STOP / DBG_WWDG_STOP) while debugging. But do not leave this enabled in production (it disables safety net).

 

Family differences & surprises (what trips people)

  • Register names differ. F0/F1/F4 often use DBGMCU->CR + DBGMCU->APB1FZ/ APB2FZ. Newer families (H7, U5, G4) may use multiple freeze registers (AHB1FZ, APB1LFZ1, APB3FZ1...). Always read the local RM chapter.

  • Not all peripherals can be frozen. The RM lists exactly which peripherals have freeze bits. Some peripherals are always running or are in separate power domains.

  • Stop vs Standby behavior: enabling DBG_STOP typically keeps an internal RC on so clocks needed for debug exist; enabling or disabling bits affects how the clock tree behaves in that low-power mode. If you rely on specific PLL/xosc behavior on exit, test carefully.

  • Some vendors / debugger combos set these bits automatically. Tools like ST-Link GUI, some debuggers or RTOS bring-up scripts may toggle DBGMCU bits; this hides the problem during development but bites you when running on a board without that helper.

 

Pitfalls & gotchas (must-read)

  1. Power vs debug tradeoff: enabling debug in low-power increases current draw and may defeat your low-power tests. Use guarded code: only enable during development or behind #ifdef DEBUG.

  2. Relying on freeze for production logic: don’t build functionality that depends on watchdogs being frozen — production devices must not disable safety features.

  3. Cache / peripheral clocks in STOP: STOP may turn off domains — enabling DBG_STOP changes clocking; your wake-up sequence may need to reinit PLLs. Test the exit path.

  4. Different behavior between stepping and halting: Some peripherals continue if they are driven by independent hardware clock domains — freezing is not a guarantee unless RM lists the freeze bit.

 

Useful ST docs & community threads (start here)

  • AN4989 — STM32 microcontroller debug toolbox (troubleshooting & low-power debug tips).

  • STM32H7 System Debug (training PDF) — architecture & specifics for H7.

  • AN5946 / family application notes about low-power — mentions DBGMCU_CR usage.

  • Cube HAL/LL docs and header macros — search __HAL_DBGMCU_FREEZE_* or LL_DBGMCU_EnableDBGStopMode() in your device package.

  • ST Community & StackOverflow threads where people discuss debugger disconnects and freezes (practical troubleshooting).

 

Final recommendations (practical)

  • For development: enable DBG_STOP/DBG_SLEEP so you can attach the debugger and freeze the peripherals you care about. Wrap these calls under #ifdef DEBUG.

  • For low-power validation: test both with and without debug bits — enabling them changes actual power draw and clocking. Measure current and verify behavior.

  • For CI / automated flashing: be aware some programmers/tools toggle DBGMCU bits — don’t rely on their presence in production.

 

 

Ex- Long Term Intern at STMicroelectronics
0 REPLIES 0