Low-power operation is not an afterthought in embedded design — for battery-powered IoT devices, it is the primary design constraint. A device that consumes 5 mA during active operation but enters deep sleep at 10 µA between measurements can extend battery life from days to years.
The PY32F0xx HAL provides comprehensive support for five low-power modes, each trading off between power savings and wake-up capability.
Why Low Power Modes Matter
A typical IoT sensor node spends most of its time idle — waiting for the next measurement interval, a button press, or a network event. During that idle time, the microcontroller core can be halted or most of the chip powered down.
Active Time vs Idle Time (typical IoT node)
--------------------------------------------
Active: 100 ms every 10 seconds = 1% of time
Idle: 9.9 seconds every 10s = 99% of time
If active current = 5 mA and sleep current = 10 µA:
Average current = (0.01 × 5000) + (0.99 × 10) = 50 + 9.9 = ~60 µA
Without sleep mode: 5 mA → Battery lasts 1 month (2000 mAh)
With sleep mode: 60 µA → Battery lasts ~3 years
PY32F0xx Low-Power Modes
The PY32F0xx supports five distinct low-power configurations:
| Mode | Core | Peripherals | Regulator | Wake-Up Sources |
|---|---|---|---|---|
| Low-Power Run | Running (low clock) | Active | Low-power | Any |
| Sleep | Halted | Active | Normal | Any interrupt |
| Low-Power Sleep | Halted | Active | Low-power | Any interrupt |
| Stop 0 | Off | Off (LSI/LSE only) | Main on | EXTI, RTC |
| Stop 1 | Off | Off (LSI/LSE only) | Low-power | EXTI, RTC |
Mode 1: Low-Power Run Mode
Reduces the core clock frequency and switches the voltage regulator to low-power state. All peripherals remain active but at reduced performance.
Use case: Applications that must continue processing but at reduced speed to save power.
Mode 2: Sleep Mode
The Cortex-M0+ core halts. Peripherals remain active — UART can still receive data, timers continue running, and ADC can continue conversions. The voltage regulator stays in normal mode.
Wake-up: Any enabled interrupt (GPIO EXTI, UART receive, timer overflow, etc.)
// Enter sleep mode — wake on any interrupt
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
Mode 3: Low-Power Sleep Mode
Like Sleep mode, but the voltage regulator switches to low-power state, further reducing current consumption.
Wake-up: Any enabled interrupt
Mode 4: Stop 0 Mode
The main clock (HSI, HSE) stops. Only LSI (low-speed internal) or LSE (low-speed external) clocks remain active, which can drive the RTC and watchdog.
The voltage regulator remains in normal mode.
Wake-up: External interrupt (EXTI), RTC alarm
// Enter Stop 0 mode — main regulator on
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
Mode 5: Stop 1 Mode
Like Stop 0, but the voltage regulator also switches to low-power mode for maximum current savings while retaining RAM content and register state.
Wake-up: External interrupt (EXTI), RTC alarm
// Enter Stop 1 mode — low-power regulator
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
WFI vs WFE
Two ARM instructions trigger sleep entry:
| Instruction | Wake-Up Trigger | HAL Entry |
|---|---|---|
| WFI (Wait For Interrupt) | Any enabled interrupt | PWR_SLEEPENTRY_WFI |
| WFE (Wait For Event) | Interrupt or event flag | PWR_SLEEPENTRY_WFE |
WFI is the most common choice — the device wakes when any configured interrupt fires.
Sleep Mode with GPIO Wake-Up: Complete Example
This example demonstrates the full flow: configure a GPIO interrupt as wake-up source, enter sleep mode, wake on button press, and toggle an LED.
#include "py32f0xx_hal.h"
// Wake-up GPIO definition
#define WAKEUP_GPIO_PIN GPIO_PIN_0
#define WAKEUP_GPIO_PORT GPIOA
#define WAKEUP_IRQ_PRIORITY 2
// Function declarations
void SystemClock_Config(void);
void GPIO_Init_WakeUp(void);
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
int main(void) {
// Initialize HAL and system clock
HAL_Init();
SystemClock_Config();
// Initialize wake-up GPIO with interrupt
GPIO_Init_WakeUp();
// Optional: turn off LED before entering sleep
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
// Enter Stop mode — core halts here until interrupt fires
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
// Execution resumes here after wake-up
// The interrupt has already been handled by the callback below
while (1) {
// Main application loop after wake-up
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(1000);
}
}
// Configure PA0 as external interrupt for wake-up
void GPIO_Init_WakeUp(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = WAKEUP_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // Interrupt on rising edge
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(WAKEUP_GPIO_PORT, &GPIO_InitStruct);
// Enable EXTI interrupt in NVIC
HAL_NVIC_SetPriority(EXTI0_1_IRQn, WAKEUP_IRQ_PRIORITY, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
// GPIO EXTI interrupt callback (called by HAL when EXTI fires)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == WAKEUP_GPIO_PIN) {
// Wake-up detected — add any immediate wake response here
}
}
// EXTI IRQ Handler — calls the HAL driver
void EXTI0_1_IRQHandler(void) {
HAL_GPIO_EXTI_IRQHandler(WAKEUP_GPIO_PIN);
}
// System clock configuration (implement for your specific clock needs)
void SystemClock_Config(void) {
// Configure HSI, PLL, HCLK, PCLK as needed for your application
}
After Wake from Stop Mode
When the device wakes from Stop mode, the clock system needs to be reconfigured because the main clocks were stopped:
// After returning from HAL_PWR_EnterSTOPMode(), reconfigure clocks
void WakeUp_ClockRestore(void) {
// Re-enable HSI or HSE and reconfigure PLL if needed
SystemClock_Config();
}
For Sleep mode (not Stop), clock restoration is automatic — the core simply resumes where it stopped.
Low-Power Mode Selection Guide
Application Requirement Recommended Mode
----------------------- ----------------
Must keep running at lower speed? Low-Power Run
Waiting for any interrupt? Sleep or Low-Power Sleep
Waiting for timed event or button? Stop 0 or Stop 1
Maximum power savings needed? Stop 1
RTC must stay running? Stop 0 or Stop 1 (LSE keeps RTC)
Power Consumption Reference
Typical current consumption figures for PY32F003 at 3.3V:
| Mode | Typical Current |
|---|---|
| Run (48 MHz) | ~5 mA |
| Sleep | ~1 mA |
| Stop 0 | ~50 µA |
| Stop 1 | ~10 µA |
These figures vary with peripheral activity, temperature, and supply voltage. Always measure actual consumption in your specific circuit.
Final Thoughts
The PY32F0xx low-power mode system is well-designed for IoT and battery-powered applications. The five modes cover the full spectrum from minimal savings (Low-Power Run) to maximum savings (Stop 1), and the HAL API makes entering and exiting these modes straightforward.
The key to effective low-power design:
- Identify how much time the device spends idle
- Choose the deepest sleep mode that still supports the required wake-up sources
- Minimize initialization time on wake-up to maximize time in sleep
Low-power modes are not optional for battery-powered embedded design — they are the design.