Embedded & Bare-Metal

low-power sleep modes (and wake-on-interrupt)

Think of how you save phone battery: dim the screen, then sleep it, then power it off — each deeper level saves more energy but takes longer to come back. A microcontroller has the same idea built into the silicon. Low-power sleep modes are hardware states the MCU can drop into to save energy when there is nothing to do, ranging from a light doze that wakes instantly to a deep hibernation that uses almost no power but takes longer (and remembers less) on waking.

Concretely, a typical MCU offers a ladder of modes (names vary by vendor). In a light SLEEP mode the CPU clock is stopped so it executes no instructions and burns far less power, but the peripherals and RAM stay alive, so the chip wakes in a microsecond and continues exactly where it paused. In a deeper STOP mode more clocks and circuits are turned off (lower power, slower wake, but RAM contents are usually retained). In the deepest STANDBY or shutdown mode almost everything is powered down — current can drop to microamps or nanoamps — but RAM is typically lost and waking is more like a reset. The key that makes sleep useful is wake-on-interrupt: before sleeping you arm an interrupt source (a button press, a timer, a received byte, an external pin), then issue the sleep instruction; the CPU halts, and when that interrupt fires, the hardware wakes the CPU, which runs the ISR and resumes. So the idiom is: set up your work to be interrupt-driven, do nothing in the main loop but sleep, and let interrupts wake you only when there is real work — the chip spends most of its life asleep. On Cortex-M the WFI ('wait for interrupt') instruction is the basic sleep, and the SysTick or a low-power timer is a common wake source.

It matters enormously for battery-powered devices: a sensor that sleeps 99.9% of the time and wakes briefly on a timer can run for years on a coin cell, whereas the same sensor busy-looping would die in days. The honest trade-offs: deeper modes save more but cost more wake-up latency and may lose state (RAM, peripheral configuration), so you must re-initialize on wake; not every peripheral can wake the chip from every mode (you must check which wake sources are valid per mode in the reference manual); and a classic battery-killer bug is leaving a peripheral or clock running, or busy-waiting in a loop, instead of actually entering a sleep mode — 'idle' code that spins still draws full power. Measure the real current; do not assume.

// Idle most of the time; wake only when an interrupt fires. arm_wakeup_interrupt(BUTTON_IRQn); // a button can wake us for (;;) { if (work_pending) handle_work(); __WFI(); // 'wait for interrupt': halt the CPU, save power. // The button (or timer) ISR runs, then we resume here. } // Deeper modes save more but may lose RAM and wake slower.

WFI halts the CPU until an armed interrupt wakes it; the device sleeps between events and only burns power when there is real work.

A common battery-killer is code that 'idles' by busy-looping instead of entering a real sleep mode — spinning draws full power. Deeper modes save more but may lose RAM and limit which interrupts can wake you, so check the wake sources per mode.

Also called
sleep modesstop modestandby modewake-on-interrupt睡眠模式停止模式中斷喚醒