Power Manager

Description

Power Manager.

Initialization

The power manager must be initialized prior to any call to power manager API. If sl_system is used, only sl_system_init() must be called, otherwise sl_power_manager_init() must be called manually. Note that the power manager must be initialized after the clock(s), when initialized manually, as the power manager check which oscillators are used during the initialization phase.

Add and remove requirements

The drivers should add and remove energy mode requirements, at runtime, on the lowest energy mode for them depending on their state. When calling sl_power_manager_sleep(), the lowest possible Energy mode will be automatically selected.

It is possible to add and remove requirements from ISR. If a specific energy mode is required in the ISR, but not required to generate the interrupt, a requirement on the energy mode can be added from the ISR. It is guaranteed that the associated clock will be active once sl_power_manager_add_requirement() returns. The EM requirement can be also be removed from an ISR.

Subscribe to events

It possible to get notified when the system transition from a power level to another power level. This can allow to do some operations depending on which level the system goes, such as saving/restoring context.

Sleep

When the software has no more operation and only need to wait for an event, the software must call sl_power_manager_sleep(). This is automatically done when the kernel is present, but it needs to be called from the super loop in a baremetal project.

Query callback functions

Is OK to sleep

Between the time sl_power_manager_sleep is called and the MCU is really put in a lower Energy mode, it is possible that an ISR occur and require the system to resume at that time instead of sleeping. So a callback is called in a critical section to validate that the MCU can go to sleep.

In case of an application that runs on an RTOS, the RTOS will take care of determining if it is ok to sleep. In case of a baremetal application, the function sl_power_manager_is_ok_to_sleep() will be generated automatically by Simplicity Studio's wizard. The function will look at multiple software modules from the SDK to take a decision. The application can contribute to the decision by defining the function app_is_ok_to_sleep(). If any of the software modules (including the application via app_is_ok_to_sleep()) return false, the process of entering in sleep will be aborted.

Sleep on ISR exit

When the system enters sleep, the only way to wake it up is via an interrupt or exception. By default, the power manager will assume that when an interrupt occurs and the corresponding ISR has been executed, the system must not go back to sleep. However, in the case where all the processing related to this interrupt is performed in the ISR, it is possible to go back to sleep by using this hook.

In case of an application that runs on an RTOS, the RTOS will take care of determining if the system can go back to sleep on ISR exit. The power manager will ensure the system resumes its operations as soon as a task is resumed, posted or that its delay expires. In case of a baremetal application, the function sl_power_manager_sleep_on_isr_exit() will be generated automatically by Simplicity Studio's wizard. The function will look at multiple software modules from the SDK to take a decision. The application can contribute to the decision by defining the function app_sleep_on_isr_exit(). The generated function will take a decision based on the value returned by the different software modules (including the application via app_sleep_on_isr_exit()):

SL_POWER_MANAGER_IGNORE: if the software module did not cause the system wakeup and/or doesn't want to contribute to the decision. SL_POWER_MANAGER_SLEEP: if the software module did cause the system wakeup, but the system should go back to sleep. SL_POWER_MANAGER_WAKEUP: if the software module did cause the system wakeup, and the system should not go back to sleep.

If any software module returned SL_POWER_MANAGER_SLEEP and none returned SL_POWER_MANAGER_WAKEUP, the system will go back to sleep. Any other combination will cause the system not to go back to sleep.

Debugging feature

By setting the configuration define SL_POWER_MANAGER_DEBUG to 1, it is possible to record the requirements currently set and their owner. It is possible to print at any time a table that lists all the added requirements and their owner. This table can be printed by caling the function sl_power_manager_debug_print_em_requirements(). Make sure to add the following define

#define CURRENT_MODULE_NAME "<Module printable name here>"

to any application code source file that adds and removes requirements.

Usage Example

