Project 13: Power Mode Explorer

A power profiling tool that measures current draw across sleep, stop, and standby modes with wake-up verification.

Quick Reference

Attribute Value
Difficulty Level 3: Advanced
Time Estimate 1-2 weeks
Main Programming Language C (Alternatives: C++, Rust, Ada)
Alternative Programming Languages C++, Rust, Ada
Coolness Level Level 3: Genuinely Clever
Business Potential 1. The “Resume Gold”
Prerequisites Clock configuration, GPIO interrupts, basic measurement
Key Topics Power modes, wake sources, clock restoration

1. Learning Objectives

By completing this project, you will:

  1. Enter and exit sleep/stop/standby modes safely.
  2. Measure current draw in each mode.
  3. Restore clocks and peripherals after wake-up.
  4. Log wake reasons and mode transitions.

2. All Theory Needed (Per-Concept Breakdown)

Power Modes, Clock Gating, and Wake-Up Sources

Fundamentals Power modes reduce energy consumption by shutting down parts of the MCU or lowering clock speeds. STM32 devices typically provide sleep, stop, and standby modes, each with different trade-offs between power and wake latency. Clock gating disables unused peripherals, saving power without stopping the CPU entirely. Understanding these modes lets you design efficient battery-powered systems.

Deep Dive into the concept Power consumption in MCUs is largely driven by clock frequency and active peripherals. Sleep mode stops the CPU but keeps peripherals running; stop mode halts most clocks while retaining RAM; standby mode powers down most of the chip and resets on wake. Each mode has a different wake-up time and context retention. Clock gating is another important technique: even when the CPU runs, you can disable clocks to unused peripherals in the RCC to reduce power. On STM32F3, the regulator and voltage scaling also impact power; lower voltage ranges reduce current but limit max frequency. A power mode explorer project should measure current draw in each mode using a multimeter or current probe. You must also identify which wake sources are available: GPIO interrupts, RTC alarms, watchdogs, or timer events. The firmware should log the wake reason, because debugging power modes without that log is difficult. Another key aspect is peripheral state. Some peripherals must be reinitialized after wake, especially after stop or standby. You need a clean re-init path and a test that proves it works. Power modes also interact with clocks: after stop mode, the system may revert to a default clock source. A robust design reconfigures the clock tree on wake and revalidates timing. By building a power mode explorer, you learn to treat energy as a measurable resource and to build systems that can trade performance for battery life predictably.

How this fit on projects In Power Mode Explorer, you cycle through power modes, measure current draw, and verify wake-up behavior and clock restoration.

Definitions & key terms

  • Sleep -> CPU halted, peripherals running.
  • Stop -> Most clocks off, RAM retained.
  • Standby -> Deepest low-power mode, most state lost.
  • Clock gating -> Disabling peripheral clocks to save power.
  • Wake source -> Event that brings MCU back to active mode.

Mental model diagram (ASCII)

Run -> Sleep -> Stop -> Standby
 ^       ^        ^        ^
 |   wake sources (GPIO/RTC/Timer)

How it works (step-by-step, with invariants and failure modes)

  1. Configure and enter each power mode.
  2. Measure current draw and log results.
  3. Trigger wake-up via GPIO or timer.
  4. Reconfigure clocks and peripherals after wake.
  5. Invariant: system resumes reliably; failure mode: lost configuration or unexpected reset.

Minimal concrete example

// Enter stop mode and wait for interrupt
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

Common misconceptions

  • Sleep and stop are the same ignores clock and state differences.
  • Wake-up restores everything ignores that clocks and peripherals often reset.
  • Power modes are only for battery devices ignores thermal and reliability benefits.

Check-your-understanding questions

  1. Which mode retains RAM while stopping most clocks?
  2. Why must you reconfigure clocks after stop mode?
  3. How do you measure current draw accurately?

Check-your-understanding answers

  1. Stop mode retains RAM but disables most clocks.
  2. The system often reverts to HSI or default clock after stop; you must restore PLL settings.
  3. Use a multimeter in series or a current probe and log stable readings.

