I have made a state machine in which
- I first initialize gpios, power management, clocks, and ble stack
- I then put nrf into deep sleep (System OFF) state
- A wakeup signal over gpio from an external on-board device wakes up the nrf
- I then enter a state where I initialize remaining hardware peripherals on nrf such as timers, uart, gatt, advertising etc.
- 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)
- I start the RTC timer based on 32 KHZ LFCLK XTAL with an empty timeout handle.
- 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 ?