Embedded Systems · Power Management
Wake-Up Latency and Its Energy Cost
Why returning from a low-power state costs microseconds and microjoules, how that cost sets a floor on the usable duty cycle, and where the transition sequence loses time.
A device that sleeps for one second and wakes for one millisecond spends 99.9 percent of its life asleep, and the naive conclusion is that its energy use is 99.9 percent determined by the sleep current. The conclusion fails at short wake intervals and at deep sleep states, because the transition itself has a duration and a current, and both are paid in full on every wake.
The phases of a wake
A wake from a clock-gated state is one instruction’s worth of delay: the clock resumes and the core continues. A wake from a stop state runs a sequence, and each element of the sequence has its own time constant.
The regulator comes first. If the core rail was removed or reduced, it must return to its operating voltage. A linear regulator recovers in a few microseconds; a switched regulator with a soft-start ramp can take hundreds. The core cannot run at full speed until the rail is within tolerance, and running it earlier produces wrong results rather than slow ones.
The clock source comes second. An RC oscillator starts in a few microseconds but drifts with temperature. A crystal oscillator needs the amplifier to build amplitude from noise, and its startup time depends on the crystal’s motional parameters, the load capacitance, and the drive level; tens of microseconds is normal and milliseconds is possible for low-frequency tuning-fork crystals. A phase-locked loop multiplying the crystal up to the core frequency adds its own lock time after the reference is stable.
Third comes the core’s own reinitialisation. The vector fetch, the reconfiguration of the clock tree, and any code that restores peripheral state all execute at whatever clock is available, so the early part of the wake runs slowly and the late part runs at full speed.
Fourth, if the state removed power from a domain, the boot path runs: memory initialisation, checksum verification of the image, and the firmware’s own start-up code. This is the phase that makes standby states unsuitable for frequent waking.
The sum of these is the wake-up latency. It is not a single number in a datasheet; it is a property of the configuration, and the datasheet figure usually names the best case with the fastest clock source and no regulator ramp.
Turning latency into energy
The energy cost of a wake is the integral of current over the transition, and during most of it the device draws something close to its active current while doing no useful work. Approximating the transition as a constant current $I_w$ for a duration $t_w$ gives $E_w = V I_w t_w$.
For a part running at 1.8 V, drawing 2 mA during a 100 µs transition, the wake costs 0.36 µJ. That number looks small. It becomes the dominant term when the useful work per wake is smaller than it: a sensor read that takes 50 µs at the same current costs 0.18 µJ, so the device spends two thirds of its awake energy on getting to the point where it can do the work.
The comparison against sleep is what makes the cost visible. Sleeping at 2 µA for one second costs 3.6 µJ at the same voltage. A 0.36 µJ wake is a tenth of that, so waking once per second adds about ten percent to the sleep energy. Sleeping at 0.5 µA for one second costs 0.9 µJ, and now the wake costs forty percent as much as the sleep itself, close to thirty percent of the total. The deeper the sleep, the more the transition matters, which inverts the intuition that deeper is always better.
def duty_cycle_energy(sleep_current, wake_current, wake_time,
work_current, work_time, sleep_time, voltage=1.8):
"""Energy per cycle, joules, for one wake-and-work period."""
e_wake = voltage * wake_current * wake_time
e_work = voltage * work_current * work_time
e_sleep = voltage * sleep_current * (sleep_time - wake_time - work_time)
return e_wake, e_work, e_sleep
e_wake, e_work, e_sleep = duty_cycle_energy(
sleep_current=2e-6, wake_current=2e-3, wake_time=100e-6,
work_current=2e-3, work_time=50e-6, sleep_time=1.0)
total = e_wake + e_work + e_sleep
print(f"wake {e_wake/total:.0%}, work {e_work/total:.0%}, sleep {e_sleep/total:.0%}")
The function reduces the sleep interval by the wake and work times rather than leaving it at the nominal period. At a one-second period and a 150 µs awake time the difference is negligible; at a ten-millisecond period it is 1.5 percent, and at a one-millisecond period it is 15 percent. A budget that leaves the interval at the nominal period overstates the sleep charge by that fraction.
The crossover between two sleep states
With two candidate states, one shallow with current $I_s$ and wake time $t_s$, one deep with current $I_d$ and wake time $t_d$, the deep state is better when the extra wake energy is repaid by the lower sleep current:
$$I_d , T + I_w , t_d < I_s , T + I_w , t_s$$
Solving for the period gives
$$T > \frac{I_w (t_d - t_s)}{I_s - I_d}$$
where $I_w$ is the transition current. With a 2 mA transition, a 900 µs difference in wake time, and a 1.5 µA difference in sleep current, the crossover is at 1.2 seconds. Waking more often than that makes the shallow state cheaper despite its higher sleep current. The formula is the reason a device with a 10 ms polling interval often runs in a light sleep state and never enters the deepest one.
The formula also shows why the transition current matters more than the transition time in some designs. If the regulator ramp draws 20 mA rather than 2 mA, the numerator grows tenfold and the crossover moves to twelve seconds. Measuring the current profile during the wake, not just its duration, is what makes the calculation usable.
Where the latency goes when it should not
A wake that takes far longer than the sum of its documented parts usually has one of four causes.
An interrupt that arrives during the transition is latched but not serviced until the sequence completes, so the handler’s own latency is added to the transition rather than overlapping with it. Firmware that clears the wake flag before the clock is stable can lose the event entirely and sleep again.
A clock source that is started but not waited for produces a wake that appears fast and then behaves erratically, because the early instructions execute at an indeterminate frequency. The failure is intermittent and temperature-dependent, which makes it expensive to diagnose. Waiting on the oscillator’s ready flag is not optional.
A peripheral that was disabled and must be re-enabled adds its own startup. An analog-to-digital converter needs its reference and its input sampling network to settle, and the settling time is a function of the source impedance; a high-impedance sensor front end can need milliseconds. An external radio needs its crystal and its synthesizer, and the settling is often the largest single term in the wake.
A wake source that is polled rather than interrupt-driven adds the polling interval. A device that wakes every 100 ms to check a flag has an average detection latency of 50 ms regardless of how fast the transition is, and the energy cost of the check is paid on every poll.
Designing around the cost
The standard response to a large wake cost is to do more per wake. Batching sensor reads, averaging several samples, and transmitting a block rather than a value all amortise the transition over more useful work. This shifts the design from a fast polling loop to a scheduled burst, and it moves the timing problem into the scheduling layer.
The second response is to keep the part in a state that preserves enough context that the wake does not need to reinitialise. Retention RAM, described in what a sleep mode actually turns off, exists precisely to shorten the post-wake path; its cost is a higher sleep current, and the crossover formula above decides whether the trade pays.
The third is to remove the wake entirely where possible. A peripheral that can operate autonomously while the core sleeps, converting and buffering samples without intervention, eliminates the transition for all the samples it handles. That is a matter of peripheral configuration and DMA, and it is the subject of peripheral clock gating and autonomous transfer.
The floor on duty cycle
Every duty-cycled design has a minimum period below which adding more wakeups costs more energy than the extra resolution is worth. The floor is set by the wake energy divided by the energy per useful unit of work, and it moves with temperature, supply voltage, and clock configuration. It is worth computing explicitly, because a design that polls at a rate below the floor is spending energy to obtain information it could have obtained by staying awake, and the fix is to restructure the work rather than to tune the sleep state.
References
- ARM Cortex-M4 Processor Technical Reference Manual — ARM Limited
- MSP430x5xx and MSP430x6xx Family User's Guide — Texas Instruments