Real-world applications

  • Battery-powered sensors and IoT devices.
  • Energy-efficient industrial monitoring.
  • Thermally constrained systems.

Where you’ll apply it

References

  • STM32F3 Reference Manual (power control chapter).
  • ST application notes on low-power design.
  • ‘Making Embedded Systems’ (power and reliability).

Key insights

  • Low power is an engineered state, not a default; you must measure and verify it.

Summary Power modes trade performance for energy savings. By measuring current draw and validating wake behavior, you gain control over your system’s energy profile.

Homework/Exercises to practice the concept

  1. Measure current draw in run and sleep modes and compute percentage savings.
  2. Test wake-up from a GPIO interrupt and log the wake reason.
  3. Verify that UART baud rate is correct after waking from stop mode.

Solutions to the homework/exercises

  1. Sleep current should be significantly lower; compute (run - sleep) / run.
  2. Store wake reason in backup registers or RAM before sleep.
  3. Reinitialize clock tree and UART after wake to restore baud accuracy.

Clock Tree, PLL, and Prescalers (System Timing Backbone)

Fundamentals Every peripheral timing and every delay in your firmware depends on the clock tree. The STM32F3 can run from internal or external oscillators, and uses a PLL to multiply those sources to reach the desired system clock. From that system clock, prescalers divide down to generate the AHB, APB1, and APB2 bus clocks, which in turn feed timers, ADCs, UARTs, and other peripherals. If you misconfigure any divider, you will see subtle failures: UART baud errors, PWM drift, incorrect ADC sampling, and watchdog timeouts. A clock tree audit is the practice of proving, with measurements, that your configured frequencies match reality. It is the single most valuable habit for embedded reliability.

Deep Dive into the concept The STM32F3 clock system is a directed graph of sources, multipliers, and dividers. At the root are the HSI (internal RC oscillator) and HSE (external crystal or clock). The PLL takes one of those sources and applies multiplication factors to produce a higher-frequency output used as the system clock. On STM32 devices, the system clock (SYSCLK) feeds the AHB bus, while APB1 and APB2 buses are derived by additional prescalers. Timers on APB buses often have a ‘x2’ effect when the prescaler is not 1, which means timer clocks can be double the APB frequency. If you forget that rule, PWM frequencies are off by exactly 2x, a classic bring-up trap. The clock tree is also linked to power: higher frequencies increase current draw, and some peripherals require specific clock ranges. USB and ADCs, for example, require precise clocks to meet protocol or sampling accuracy requirements. The RCC (Reset and Clock Control) registers configure all of this. A good audit reads those registers at runtime and recomputes derived clocks, then compares expected timing (based on configuration) to observed timing (based on measurement). Measurement can be as simple as toggling a GPIO at a known rate and timing it with a stopwatch, or as precise as using a logic analyzer to measure a timer output. A thorough audit includes the SysTick frequency, timer tick frequency, and peripheral baud rate verification. There are also failure modes: the external crystal may not start, the PLL may fail to lock, or the clock security system may switch back to HSI without warning. In robust firmware, you detect and log these events. The clock tree is therefore not just a setup routine, but an operational dependency that must be measured. When you develop on the STM32F3DISCOVERY, you should record expected frequencies, read RCC_CFGR to confirm clock sources, and validate at least one timer output. This practice makes you immune to the most common cause of ‘mystery bugs’ in embedded projects: silent timing errors.

How this fit on projects In Power Mode Explorer, you audit the clock tree by reading RCC configuration, computing derived clocks, and validating time with measured outputs (LEDs, timers, or UART).

Definitions & key terms

  • HSI -> Internal high-speed oscillator, convenient but less accurate.
  • HSE -> External crystal oscillator, more accurate but requires hardware.
  • PLL -> Phase-Locked Loop that multiplies an input frequency.
  • SYSCLK -> System clock feeding the CPU core.
  • AHB/APB -> Buses that distribute clocks to memory and peripherals.

