Link Search Menu Expand Document

Power Management and Sleep

The Poll-Sleep-Interrupt Cycle

The entire protocol stack shall be a single threaded state machine, working in an infinite poll() -> sleep() cycle.

Programmer is responsible for an application level poll function! The OS is responsible for sleeping and waking up.

MCU must provide hardware mechanism for waking up from sleep, which is called interrupt, such as

  • Timer Hardware - Scheduledto wake up within certain ticks
  • GPIO - e.g. end-user pressed a button
  • Radio - A wireless packet is received

Power State

Hornet implementation puts MCU into “low power mode” while sleeping to further conserving energy.

Low power mode is crucial to battery powered devices. For mains powered device, lower power consumption corresponds to longer life of AC/DC components which affects overall life of the device.

typedef enum {
    PM_STATE_ACTIVE = 0,
    PM_STATE_IDLE = 1,
    PM_STATE_SUSPENDED = 2,
    PM_STATE_SOFT_OFF = 3,
} hornet_power_state_t;

The deeper power state, the less functional the MCU will be.

Power State Wake Up Events
PM_STATE_ACTIVE Keeps polling
PM_STATE_IDLE Any event
Most importantly, RF Radio and RTC Timer
PM_STATE_SUSPENDED GPIO Pins
RTC Timer
PM_STATE_SOFT_OFF GPIO Pins Only

As we can see, for router and RRED, radio needs to on (and listening) all the time, we can only use PM_STATE_IDLE.

For battery powered device and sensors, we need sleep timer. So we can only reach sleep PM_STATE_SUSPENDED. In PM_STATE_SUSPENDED the radio is turned off. As a result, battery powered devices needs to wake up periodically to “poll” queued messages from parent router, using the RTC Timer.

HORNET_ARCH_MAX_PWR_STATE

HORNET_ARCH_MAX_PWR_STATE is the maximum power state the firmware can use. It is defined by default. Usually there is no reason to redefined it.

#ifndef HORNET_ARCH_MAX_PWR_STATE
#if HORNET_DEVICE_TYPE == HORNET_RFD
#define HORNET_ARCH_MAX_PWR_STATE			(PM_STATE_SUSPENDED)
#else
#define HORNET_ARCH_MAX_PWR_STATE			(PM_STATE_IDLE)
#endif
#endif

Power Management

In Hornet code, at the end of iteration of poll, before entering the sleep mode, our code queries every layer for the maximum power state it can use.

For example, for MAC layer, mac_get_power_state() is defined. Below is how it works.

  1. If there is unprocessed incoming message, do not sleep at all (returns PM_STATE_ACTIVE);
  2. If stack is in ed scan or active scan mode, do not turn off the radio (returns PM_STATE_IDLE);
  3. If the stack is sending a message or waiting for ACK message, do not turn off the radio (returns PM_STATE_IDLE);
  4. Otherwise, returns HORNET_ARCH_MAX_PWR_STATE, which could be PM_STATE_IDLE for battery powered devices.

app_get_power_state

The developer has a chance to implement app_get_power_state to further control the power state. The default implementation is below:

hornet_power_state_t app_get_power_state() {
	return HORNET_ARCH_MAX_PWR_STATE;
}

Hornet OS implementation will combine the final power mode from all three functions and use the lowest value of all.