The power manager is a platform level software module that manages the system's energy modes. Its main purpose is to transition the system to a low energy mode when the processor has nothing to execute. The energy mode the system will transition to is determined each time the system goes to sleep using requirements. These requirements are set by the different software modules (drivers, stacks, application code, etc...). The power manager also ensures a strict control of some power hungry resources such as the high frequency external oscillator (normally called HFXO or SYXO).
Energy modes overview
As a general rule, the following energy modes are available. The description provides an overview of what functionalities are lost in comparison to the previous energy mode.
|EM0||System is fully operational. All peripherals are available. The CPU is executing code.|
|EM1||The CPU is in sleep mode and is not executing any code.|
|EM2||High frequency clock sources are shut down. Peripherals that require a high frequency clock are unavailable or have limited functionalities.|
|EM3||Low frequency clock sources are shut down. Peripherals that require a low frequency clock are unavailable.|
*The EM4 energy mode has been omitted from this list as it is not supported by the power manager. See section Entering EM4 for more details.
Once the system enters a low energy mode, the way to wake it up to EM0 is via interruptions. Once an interruption occurs, the system goes back to the highest energy mode (EM0). However, if the system was in a deep sleep mode (EM2 or EM3), the system may not wake up in a fully restored mode. See section Waking up from sleep for more information.
For more information on the different energy modes, refer to your device's user manual.
Power manager design considerations
The power manager acts as the middleman between the different software modules and the device.
Power Manager Interactions
Any piece of software can interact with the power manager. There are two main interfaces, as described below.
APIs allow you to add and remove requirements on energy modes (EM1, EM2 and EM3). Refer to your chip's reference manual to determine what operations are possible in each energy mode.
The normal use case for these APIs is to add a requirement on a given energy mode before starting a given operation (using one or more peripherals) and removing this requirement once the operation is completed. The more efficient and refined are your operations and the add/remove requirements blocks, the more power efficient your application will be.
For example, when transmitting data on a USART, the system can go to sleep. However, it can only sleep in EM1 mode as otherwise the USART would stop working. The correct way of handling this is to add a requirement on EM1 when the transfer is set up, and remove the requirement on EM1 once the transfer complete ISR is triggered.
The requirements are added and removed via the following APIs:
void sl_power_manager_add_em_requirement(sl_power_manager_em_t em); void sl_power_manager_remove_em_requirement(sl_power_manager_em_t em);
You must always call the functions
sl_power_manager_remove_em_requirement() in pair. If you omit to remove a
requirement previously added on a given energy mode, that will cause your
application to be unable to sleep to a lower energy mode.
You can add and remove requirements from ISR. This is useful to perform a full
restore of the different clock sources when waking-up from a deep sleep energy
mode (more information on that in the
Waking up from deep sleep section).
Upon return from a function call to
the power manager guarantees that all resources related to the requested energy
mode are fully restored and available. You should however add requirements from
an ISR only when this is absolutely necessary, as this can impact power
consumption and interrupt latency.
*Note that software provided by Silicon Labs as part of the different SDKs has, for the most part, a proper and efficient integration with the power manager. You don't have to add and remove requirements for operations performed by these SDK functions unless stated otherwise in the module's user manual.
The power manager offers a notification mechanism. This mechanism allows any piece of software to be notified of any energy mode transition. When transitioning from a high energy mode to a lower one (for example, from EM0 to EM2), the listeners are notified before the transition. When transitioning from a low energy mode to a high energy mode (from EM2 to EM0, for example), the listeners are notified after the transition is completed. The main purpose of these notifications is for the different software modules to "adapt" to the new energy mode applied. For instance, a given software module may not need to have a requirement on EM1 to perform a given operation, but may have to do some modifications to continue to perform its operation in EM2. These modifications can be applied in the notification callback. You must use these notifications from your application if you need to perform such operations. Note that the notifications may be called from an ISR context.
The following API is available to subscribe to notifications. The events to subscribe to are configurable.
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);
*Note that it is not possible to add and remove requirements from a notification.
The process of entering a sleep mode
When using an operating system
When your application uses an Operating System (Micrium OS kernel or FreeRTOS, for example), the process of going to sleep is fully handled by the OS. The system will automatically enter the lowest possible energy mode (depending on the requirements currently set) when the OS enters idle mode (i.e. when all the tasks are pending on something, delayed or suspended). The power manager will ensure the system resumes its operations as soon as a task is resumed, posted or that its delay expires.
When on a baremetal environment, the process of bringing the system into sleep
is your application's duty. You are required to call a function named
sl_power_manager_sleep() when your application is idling. Once you call this
function, the power manager will enter in a sleep loop and won't exit this loop
until a system wakeup is requested after an ISR. Two entry points to this sleep
loop are provided and used by the power manager to determine if it is safe to
enter/return to a low energy mode. These entry points are implemented as
function callbacks. The power manager offers a contributions mechanism, as
multiple different software modules can contribute to the decision. The
software provided by Silicon Labs offers a full integration by contributing to
these callbacks when needed.
|Entry point||Description||Algorithm description|
|This entry point is only called once at the beginning of the ||The functions provided by the different contributors are called one by one and return a boolean value.|
|This function is called each time an interrupt (or multiple interrupts) wakes the system up, before re-entering sleep. It is used to determine if the system should go back to sleep or wake-up.||The functions provided by the different software modules are called one by one and return one of these states:|
Two fixed functions are available for your application to implement and contribute to these two entry points decision:
Waking up from sleep
The device wakes up from sleep when an interruption occurs. This causes the system to go back to the EM0 energy mode and the CPU to resume code execution (and execute interrupt's ISR). The state of the system when executing the interrupt's ISR will however differ depending on the energy mode the system was sleeping into.
|Energy mode the system was sleeping into||System restore state|
|EM1||On ISR entry, the system will be fully restored as it was before entering sleep mode.|
|EM2 or EM3 (deep sleep)||Depending on the wakeup source, some clock sources may not be restored. See following section for more information.|
Waking up from deep sleep
When waking up from deep sleep and executing the interrupt's ISR, the device only restores a fast startup RC oscillator to provide a high frequency clock source for the CPU. The reason being that the process of restoring all the clock sources can be time consuming and requires energy. Depending on the operation that needs to be performed in these ISR, having only one RC oscillator clocking the CPU may be sufficient. It is more energy efficient to not restore all the clock sources in the cases where an ISR with simple processing is executed and the system can get back to a deep sleep mode.
See the sections Synchronous events and
Asynchronous events for more information on the events
that cause a full clock sources restore by the power manager. Note that when
the system gets back to thread mode (if an os task is posted or if a decision
to wake-up is taken using the
sleep_on_isr_exit entry point in a baremetal
application) the power manager will always perform a full restore before.
Following table provides examples of clock sources that are not always automatically restored when waking up from deep sleep.
|Energy mode the system was sleeping to||Clock sources|
|EM3||Clock sources from EM2 + LFXO and LFRCO|
Synchronous events are real-time timed events that are expected to occur in the future. Processing these events will require a full restore of the clock sources. Since the process of restoring the clock sources can be time consuming, the power manager will ensure to wake up in advance and proceed to a full restore of the clock sources in order to be ready on time to process the synchronous event.
To register an event that will be considered as synchronous by the power
manager, you must use the timer functionality provided by the
module. Any timer (periodic or one-shot) created with the argument option_flags
set to 0 will be considered as a synchronous event that requires a full restore
of the clock sources on expiration. If you create a timer with the option flag
SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG, you won't have a
guarantee that all the clock sources will be restored on expiration. For more
information on how to create a timer, refer to the
sl_sleeptimer user manual.
Asynchronous events are any other events (ISRs) that occur in the system. Those
events are unexpected by their nature. When they occur and the system was deep
sleeping, the various clock sources are not guaranteed to be restored. As for
normal operations, if you need to perform or initiate an operation that
requires some specific clock sources from your ISR, you must add a requirement
on the necessary energy mode to force a restore of the clock sources. If you
add a requirement on EM2, upon return of the function
sl_power_manager_add_em_requirement() the low frequency clock sources are
guaranteed to be available and ready. If you add a requirement on EM1, upon
return of the function
sl_power_manager_add_em_requirement() the high and low
frequency clock sources are guaranteed to be available and ready.
Note that a call to
sl_power_manager_add_em_requirement() that triggers a
high frequency clock restore will take some time to execute and will stop the
CPU for some time. If this is a problem for your application, consider making
sure that a requirement on EM1 is added before entering sleep mode.
The time required to restore the clock sources depends on many factors. Refer to your device's datasheet and user manual for more details.
Tips and tricks to optimize your power consumption with the power manager
Refine your requirement blocks as much as possible
You may be tempted to have a very broad coverage of operations between the moment you add a requirement and the moment you remove it. While this offers some simplicity benefits, this is not very efficient. In order to achieve better power consumption, the periods where a requirement is added must be as small and as refined as possible. This will avoid cases where the system enters sleep mode in a high energy mode when it could enter a lower one.
Fine tune the restore time overhead
As described earlier, restoring the clock sources (especially the
high-frequency clock sources) can be time consuming. Since this restore time
can vary depending on many factors (external crystal type, ambient temperature,
etc) the power manager implements a mechanism where it measures the time
required to restore some high frequency clock sources. This restore time is
used when deep sleeping to trigger a clock sources restore in advance in
expectation of an upcoming synchronous event. In order to maintain real-time
responsiveness of your application, it is vital to have a restore time that is
not too short, as that would cause the clock sources not to be ready on time.
For that reason, the power manager always adds a safety margin to the restore
time it measures. However, since the system consumes more power when these
clock sources are restored, the shorter this restore time is, the better will
the energy consumption be. The functions
sl_power_manager_schedule_wakeup_set_restore_overhead_tick() are offered to
fine tune this safety overhead.
Please note that because of hardware limitations on series 2 devices supporting
EM1P energy mode, the power manager is not always able to measure the high
frequency clock restore time. Since the default restore time has a large
margin, it is possible that the restore time remains longer than needed.
Therefore, if higher power consumption than expected is observed,
sl_power_manager_schedule_wakeup_set_restore_overhead_tick() can be used to
reduce the restore time by passing a negative overhead.
The power manager doesn't support the EM4 energy mode. As such, it will never take the decision to enter this energy mode. However, that doesn't prevent you from using this energy mode.
As described in this document, the power manager bases its decisions of sleeping to a given energy mode on requirements that are added and removed by the diferent software modules. Given the very different nature of EM4, this approach is not well suited to take a decision to enter this energy mode. Most of the time, when the decision is taken to enter EM4, the sleep period will be fairly long, and the wakeup source will be quite basic (GPIO interrupt, low energy timer compare match, etc.). As such, in most circumstances, your application is in the best position to take this decision.
A good approach for your application is to enter EM4 when the power manager is
about to enter a low energy mode. This is possible by subscribing to a
notification of entering a low energy mode (see Notifications
for more details). In this notification callback, you can evaluate if you want
to enter EM4 instead. To enter EM4, you can simply call the function:
EMU_EnterEM4(). Keep in mind that waking up from this energy mode will result
in a reset of the device. Restoring previous states after wakeup is your
application's duty. Refer to your device's reference manual for more
information on the EM4 energy mode.
However, be aware that entering the EM4 energy mode will abort any operation that require a higher energy mode. If, for example, you need a transfer to complete on the UART via DMA before entering EM4, you must wait for its completion. This can be done by polling the STATUS register of the controller.