Mental model diagram (ASCII)

HSI/HSE -> PLL -> SYSCLK -> AHB -> APB1/APB2 -> Peripherals
         |                |            |
       prescalers       timers       UART/ADC

How it works (step-by-step, with invariants and failure modes)

  1. Select a clock source (HSI or HSE) and enable it.
  2. Configure PLL multipliers/dividers to reach target SYSCLK.
  3. Set AHB/APB prescalers to keep peripherals within spec.
  4. Validate that timers and UARTs use the expected derived clocks.
  5. Invariant: All configured clocks must be within device limits; failure mode: peripheral timing mismatch or PLL unlock.

Minimal concrete example

// Pseudocode: compute SYSCLK from RCC registers
uint32_t sysclk = rcc_get_sysclk();
uint32_t hclk = sysclk / ahb_prescaler();
uint32_t pclk1 = hclk / apb1_prescaler();
printf("SYSCLK=%lu HCLK=%lu PCLK1=%lu\n", sysclk, hclk, pclk1);

Common misconceptions

  • If SYSCLK is correct, peripherals are correct ignores bus prescalers and timer x2 behavior.
  • HSI is good enough for all peripherals ignores baud accuracy and ADC sampling constraints.
  • PLL always locks ignores startup and clock security failures.

Check-your-understanding questions

  1. Why can a timer run at twice the APB clock on STM32?
  2. How would you detect that the HSE crystal failed to start?
  3. What is the difference between SYSCLK and HCLK?
  4. Why does UART baud depend on clock prescalers?

Check-your-understanding answers

  1. When APB prescaler is not 1, timer clocks are doubled to preserve timer resolution.
  2. Check RCC flags for HSE ready or clock security events and log a fallback to HSI.
  3. SYSCLK feeds the core; HCLK is SYSCLK after the AHB prescaler.
  4. UART divider is computed from the peripheral clock; a mismatch shifts baud rate.

Real-world applications

  • Motor control where PWM frequency accuracy matters.
  • Precision sensing with ADC sampling rate requirements.
  • Communication interfaces that need accurate baud rates.

Where you’ll apply it

References

  • STM32F3 Reference Manual (RCC chapter).
  • Joseph Yiu, ‘The Definitive Guide to ARM Cortex-M3/M4’ (system clocking).
  • Elecia White, ‘Making Embedded Systems’ (timing and measurement).

Key insights

  • If you cannot measure your clock tree, you cannot trust any timing claim in your system.

Summary Clock configuration is a system-wide contract. A small prescaler mistake can propagate into every peripheral. A clock audit makes timing visible and protects you from silent configuration errors.

Homework/Exercises to practice the concept

  1. Compute expected timer tick rates for APB1 and APB2 given a target SYSCLK.
  2. Toggle a GPIO every 1000 SysTick ticks and measure the period with a stopwatch.
  3. Force a fallback to HSI and log the resulting SYSCLK change.

Solutions to the homework/exercises

  1. Use the RCC_CFGR register to determine prescalers and apply the x2 rule for timers.
  2. 1,000 ticks at 1 kHz should be 1 second; if not, check SysTick reload value.
  3. When HSE fails, the system clock source bit will indicate HSI; log the event over UART.

Timebase, SysTick, and Measurement Discipline

Fundamentals A reliable timebase is how you reason about time in firmware. SysTick is a dedicated timer tied to the core clock that can generate periodic interrupts. If you configure it for 1 kHz, you get a millisecond tick that becomes your system heartbeat. This tick drives delays, scheduling, timeouts, and timestamps. But SysTick is only reliable if you know the core clock frequency and if you measure the actual timing. Without measurement, a ‘1 ms tick’ is just a guess. A bring-up project must therefore treat SysTick as a calibration point and validate it with real-world observation.