#define EM_EVENT_MASK_ALL (SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM0 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM0 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM1 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM1 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM2 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM2 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM3 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM3)
.event_mask = EM_EVENT_MASK_ALL,
.on_event = my_events_callback,
}
void main(void)
{
// Initialize the power manager; not needed if sl_system_init() is used.
// Limit sleep level to EM1
// Subscribe to all event types; get notified for every power transition.
while (1) {
// Actions
[...]
if (completed) {
// Remove energy mode requirement, can go to EM2 or EM3 now, depending on the configuration
}
// Sleep to lowest possible energy mode; This call is not needed when using the kernel.
// Will resume after an interrupt or exception
}
}
void my_events_callback(sl_power_manager_em_t from,
{
printf("Event:%s-%s\r\n", string_lookup_table[from], string_lookup_table[to]);
}

Data Structures

struct  sl_power_manager_em_transition_event_info_t
 TODO.
 
struct  sl_power_manager_em_transition_event_handle_t
 TODO.
 

Functions

void sl_power_manager_debug_print_em_requirements (void)
 Print a table that describes the current requirements on each energy mode and their owner.
 
sl_status_t sl_power_manager_init (void)
 Initialize Power Manager module.
 
void sl_power_manager_sleep (void)
 Sleep at the lowest allowed energy mode.
 
void sl_power_manager_add_em_requirement (sl_power_manager_em_t em)
 Adds requirement on given energy mode.
 
void sl_power_manager_remove_em_requirement (sl_power_manager_em_t em)
 Removes requirement on given energy mode.
 
void sl_power_manager_subscribe_em_transition_event (sl_power_manager_em_transition_event_handle_t *event_handle, const sl_power_manager_em_transition_event_info_t *event_info)
 Registers a callback to be called on given Energy Mode transition(s).
 
void sl_power_manager_unsubscribe_em_transition_event (sl_power_manager_em_transition_event_handle_t *event_handle)
 Unregisters an event callback handle on Energy mode transition.
 
int32_t sl_power_manager_schedule_wakeup_get_restore_overhead_tick (void)
 Get configurable overhead value for early restore time in Sleeptimer ticks when a schedule wake-up is set.
 
void sl_power_manager_schedule_wakeup_set_restore_overhead_tick (int32_t overhead_tick)
 Set configurable overhead value for early restore time in Sleeptimer ticks used for schedule wake-up.
 
uint32_t sl_power_manager_schedule_wakeup_get_minimum_offtime_tick (void)
 Get configurable minimum off-time value for schedule wake-up in Sleeptimer ticks.
 
void sl_power_manager_schedule_wakeup_set_minimum_offtime_tick (uint32_t minimum_offtime_tick)
 Set configurable minimum off-time value for schedule wake-up in Sleeptimer ticks.
 
bool sl_power_manager_is_latest_wakeup_internal (void)
 Determines if the HFXO interrupt was part of the last wake-up and/or if the HFXO early wakeup expired during the last ISR and if it was the only timer to expire in that period.
 

Macros

#define CURRENT_MODULE_NAME   "Anonymous"
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM0   (1 << 0)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM0   (1 << 1)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM1   (1 << 2)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM1   (1 << 3)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM2   (1 << 4)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM2   (1 << 5)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM3   (1 << 6)
 
#define SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM3   (1 << 7)
 

Typedefs

typedef uint32_t sl_power_manager_em_transition_event_t
 Mask of all the event(s) to listen to.
 
typedef void(* sl_power_manager_em_transition_on_event_t) (sl_power_manager_em_t from, sl_power_manager_em_t to)
 Typedef for the user supplied callback function which is called when an energy mode transition occurs.
 

Enumerations

enum  sl_power_manager_em_t {
  SL_POWER_MANAGER_EM0 = 0,
  SL_POWER_MANAGER_EM1,
  SL_POWER_MANAGER_EM2,
  SL_POWER_MANAGER_EM3,
  SL_POWER_MANAGER_EM4
}
 Energy modes.
 
enum  sl_power_manager_on_isr_exit_t {
  SL_POWER_MANAGER_IGNORE = (1UL << 0UL),
  SL_POWER_MANAGER_SLEEP = (1UL << 1UL),
  SL_POWER_MANAGER_WAKEUP = (1UL << 2UL)
}
 On ISR Exit Hook answer.
 

Function Documentation

◆ sl_power_manager_debug_print_em_requirements()

void sl_power_manager_debug_print_em_requirements ( void  )

Print a table that describes the current requirements on each energy mode and their owner.

◆ sl_power_manager_init()

sl_status_t sl_power_manager_init ( void  )

Initialize Power Manager module.

Returns
Status code

◆ sl_power_manager_sleep()

void sl_power_manager_sleep ( void  )

Sleep at the lowest allowed energy mode.

Note
Must not be called from ISR
Note
This function will expect and call a callback with the following signature: bool sl_power_manager_is_ok_to_sleep(void)
This function can be used to cancel a sleep action and handle the possible race condition where an ISR that would cause a wakeup is triggered right after the decision to call sl_power_manager_sleep() has been made.

Usage example:

void main(void)
{
while (1) {
tick();
}
}

◆ sl_power_manager_add_em_requirement()

void sl_power_manager_add_em_requirement ( sl_power_manager_em_t  em)
inline

Adds requirement on given energy mode.

Parameters
emEnergy mode to add the requirement to:

◆ sl_power_manager_remove_em_requirement()

void sl_power_manager_remove_em_requirement ( sl_power_manager_em_t  em)
inline

Removes requirement on given energy mode.

Parameters
emEnergy mode to remove the requirement to:

◆ sl_power_manager_subscribe_em_transition_event()

void sl_power_manager_subscribe_em_transition_event ( sl_power_manager_em_transition_event_handle_t event_handle,
const sl_power_manager_em_transition_event_info_t event_info 
)

Registers a callback to be called on given Energy Mode transition(s).

Parameters
event_handleEvent handle (no initialization needed).
event_infoEvent info structure that contains the event mask and the callback that must be called.
Note
Adding and removing requirement(s) from a callback on a transition event is not supported.
The parameters passed must be persistent, meaning that they need to survive until the callback fires.

Usage example:

#define EM_EVENT_MASK_ALL ( SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM0 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM0 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM1 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM1 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM2 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM2 \
| SL_POWER_MANAGER_EVENT_TRANSITION_ENTERING_EM3 \
| SL_POWER_MANAGER_EVENT_TRANSITION_LEAVING_EM3)
.event_mask = EM_EVENT_MASK_ALL,
.on_event = my_callback,
};
void my_callback(sl_power_manager_em_t from,
{
[...]
}
void main(void)
{
}

◆ sl_power_manager_unsubscribe_em_transition_event()

void sl_power_manager_unsubscribe_em_transition_event ( sl_power_manager_em_transition_event_handle_t event_handle)

Unregisters an event callback handle on Energy mode transition.

Parameters
event_handleEvent handle which must be unregistered (must have been registered previously).
Note
An EFM_ASSERT is thrown if the handle is not found.

◆ sl_power_manager_schedule_wakeup_get_restore_overhead_tick()

int32_t sl_power_manager_schedule_wakeup_get_restore_overhead_tick ( void  )

Get configurable overhead value for early restore time in Sleeptimer ticks when a schedule wake-up is set.

Returns
Current overhead value for early restore time.

◆ sl_power_manager_schedule_wakeup_set_restore_overhead_tick()

void sl_power_manager_schedule_wakeup_set_restore_overhead_tick ( int32_t  overhead_tick)

Set configurable overhead value for early restore time in Sleeptimer ticks used for schedule wake-up.

Must be called after initialization else the value will be overwritten.

Parameters
overhead_tickOverhead value to set for early restore time.
Note
The overhead value can also be negative to remove time from the restore process.

◆ sl_power_manager_schedule_wakeup_get_minimum_offtime_tick()

uint32_t sl_power_manager_schedule_wakeup_get_minimum_offtime_tick ( void  )

Get configurable minimum off-time value for schedule wake-up in Sleeptimer ticks.

Returns
Current minimum off-time value for schedule wake-up.
Note
Turning on external high frequency clock, such as HFXO, requires more energy since we must supply higher current for the wake-up. Therefore, when an 'external high frequency clock enable' is scheduled in 'x' time, there is a threshold 'x' value where turning off the clock is not worthwhile since the energy consumed by taking into account the wake-up will be greater than if we just keep the clock on until the next scheduled clock enabled. This threshold value is what we refer as the minimum off-time.

◆ sl_power_manager_schedule_wakeup_set_minimum_offtime_tick()

void sl_power_manager_schedule_wakeup_set_minimum_offtime_tick ( uint32_t  minimum_offtime_tick)

Set configurable minimum off-time value for schedule wake-up in Sleeptimer ticks.

Parameters
minimum_offtime_tickminimum off-time value to set for schedule wake-up.
Note
Turning on external high frequency clock, such as HFXO, requires more energy since we must supply higher current for the wake-up. Therefore, when an 'external high frequency clock enable' is scheduled in 'x' time, there is a threshold 'x' value where turning off the clock is not worthwhile since the energy consumed by taking into account the wake-up will be greater than if we just keep the clock on until the next scheduled clock enabled. This threshold value is what we refer as the minimum off-time.

◆ sl_power_manager_is_latest_wakeup_internal()

bool sl_power_manager_is_latest_wakeup_internal ( void  )

Determines if the HFXO interrupt was part of the last wake-up and/or if the HFXO early wakeup expired during the last ISR and if it was the only timer to expire in that period.

Returns
true if power manager sleep can return to sleep, false otherwise.

Typedef Documentation

◆ sl_power_manager_em_transition_event_t

Mask of all the event(s) to listen to.

◆ sl_power_manager_em_transition_on_event_t

typedef void(* sl_power_manager_em_transition_on_event_t) (sl_power_manager_em_t from, sl_power_manager_em_t to)

Typedef for the user supplied callback function which is called when an energy mode transition occurs.

Parameters
fromEnergy mode we are leaving.
toEnergy mode we are entering.

Enumeration Type Documentation

◆ sl_power_manager_em_t

Energy modes.

Enumerator
SL_POWER_MANAGER_EM0 

Run Mode (Energy Mode 0)

SL_POWER_MANAGER_EM1 

Sleep Mode (Energy Mode 1)

SL_POWER_MANAGER_EM2 

Deep Sleep Mode (Energy Mode 2)

SL_POWER_MANAGER_EM3 

Stop Mode (Energy Mode 3)

SL_POWER_MANAGER_EM4 

Shutoff Mode (Energy Mode 4)

◆ sl_power_manager_on_isr_exit_t

On ISR Exit Hook answer.

Enumerator
SL_POWER_MANAGER_IGNORE 

The module did not trigger an ISR and it doesn't want to contribute to the decision.

SL_POWER_MANAGER_SLEEP 

The module was the one that caused the system wakeup and the system SHOULD go back to sleep.

SL_POWER_MANAGER_WAKEUP 

The module was the one that caused the system wakeup and the system MUST NOT go back to sleep.