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

FreeRTOS power consumption spikes when in System ON sleep mode

Hello -

We are developing on the nRF52840-DK, using SDK 15.3.0 and FreeRTOS with tickless idle. The SoftDevice is disabled. Using the PPK v2.3.1 when our app is in System ON sleep mode, we are seeing power consumption spikes at regular ~1s intervals:

During this period our app is waiting on messages from a FreeRTOS message queue. At this time there are no other pending tasks:

xQueueReceive(msgQueue, &msg, maxDelayMS);

After maxDelayMS we enter System OFF sleep mode and the current drops for the duration:

NRF_POWER->SYSTEMOFF = 1;

I toggle an onboard LED in the vPortSuppressTicksAndSleep() function before and after System ON sleep. The LED toggles only once after the specified delay, which leads me to believe that the sleep logic is working as expected. After some experimentation, I found that the RTC wakeup interrupt configuration leads to the spikes. If I comment out this code, the spikes no longer occur, but of course the app never exits System ON sleep:

/* Configure CTC interrupt */
nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);

Is there anything we can do in our app or FreeRTOS configuration to eliminate these spikes?

Regards,

Brian

Parents
  • Your system seems to be sleeping most of the time and hence you managed to pull the power consumption low most of the time.

    The configEXPECTED_IDLE_TIME_BEFORE_SLEEP in the FreeRTOSConfig.h file decides the expected sleep time and after which the RTOS will wakeup to see if everything is ok and do the book keeping. You can increase this to a suitable value for you app and this should move the spikes farther apart if you increase the value.

  • Hello -

    I apologize for the very late follow-up here. We've since brought up our custom nRF52840 board and we are still seeing regular power consumption spikes at ~1s intervals when running under FreeRTOS, with tickless idle enabled, and using the vPortSuppressTicksAndSleep() function provided in the nRF52 SDK v17.0.

    We enter System ON sleep mode by waiting forever on a FreeRTOS task queue. Using the PPK, this is what we see when that happens:

    My understanding is that the spikes are related to the RTC wakeup configuration I described above.

    Changing the value of configEXPECTED_IDLE_TIME_BEFORE_SLEEP doesn't seem to help. As a test I bumped that value up to 2000 and the resulting power draw was much higher and constant.

    I did some experiments to try and isolate the problem. One of those experiments disables tickless idle and instead calls __WFE() from our application idle hook function. Here is the idle hook implementation:

    void vApplicationIdleHook( void )
    {
    #ifdef SOFTDEVICE_PRESENT
    	if (nrf_sdh_is_enabled())
    	{
    		uint32_t err_code = sd_app_evt_wait();
    		APP_ERROR_CHECK(err_code);
    	}
    	else
    #endif
    	{
    		/* No SD -  we would just block interrupts globally.
    		* BASEPRI cannot be used for that because it would prevent WFE from wake up.
    		*/
    		do{
    			__WFE();
    		} while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
    	}
    #endif
    }
    

    When we run this configuration, without tickless idle, the power spikes are essentially eliminated, but the average current consumption is much higher:

    Based on this experiment I am wondering if something in the vPortSuppressTicksAndSleep() function reduces current consumption. Ideally we are looking for a solution that eliminates the spikes but also reduces power consumption down to what we've measured when tickless idle is enabled.

    Thank you again for your helpful feedback. Looking forward to finding a solution.

    Regards,

    Brian

  • That is a worrisome finding. In your application idle hook, you are using both sd_app_evt_wait and WFE. Which one is executed by your application? Are you using logs? can you test once by disabling logs ?(NRF_LOG_ENABLED set to 0 in sdk_config.h file)

  • Susheel -

    Welcome back to this case. In our application idle hook we are calling WFE in the profile I shared three days ago. We do not have NRF_LOG_ENABLED in our build. We do have SOFTDEVICE_PRESENT set to 1 in our build, though this test app isn't using the SoftDevice. Hence the call to nrf_sdh_is_enabled() returns false and we call WFE. The code I shared from the idle hook was basically copied from the SDK vPortSuppressTicksAndSleep() function. Just to clarify, is there anything wrong with this approach?

    That said, I remembered that we have the watch dog timer enabled. In our build we have the NRFX_WDT_CONFIG_BEHAVIOR set to 1 (Run in SLEEP, Pause in HALT). I reverted our code back to use tickless idle, the Nordic vPortSuppressTicksAndSleep() function, but disabled the watch dog timer. That seems to have eliminated the power consumption spikes. The strange thing is that setting the NRFX_WDT_CONFIG_BEHAVIOR to 1, 0, or 8 doesn't eliminate the spikes. Nor does changing the NRFX_WDT_CONFIG_RELOAD_VALUE. Unless the watch dog timer is completely disabled, we see the spikes at ~1s intervals, even if the reload value is much higher.

    I hope these findings help to pin down the root cause. We do want to run with tickless idle and also have the WDT enabled to catch any unexpected stalls while not sleeping. For reference, here is our WDT setup and feed code:

    static nrf_drv_wdt_channel_id wdt_channel_id;
    
    static void watchdog_init(void)
    {
    	nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    	nrf_drv_clock_lfclk_request(NULL);
    	ret_code_t err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
    	APP_ERROR_CHECK(err_code);
    	nrf_drv_wdt_channel_alloc(&wdt_channel_id);
    	nrf_drv_wdt_enable();
    }
    
    static void watchdog_feed(void)
    {
    	nrf_drv_wdt_feed();
    }
    

    Regards,

    Brian

  • Hello -

    Just a quick check to see if there is anything else we can try here. Another thought I had was to turn off /on the WDT inside vPortSuppressTicksAndSleep() before and after sleep.

    Regards,

    Brian

Reply Children
No Data
Related