Deep Dive into the concept SysTick is a 24-bit down-counter integrated into the Cortex-M core. It takes the core clock (or core clock divided by 8) and counts down from a reload value to zero, then sets a flag and optionally fires an interrupt. Because it is in the core, it is unaffected by peripheral bus prescalers, which makes it a good reference for measuring the system clock. To configure SysTick, you load the reload register with (core_clock / desired_tick) - 1, select the clock source, enable the counter, and enable its interrupt. The interrupt handler typically increments a global tick counter. On STM32, HAL_Delay and other drivers are often built on this tick. The main danger is implicit coupling: if SysTick is configured incorrectly, every delay and timeout in your system is wrong. Another hazard is jitter. SysTick interrupts can be delayed by higher-priority interrupts, which means the tick is not a precise real-time clock, but a best-effort scheduler. For measurement, you should use SysTick only as a reference and then validate it with a GPIO toggle or timer output. A robust timebase audit logs the computed reload value, the configured clock source, and the observed period. The audit should also include a drift test: toggle a pin every N ticks for several minutes and measure drift relative to a stopwatch or logic analyzer. If drift is observed, the root cause is often clock source accuracy (HSI vs HSE) or an incorrect reload value due to a wrong core clock assumption. You also need to consider wraparound. A 24-bit counter at 72 MHz will wrap quickly if used without an interrupt, and a 32-bit tick counter will wrap after ~49 days at 1 kHz. In embedded systems, you typically handle wraparound by using unsigned arithmetic and comparing time differences rather than absolute values. Finally, you must decide what ‘good enough’ measurement means. For LED blinking, 1-2% accuracy is acceptable. For UART baud or ADC sampling, you need tighter tolerances. The discipline is to tie every time-dependent feature to a measured reference rather than an assumption.

How this fit on projects In Power Mode Explorer, SysTick is your baseline for clock validation. You compute the reload value, log it, and then validate the resulting tick with physical measurement.

Definitions & key terms

  • SysTick -> Core-integrated timer used for periodic interrupts and timekeeping.
  • Reload value -> The count value loaded into SysTick before it starts counting down.
  • Tick -> A periodic time event, commonly 1 ms in embedded systems.
  • Jitter -> Variation in the timing of periodic events due to interrupt latency.
  • Drift -> Long-term timing error relative to a reference clock.

Mental model diagram (ASCII)

Core clock -> SysTick down-counter -> interrupt -> tick++
                  |
                  v
             timing reference

How it works (step-by-step, with invariants and failure modes)

  1. Compute reload value based on expected core clock and desired tick rate.
  2. Configure SysTick to use core clock and enable interrupt.
  3. Increment a global tick counter in the SysTick handler.
  4. Toggle a GPIO every N ticks and measure the period.
  5. Invariant: tick increments at configured frequency; failure mode: drift or jitter due to wrong clock or interrupt priority.

Minimal concrete example

void SysTick_Handler(void) {
g_tick_ms++;
}
void delay_ms(uint32_t ms) {
uint32_t start = g_tick_ms;
while ((uint32_t)(g_tick_ms - start) < ms) {
    __WFI();
}
}

Common misconceptions

  • SysTick gives precise real-time scheduling ignores interrupt latency and jitter.
  • If LED blinks, tick is correct ignores the need to measure drift over time.
  • Tick counters never overflow ignores wraparound in long-running systems.

Check-your-understanding questions

  1. Why might SysTick interrupts be delayed even if configured correctly?
  2. How do you compute reload for 1 kHz at 72 MHz?
  3. What is the safest way to compare timeouts with wraparound?

Check-your-understanding answers

  1. Higher-priority interrupts can preempt SysTick, causing jitter.
  2. Reload = (72,000,000 / 1,000) - 1 = 71,999.
  3. Use unsigned subtraction: if (now - start) >= timeout.

Real-world applications

  • Scheduling periodic sensor sampling.
  • Timeouts in communication protocols.
  • Measuring CPU load and real-time performance.

Where you’ll apply it

