Bare Metal STM32 · Part 7 of 7
Low-Power Stop Mode with Wake-Up on EXTI
34:12
Part 7 / 7
⚙️ Bare Metal STM32 Series · 7 Parts
Part 7 of 7
Part 01
HAL vs Bare Metal: Which Should You Use?
38:22
Part 02
Clock Configuration with RCC: From HSI to PLL
22:10
Part 03
Interrupts & NVIC: Complete Configuration Guide
47:22
Part 04
SPI DMA Transfers: No CPU Overhead
33:05
Part 05
ADC DMA Circular Mode: Continuous Sampling
29:45
Part 06
Debugging with SWO Trace & ITM Printf
18:30
Part 07
Low-Power Stop Mode with Wake-Up on EXTI
34:12
01
Overview
A bare-metal STM32 sitting in a while(1) loop burns 50–100 mA. Put it in Stop mode and it drops to under 100 μA — a 1000× reduction — while keeping SRAM and register state intact. This final part covers the three STM32 sleep modes, entering Stop mode bare-metal, waking on an EXTI edge, and the one thing that kills every first attempt: reconfiguring the PLL after wakeup.
- Compare Sleep, Stop, and Standby modes — current draw, wakeup time, and what survives
- Enter Stop mode using WFI with the main regulator in low-power mode
- Wake on a falling EXTI edge and immediately reconfigure clocks before any peripheral access
- Measure current in each mode with a bench supply and verify against the datasheet
02
Sleep Modes Compared
Sleep Mode
CPU clock stopped. All peripherals and SRAM stay powered. Wakes on any interrupt in microseconds. Useful when you're waiting for a DMA or timer interrupt but not doing CPU work.
~10 mA · WFI instruction
Stop Mode ★
All clocks stopped, PLL and HSE off. Only LSI/LSE and RTC can run. SRAM and registers preserved. Wakes on EXTI, RTC alarm, or USB. Must reinitialise PLL on wakeup.
~100 μA · Best trade-off
Standby Mode
Nearly everything off. Only RTC and backup registers survive. Wakeup resets the device from the beginning. Use for multi-hour battery applications where wakeup latency is acceptable.
~2 μA · Full reset on wake
03
Code
01
Enter Stop mode, wake on EXTI, restore clockslow_power.c
C
/* Call this from your main loop when there's nothing to do */ void Enter_StopMode(void) { /* 1. Clear any pending wakeup flags */ PWR->CR |= PWR_CR_CWUF; /* 2. Select Stop mode: set PDDS=0 (Stop, not Standby) Use low-power regulator to save more current: LPDS=1 */ PWR->CR &= ~PWR_CR_PDDS; PWR->CR |= PWR_CR_LPDS; /* 3. Set SLEEPDEEP so WFI enters a deep sleep mode */ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* 4. Ensure memory writes complete before sleeping */ __DSB(); /* 5. Enter Stop mode — CPU halts here until an EXTI fires */ __WFI(); /* 6. Back from Stop — clear SLEEPDEEP immediately */ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; /* 7. CRITICAL: Stop mode killed the PLL. Peripherals run on HSI (~16 MHz) until we restore the full clock config. Do this BEFORE any peripheral access (UART, SPI, etc.) */ SystemClock_Config(); } /* EXTI wakeup ISR — fires immediately on wakeup edge */ void EXTI0_IRQHandler(void) { if (EXTI->PR & EXTI_PR_PR0) { EXTI->PR = EXTI_PR_PR0; // Clear pending g_wakeup_reason = WAKE_EXTI0; } } /* Main loop pattern */ void main_loop(void) { while(1) { Do_Work(); // ~5ms active Enter_StopMode(); // Sleep until next event // Execution resumes here after EXTI fires + clocks restored Handle_WakeupReason(g_wakeup_reason); } }
02
Sleep mode — lightweight alternative when only CPU needs to pausesleep_mode.c
C
/* Sleep mode — much simpler, no clock reconfiguration needed */ void Enter_SleepMode(void) { // SLEEPDEEP must be 0 for Sleep (not Stop/Standby) SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; __DSB(); __WFI(); // Returns here on ANY enabled interrupt — no clock restore needed }
Reconfigure clocks immediately after waking from Stop
Stop mode powers down the PLL and HSE. On wakeup the MCU runs on the HSI at 16 MHz. If you access a UART, SPI, or timer before calling
SystemClock_Config(), baud rates and timings will be completely wrong — and the bug is nearly impossible to spot without a logic analyser.Series Complete
You've finished all 7 parts of Bare Metal STM32. Ready to apply these techniques in a real-time system? Start the FreeRTOS Deep Dive series next.