This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Timed Sleep (System ON) mode: do I have to always call nrf_pwr_mgmt_run() or sd_app_evt_wait() inside a loop ?

I have made a state machine in which

  1. I first initialize gpios, power management, clocks, and ble stack
  2. I then put nrf into deep sleep (System OFF) state
  3. A wakeup signal over gpio from an external on-board device wakes up the nrf
  4. I then enter a state where I initialize remaining hardware peripherals on nrf such as timers, uart, gatt, advertising etc.
  5. Next I enter a state where I send some data to external on board device and wait for ACK response on GPIO. While waiting for some timeout interval X, I want to sleep. As I want to preserve my system state, I cannot put nrf into a deep sleep(System OFF) as it resets the system upon wakeup. And so, I then try to put nrf into timed shallow or nap sleep(System ON)
    1. I start the RTC timer based on 32 KHZ LFCLK XTAL with an empty timeout handle. 
    2. After this I immediately make a call to function nrf_pwr_mgmt_run() and I notice the call is non-blocking and function immediately returns. Below is sample code of how I am doing this. This is unlike nrf_pwr_mgmt_shutdown() or nrf_power_system_off() which are blocking function calls for putting system in OFF mode. 

static void Timeout_Handler( void * p_context )
{
  UNUSED_PARAMETER(p_context);
}

/* Create an RTC timer and register time ouut handler */
err_code = app_timer_create(&m_shallow_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            Timeout_Handler);
APP_ERROR_CHECK(err_code);

/* Start the timer for 5 sec */
ret_code_t err_code = app_timer_start(m_shallow_timer_id,
                                      APP_TIMER_TICKS(5000), NULL);
APP_ERROR_CHECK(err_code);

/* Go to shallow sleep */
nrf_pwr_mgmt_run();

/* The above function call returns immediately!! Is it non-blocking ? */

After grep search for nrf_pwr_mgmt_run() and sd_app_evt_wait() in nrf examples, I noticed that either of these functions are always called inside an infinite loop (naturally as they are non-blocking). However I couldnt find any other examples where they are called inside a conditional loop.

So would it be correct to say that correct way of using these functions is to always call them inside a loop as its a non-blocking function and it cannot be used without a loop ?

So to make my  shallow sleep work, I modified the time out event handler which sets a flag indicating that a timeout happened. I enclosed my nrf_pwr_mgmt_run() inside a conditional loop with condition checking if timeout happened or not.

volatile bool bShallowSleepTimedOutFlag = false;

static void Timeout_Handler( void * p_context )
{
  UNUSED_PARAMETER(p_context);

  assert( false == bShallowSleepTimedOutFlag);

  bShallowSleepTimedOutFlag = true;
}

/* Create an RTC timer and register time ouut handler */
err_code = app_timer_create(&m_shallow_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            Timeout_Handler);
APP_ERROR_CHECK(err_code);

/* Start the timer for 5 sec */
ret_code_t err_code = app_timer_start(m_shallow_timer_id,
                                      APP_TIMER_TICKS(5000), NULL);
APP_ERROR_CHECK(err_code);

/* Go to shallow sleep */                                      
while(false == bShallowSleepTimedOutFlag)
{
    /* This non-blocking function call has to be always called inside a loop */
    nrf_pwr_mgmt_run();
}

Is this the above code most elegant way to do a timed shallow sleep (System ON) ?

Also, is it possible to use deep sleep(System OFF) being in 4th state of my state machine by somehow preserving system state and restoring it after wakeup ?

  • Hello,

    I don't understand your last snippet. Is (part of) this in your main() function?

    The short answer to your question is to do it like the examples. Go to sleep in your main-loop, and don't prevent your device to go to sleep? Why don't you want to go to sleep (nrf_pwr_mgmt_run()) before this flag is set to false?

    All timers that you have started will run, and your interrupts will still trigger in "moderate sleep". 

     

    Is this the above code most elegant way to do a timed shallow sleep (System ON) ?

     I would say that the way it is in the examples is better. What you end up with in this scenario is a device that doesn't go to sleep when your timer is running (if I understand it correctly), and hence, it will use a lot more power.

     

    Also, is it possible to use deep sleep(System OFF) being in 4th state of my state machine by somehow preserving system state and restoring it after wakeup ?

     You can consider the System OFF as turning off your chip. Whenever it wakes up from system off, it will start from the top of the application. 

    1: You can store some state in flash, and read this on startup, if that is a possible solution.

    2: It is only possible to wake up from System OFF through an external interrupt, and not on a timer interrupt, because you can't run timers in System OFF.

Related