Sleep

Functionality to help when putting the system to an EM2/EM3/EM4 sleep states where the high frequency clock is disabled.

Enumerations

enum  RAIL_SleepConfig_t {
  RAIL_SLEEP_CONFIG_TIMERSYNC_DISABLED,
  RAIL_SLEEP_CONFIG_TIMERSYNC_ENABLED
}
 The configuration.

Functions

RAIL_Status_t RAIL_ConfigSleep (RAIL_Handle_t railHandle, RAIL_SleepConfig_t sleepConfig)
 Initialize RAIL timer synchronization.
 
RAIL_Status_t RAIL_Sleep (uint16_t wakeupProcessTime, bool *deepSleepAllowed)
 Stop the RAIL timer and prepare RAIL for sleep.
 
RAIL_Status_t RAIL_Wake (RAIL_Time_t elapsedTime)
 Wake RAIL from sleep and restart the RAIL timer.

Detailed Description

Functionality to help when putting the system to an EM2/EM3/EM4 sleep states where the high frequency clock is disabled.

The RAIL library has its own timebase and the ability to schedule operations into the future. When going to any power mode that disables the HF clock used for the radio (EM2/EM3/EM4) it is important that this timebase is synchronized to a running LFCLK and the chip is set to wakeup before the next scheduled event. The APIs in this block are responsible for performing this synchronization. When synchronizing the time base there are two options:

Sleep with timer synchronization:

When sleeping with timer synchronization you must first get the required LFCLK up and running and leave it running across sleep so that the high frequency clock that drives the RAIL time base can be synchronized to it. The RAIL_Sleep() API will also setup a wake event on the timer to wake up wakeupTime before the next timer event so that it can run successfully. See the EFR32 sections on Low-Frequency Clocks and RAIL Timer Synchronization for more setup details.

This is useful for scenarios where you want to maintain packet timestamps across sleep or use the scheduled Rx/Tx APIs while sleeping in between. It does take more time and code to do this synchronization so if your application does not need this it should be avoided.

Example:

#include <rail.h>
#include <rail_types.h>
extern RAIL_Handle_t railHandle;
// Wakeup time for your crystal/board/chip combination
extern uint32_t wakeupTime;
void main(void) {
RAIL_Status_t status;
bool shouldSleep = false;
// This function depends on your board/chip but it must enable the LFCLK
// you intend to use for RTCC sync before we configure sleep as that function
// will attempt to auto detect the clock.
BoardSetupLFCLK()
// Configure sleep for timer synchronization
assert(status == RAIL_STATUS_NO_ERROR);
// Application main loop
while(1) {
// ... do normal app stuff and set shouldSleep when we want to sleep
if (shouldSleep) {
bool sleepAllowed = false;
// Go critical to assess sleep decisions
CORE_ENTER_CRITICAL();
if (RAIL_Sleep(wakeupTime, &sleepAllowed) != RAIL_STATUS_NO_ERROR) {
printf("Error trying to go to sleep!");
CORE_EXIT_CRITICAL();
continue;
}
if (sleepAllowed) {
// Go to sleep
}
// Wakeup and sync the RAIL timebase back up
CORE_EXIT_CRITICAL();
}
}
}

Sleep without timer synchronization:

When sleeping without timer synchronization you are free to enable only the LFCLK's and wake sources required by the application. RAIL will not attempt to configure any wake events and may miss anything that occurs over sleep.

This is useful for scenarios where your application does not care about packet timestamps or scheduling operations accurately over sleep.

Example:

#include <rail.h>
#include <rail_types.h>
extern RAIL_Handle_t railHandle;
void main(void) {
RAIL_Status_t status;
bool shouldSleep = false;
// Configure sleep for timer synchronization
assert(status == RAIL_STATUS_NO_ERROR);
// Application main loop
while(1) {
// ... do normal app stuff and set shouldSleep when we want to sleep
if (shouldSleep) {
bool sleepAllowed = false;
uint32_t sleepTime = 0;
// Go critical to assess sleep decisions
CORE_ENTER_CRITICAL();
if (RAIL_Sleep(0, &sleepAllowed) != RAIL_STATUS_NO_ERROR) {
printf("Error trying to go to sleep!");
CORE_EXIT_CRITICAL();
continue;
}
if (sleepAllowed) {
// Go to sleep and optionally update sleepTime to the correct value
// in microseconds
}
// Wakeup and sync the RAIL timebase back up
RAIL_Wake(sleepTime);
CORE_EXIT_CRITICAL();
}
}
}

Enumeration Type Documentation

◆ RAIL_SleepConfig_t

The configuration.

Enumerator
RAIL_SLEEP_CONFIG_TIMERSYNC_DISABLED 

Disable timer sync before and after sleep.

RAIL_SLEEP_CONFIG_TIMERSYNC_ENABLED 

Enable timer sync before and after sleep.

Definition at line 346 of file rail_types.h.

Function Documentation

◆ RAIL_ConfigSleep()

RAIL_Status_t RAIL_ConfigSleep ( RAIL_Handle_t  railHandle,
RAIL_SleepConfig_t  sleepConfig 
)

Initialize RAIL timer synchronization.

Parameters
[in]railHandleA RAIL instance handle.
[in]sleepConfigA sleep configuration.
Returns
Status code indicating success of the function call.

◆ RAIL_Sleep()

RAIL_Status_t RAIL_Sleep ( uint16_t  wakeupProcessTime,
bool *  deepSleepAllowed 
)

Stop the RAIL timer and prepare RAIL for sleep.

Parameters
[in]wakeupProcessTimeTime in microseconds that the application and hardware need to recover from sleep state.
[out]deepSleepAllowedtrue - system can go to deep sleep. false - system should not go to deep sleep. Deep sleep should be blocked in this case.
Returns
Status code indicating success of the function call.
Warning
The active RAIL configuration must be idle to enable sleep.

◆ RAIL_Wake()

RAIL_Status_t RAIL_Wake ( RAIL_Time_t  elapsedTime)

Wake RAIL from sleep and restart the RAIL timer.

Parameters
[in]elapsedTimeAdd the sleep duration to the RAIL timer before restarting the RAIL timer.
Returns
Status code indicating success of the function call.

If the timer sync was enabled by RAIL_ConfigSleep, synchronize the RAIL timer using an alternate timer. Otherwise, add elapsedTime to the RAIL timer.