References

  • ARM Cortex-M4 Technical Reference Manual (SysTick).
  • Joseph Yiu, ‘The Definitive Guide to ARM Cortex-M3/M4’ (timers and exceptions).
  • Elecia White, ‘Making Embedded Systems’ (timing discipline).

Key insights

  • A tick is only trustworthy when you can measure it and bound its jitter and drift.

Summary SysTick provides a convenient timebase, but it is only as accurate as your clock configuration and interrupt discipline. Treat it as a calibrated instrument, not a magic delay source.

Homework/Exercises to practice the concept

  1. Compute the reload value for 2 kHz and verify it in code.
  2. Measure the drift of a 1 Hz LED blink over 10 minutes.
  3. Experiment with interrupt priorities and observe SysTick jitter.

Solutions to the homework/exercises

  1. Reload for 2 kHz at 72 MHz is 35,999.
  2. A 1 Hz blink should be 600 seconds over 10 minutes; log the error and compute percent drift.
  3. Setting a higher-priority timer interrupt increases SysTick jitter; adjust priorities if needed.

3. Project Specification

3.1 What You Will Build

A firmware tool that cycles through power modes, measures current, logs wake sources, and validates clock restoration.

3.2 Functional Requirements

  1. Mode Entry: Support sleep, stop, and standby transitions.
  2. Wake Sources: Wake via GPIO or timer and log the source.
  3. Current Measurement: Record current draw per mode.
  4. Clock Restoration: Reinitialize clocks and verify SYSCLK after wake.

3.3 Non-Functional Requirements

  • Performance: Wake-up latency measured and logged.
  • Reliability: System always returns to known state after wake.
  • Usability: Clear report format for power comparisons.

3.4 Example Usage / Output

Mode: STOP
Current: 0.8 mA
Wake: GPIO
SYSCLK restored: 72 MHz

3.5 Data Formats / Schemas / Protocols

Power log format: MODE=<sleep|stop|standby> CURRENT_MA=<float> WAKE=<src>

3.6 Edge Cases

  • Wake source not configured; device stays asleep.
  • Clock not restored after stop mode.
  • UART unavailable in low-power modes.
  • Standby causes full reset and loses state.

3.7 Real World Outcome

You will measure current draw across modes and verify wake-up behavior.

3.7.1 How to Run (Copy/Paste)

$ make flash
$ screen /dev/tty.usbmodem* 115200

3.7.2 Golden Path Demo (Deterministic)

  • Enter STOP mode, wake with GPIO, log current.

3.7.3 CLI Transcript (Success)

MODE=STOP CURRENT_MA=0.8 WAKE=GPIO
SYSCLK=72000000
RESULT=PASS
# Exit code: 0

3.7.4 Failure Demo (Clock Not Restored)

SYSCLK=8000000
RESULT=FAIL
# Exit code: 2

4. Solution Architecture

Mode controller enters power states, measurement module records current, and wake handler restores clocks.

4.1 High-Level Design

Mode Controller -> Enter Low Power -> Wake Event -> Restore Clock -> Log

4.2 Key Components

Component Responsibility Key Decisions
Mode Controller Transitions between power modes Explicit sequence per mode
Wake Handler Detects wake source and restores clocks Log reset cause flags
Measurement Logger Records current and latency Manual measurement entry or sensor integration

4.3 Data Structures (No Full Code)

typedef struct {
const char* mode;
float current_ma;
const char* wake_src;
} power_report_t;

4.4 Algorithm Overview

Mode Cycle

  1. Enter mode and start measurement.
  2. Wait for wake event.
  3. Restore clocks and log data.

Complexity: O(1) per mode.


5. Implementation Guide

5.1 Development Environment Setup

make init
make flash
screen /dev/tty.usbmodem* 115200

5.2 Project Structure

project-root/
|-- src/
|   |-- main.c
|   |-- drivers/
|   `-- app/
|-- include/
|-- Makefile
`-- README.md

5.3 The Core Question You’re Answering

“How much power can I save, and what does it cost in wake latency?”

