Active Power Management Task Force - kbonset/RIOT GitHub Wiki

Active Power Management TF

Shepherds: Jon Pattison, Kaspar Schleiser

Background

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 architect power management into the application is an arduous task that the application programmer shouldn’t have to go through.

Requirements

Some of the requirements for an implementation of Active Power Management (APM) are:

  • Easy for application developers to implement without understanding intimate hardware details. This implies that the API is generic across different hardware.
  • Must be “automatic” from the application’s point of view. The application should not have to actively invoke each power saving method.
  • Must be able to exclude the APM code from the application without side effects.
  • Extensible so additional methods can be implemented in the application.
  • Minimal program size impact.
  • Minimal RAM usage.
  • Negligible MCU performance impact.

Proposed Interface

/**
* @brief   Modify the parameters of apm_set_requirements().
*
* These flags are binary OR'd with the frequency_hz parameter:
* APMF_FREQUENCY_EXACT signifies that the specified frequency is the exact frequency that this
* thread or device requires.
* APMF_FREQUENCY_DONT_CARE indicates that the device or thread doesn't care about clock frequency.
* APMF_FREQUENCY_MAX indicates that this thread or device needs the fastest clock frequency available.
*
* This flag replaces the max_response_time parameter:
* APMF_RESPONSE_TIME_DONT_CARE The thread or device doesn't care how long it takes to wake up.
*
* @{
*/
#define APMF_RESPONSE_TIME_DONT_CARE	0xFFFF
#define APMF_FREQUENCY_EXACT            0x8000000000000000ull;
#define APMF_FREQUENCY_DONT_CARE        0x4000000000000000ull;
#define APMF_FREQUENCY_MAX              0x2000000000000000ull;
/** @} */

/**
* @brief   Changes the operating requirements of a thread or device.
* @param[in]   apm_id		Identifies the thread or device that the requirements apply to.
* @param[in]   frequency_hz    	Desired clock frequency in hertz.
* @param[in]   max_response_time	Maximum tolerable wakeup delay time for this thread or device
*                                  in microseconds.
*
* apm_set_requirements() can be called by any thread or device driver at any time.
*
* kernel_pid_t will cast to apm_deviceid_t.
*/
void apm_set_requirements(apm_deviceid_t apm_id, uint64_t frequency_hz, uint16_t max_response_time);

/**
* @brief   Changes the power state of a peripheral device
* @param[in]   power_state The new desired power state.
* @param[in]   deviceid    APM Identifier for the peripheral device.
*
* @return    The previous power state of the device.
*
* This function gives a process the ability to turn a peripheral device on or off. In cases where
* the peripheral power can’t be turned off, but the clock to the device can be gated, the peripheral
* clock will be stopped or started as appropriate.
*/
int apm_set_device_power(apm_power_state_t power_state, apm_deviceid_t deviceid);

/**
* @brief   Attempts to minimize the power state of the MCU
* @param[in]   must_return When set to 1 this parameter prevents the MCU from entering a power down
*                          state that halts program execution.
*
* This function attempts to minimize the power usage of the MCU  without violating the constraints
* imposed by threads and devices. It is normally called from the idle thread.
*
* NOTE: It is possible that this function could put the MCU in such
* a deep sleep mode that cycling power to the MCU or signalling on
* a specific pin of the MCU (causing a reboot) is the only way to
* wake the device if must_return == 0.
*/
void apm_reduce_power(int must_return = 1);

Request for Comment

Please express your interest in this subject with an email to [email protected].