Overview
Curated: · Written: · Reviewed:
Low-power design is an energy-and-latency optimization constrained by correctness. A useful model accounts for active current, state-specific leakage, transition energy, minimum residency, exit latency, clock and regulator settling, retained context, peripheral dependencies, wake-source availability, and workload duty cycle. The deepest state is not automatically the most efficient: transition overhead can cost more energy than a short idle interval.
Sleep entry is a concurrent state transition. Firmware must prevent a lost-wakeup race between checking that no work is ready and executing WFI/WFE, program a wake source that remains powered in the selected state, quiesce or veto busy devices, order child/parent suspend, save only required state, and restore clocks and devices before consumers run. A wake interrupt being pending is not proof that its peripheral retained configuration or timestamp continuity.
Runtime device power management needs balanced ownership/usage counts and dependency-aware resume: a usage count represents outstanding clients that require the device active. Tickless kernels must reconcile elapsed time using a wake-capable monotonic clock and handle early wake, counter wrap, drift, and maximum programmable intervals. DMA, caches, radios, sensors, flash operations, watchdogs, debug probes, and brownout behavior all cross power boundaries. Nominal capacity is insufficient without the battery's load, voltage, temperature, aging, and conversion model.
The production invariant is energy-state fidelity: every measured interval is attributable to a declared hardware/software state, clock and peripheral configuration, workload, wake reason, latency, and transition outcome. Current traces, residency histograms, wake counters, deadline misses, retained-state checks, and environmental tests must prove both energy savings and functional recovery.
Break-even time is arithmetic. Stop mode at 2.1 µA versus Run at 8.4 mA saves 8.398 mA, but entering and exiting Stop costs 18 µC of regulator and oscillator energy (about 2.1 ms at 8.4 mA equivalent). Idle shorter than 2.1 ms in Stop spends more than it saves; a 200 µs SPI gap should stay in Run or Sleep, not Stop. A product that entered Stop on every idle because “Stop is lowest” spent 11 mAh/day on transitions versus 6.4 mAh/day staying in Sleep at 1.2 mA for those gaps. Measure with a current shunt at ≥100 kHz, not with a DMM average.
Lost-wakeup is the correctness twin. Checking a work-pending flag then executing WFI without masking the producer interrupt lets a UART byte set the flag after the check and before WFI; the interrupt runs, the flag is consumed, WFI then waits for the next byte that may not come for an hour. The kernel idle path that sets BASEPRI, re-reads the flag, and WFI with the event registered is the protocol; a custom idle that “just WFI” is not. Independent watchdogs often keep running in Stop: a 4 s IWDG with a 30 s BLE advertising interval in Stop resets the part every 4 s unless the IWDG is fed from RTC wakeup or the timeout is reprogrammed. GPIO leakage of 80 µA on an unconfigured pin dwarfs the 2.1 µA Stop current; analog-disable and pull policy belong in the sleep entry checklist.
Brownout at 1.8 V while flash is at 2.0 V minimum for writes bricks the trailer; detect Vbat/Vdd against the flash spec, not against “the MCU still runs.” SRAM bank retention: dropping bank 2 to save 0.4 µA loses the 8 KiB log buffer that the next boot needed for the crash record. DMA in Sleep may freeze if its clock is gated; a transfer that “completed” in the driver’s book has 0 bytes on the wire. Attribute every microamp to a pin, clock, or bank on a schematic-level current budget, then close it with a trace.
Regulator modes change both current and noise. A buck in PFM at 50 µA load is 1.8 µA quiescent versus 12 µA PWM, but PFM ripple of 40 mV on a 1.8 V rail can shift an ADC 12-bit LSB (1.8/4096 ≈ 440 µV) by 90 counts. Sample-sensitive paths may need PWM during conversion and PFM in Stop. RAM retention banks: 8 KiB retained at 0.6 µA versus 0.1 µA fully off; if crash breadcrumbs live in the off bank they are gone. Place no-init sections explicitly in a retained bank in the linker script.
Wake filters on GPIO that debounce 30 ms in hardware will miss a 5 ms button; software debounce after a raw edge is a different product. DMA in Stop: if the DMA clock is in the gated domain, disable DMA before Stop or the next Run sees a half-written buffer and a TC flag that never set. Temperature: Stop current of 2.1 µA at 25 °C can be 18 µA at 85 °C; a battery life calculated at room temperature is 8× optimistic. Close the energy model at the specified temperature extremes with a current trace, then lock the sleep entry sequence so a debug probe left attached cannot keep the domain in Run at 8 mA while you believe the 2.1 µA figure.
Energy verification is a release-image ritual that starts at a shunt and ends at a residency histogram. Record SYSCLK, wait states, compiler flags, .map sizes, painted stack high-water marks, ISR GPIO timing, logic-analyzer traces of CS/SCK/SDA, current-shunt waveforms at not less than 100 kHz, reset-cause and fault registers, and the boot slot/security counter after every power-loss injection. A pass is a number that can be recomputed from those artifacts: flash LOAD versus FLASH LENGTH, ISR high-water versus period, Stop current versus the schematic budget, confirm window versus the health checks, and disable-to-deny for debug and keys. If the only evidence is a green LED, a UART log, or a debugger session on an -O0 build, the claim is unpublished. Repeat the same measurements at the temperature and voltage corners the datasheet allows, because flash wait states, Stop leakage, crystal error, and brownout thresholds all move, and a 25 °C passing suite is not a 85 °C passing suite.
Minimum residency is not optional: a Stop entry of 2.1 ms break-even with a 1.0 ms predicted idle is a net energy loss and a 40 µs extra wake latency on the control loop. Predict idle from the next RTOS timeout, not from 'CPU utilization is low'. GPIO analog mode on unused pins is worth tens of microamps; leave it in the sleep checklist next to the IWDG and the DMA disable.
Worked example: 200 us SPI gap is not a Stop
Stop at 2.1 uA versus Run at 8.4 mA. Entry/exit costs 18 uC, about 2.1 ms at Run equivalent.
| idle gap | state | energy that day |
|---|---|---|
| 200 us SPI, Stop every time | deepest | 11 mAh on transitions |
| 200 us SPI, Sleep at 1.2 mA | shallower | 6.4 mAh |
| idle greater than 2.1 ms, Stop | deepest | savings exceed the 18 uC tax |
The deepest state is not the cheapest. Break-even time is the policy.
