-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Power Management
Information is based on #7726
At the microcontroller (MCU) level there are several ways to reduce power usage. Some methods for reducing power consumption are:
- Slow down the clocks, especially the main clock for the core (CPU and main logic) of the device.
- Reduce the supply voltage to the core of the device.
- Stop the main clock.
- Turn off power to the core.
- Turn off power to the clock generator(s).
- Turn off clocks to unused peripherals and peripheral bus controllers.
- Turn off power to unused peripherals.
- Put memory into a low-power (RAM data retained) “not instantly accessible” mode.
- Turn off power to unused sections of memory.
- Turn off power to the entire device except an external “wake-up” pin.
Each of these methods has consequences. The most significant consequence is that it can take up to several 10s of microseconds to recover or respond to an IRQ or event. Sometimes this is tolerable, other times it is not.
Most MCUs have some sort of “sleep modes”. These sleep modes invoke some combination of the methods above. Typically these modes progressively turn off clocks/power to sets of major functions of the device (ie. [CPU], [CPU+Main Logic], [CPU+Main Logic+Clock Gen], etc.). These sleep modes don’t generally address Active Mode clock speed and core voltage or turning off clocks and/or power to unused parts of the device. All of this is also passive - the application has to manage power on its own by setting each of these parameters when appropriate. This leads to non-portable application code - power management has to be implemented in the application for each specific MCU.
Understanding how the sleep modes and power reduction methods are implemented for each MCU, how all of the methods interact and affect a specific MCU, and how to architecthet power management into the application is an arduous task that the application programmer shouldn’t have to go through.
Therefore the new power management api was born. A specific implementation called pm_layered is provided to automatically switch to sleep modes. The pm_layered module will be explained in the next sections.
The pm api provides three functions: pm_set_lowest, pm_off and pm_reboot. As the name suggests, pm_off powers down the node and stops all further operation. pm_reboot initiates a reboot.
Finally, pm_set_lowest is responsible for choosing the minimal applicable power level.
The implementation is not using any weak definitions. Furthermore, we use defines to determine if the cpu provides their own implementations using #define PROVIDES_PM_...
The pm_layered module superseeds the default pm api, by introducing up to 4 different power modes that can be blocked or unblocked. It is up to the developer to choose the right number of these modes, as there might be more than 4 levels.
The interface consists of three functions defined in drivers/include/periph/pm.h. An additional module pm_layered allows for an automatic usage of pre-defined power levels on the CPU level. In this case, an additional function pm_set is required to be implemented by the CPU.
pm_layered shares the same idea of pm, to function as a fallback and defines in the form of PROVIDES_PM_???.
CPUs and Families can define specific implementations.
A good example is the stm32_common and cortexm_common platform. The stm32_common CPU is providing pm_set and therefore is using pm_layered.