5.4 Concepts You Must Understand First

  1. Sleep/stop/standby differences.
  2. Wake-up sources and reset causes.
  3. Clock tree restoration after wake.

5.5 Questions to Guide Your Design

  1. Which wake sources are required for your product?
  2. What is acceptable wake latency?
  3. Which peripherals need reinitialization after wake?

5.6 Thinking Exercise

Power Budget

Run: 20 mA
Stop: 0.8 mA
Sleep: 3 mA
Compute savings for 90% idle time

5.7 The Interview Questions They’ll Ask

  1. What is the difference between sleep and stop modes?
  2. Why must clocks be restored after wake?
  3. How do you measure power consumption in low-power modes?

5.8 Hints in Layers

Hint 1: Start with sleep mode; verify wake first. Hint 2: Log reset cause before clearing flags. Hint 3: Use a multimeter in series with the supply.

5.9 Books That Will Help

Topic Book Chapter
Low power design Making Embedded Systems Ch. 10
Power control STM32 Reference Manual PWR chapter

5.10 Implementation Phases

Phase 1: Sleep Mode (2 days)

Enter sleep and wake via GPIO.

Phase 2: Stop Mode (4 days)

Measure current and restore clocks.

Phase 3: Standby Mode (3 days)

Test wake and reset behavior.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Wake source GPIO vs RTC GPIO Simple for lab testing
Measurement Manual vs sensor Manual Simplicity and accuracy

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Clock restore logic RCC config checks
Integration Tests Mode transitions Sleep/stop/standby cycles
Edge Case Tests Failed wake Invalid wake source

6.2 Critical Test Cases

  1. Sleep Wake: System wakes and resumes logging.
  2. Stop Clock Restore: SYSCLK matches pre-sleep value.
  3. Standby Reset: Reset cause logged as standby.

6.3 Test Data

Sleep=3.0 mA, Stop=0.8 mA, Standby=0.1 mA

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
No wake source Board appears dead Enable EXTI or RTC wake
Clock not restored UART garbled after wake Reconfigure PLL
Standby resets state Variables lost Use backup registers or re-init

7.2 Debugging Strategies

  • Use LED indicators to show entry/exit of modes.
  • Log reset cause flags on boot.
  • Measure current with a stable supply and meter.

7.3 Performance Traps

Disabling clocks without reinit can break peripherals silently.


8. Extensions & Challenges

8.1 Beginner Extensions

  • Add a low-power heartbeat LED.

8.2 Intermediate Extensions

  • Measure wake latency in microseconds.

8.3 Advanced Extensions

  • Integrate RTC wake and periodic sampling.

9. Real-World Connections

9.1 Industry Applications

  • IoT sensors: Battery life depends on sleep/stop usage.
  • Wearables: Low-power modes critical for user experience.
  • Zephyr power management: Low-power mode strategies.
  • STM32Cube examples: Vendor low-power demos.

9.3 Interview Relevance

  • Power mode trade-off questions.
  • Wake-up sources and clock restoration discussions.

10. Resources

10.1 Essential Reading

  • Making Embedded Systems by Elecia White - Power and reliability topics.
  • STM32F3 Reference Manual by ST - PWR and RCC chapters.

10.2 Video Resources

  • STM32 low-power modes tutorial.
  • Measuring current in embedded systems.

10.3 Tools & Documentation

  • Multimeter or power profiler: Measure current draw.
  • STM32CubeIDE: Build and debug.

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain differences between power modes.
  • I can restore clocks after wake.
  • I can measure current accurately.

11.2 Implementation

  • Mode transitions work reliably.
  • Current measurements logged.
  • Wake sources verified.

11.3 Growth

  • I can design a power budget for a device.
  • I can select wake sources for a product.
  • I can explain power trade-offs in interviews.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Sleep and stop modes demonstrated.
  • Wake source verified.
  • Current logged.

Full Completion:

  • Standby mode tested.
  • Clock restoration confirmed.

Excellence (Going Above & Beyond):

  • RTC-based periodic wake implemented.