Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Going low power in freertos app

Hi, 

I have an app based on freertos_hrs example (nRF52832, SDK14.2)

I'm trying to get it into low power(sleep) mode, however the idle task keep on running and the system consumes ~4.5mA constantly (ble is off most of the time)

I tried the following:

  • Setting #define configUSE_TICKLESS_IDLE   1 in freeRTOSConfig.h but is does not seem to help.
  • Disabled NRF_Log options in sdk_config.h as several posts suggested
  • Verified that none of my app's tasks is running (All are blocked), neither is the timer task. The only task that seem to run is the idle task.
  • Verified that the idle task handler portTASK_FUNCTION() (part of freertos port) do get to the line portSUPPRESS_TICKS_AND_SLEEP() that eventually calls sd_app_evt_wait()

  • I tried to forcefully call sd_app_evt_wait() from within  the applications idle hook (vApplicationIdleHook(), #define configUSE_IDLE_HOOK  1)
    It does lower the consumed power to few uA, but I keep getting hard faults when ble activity is encountered (not sure exactly what is the cause) - e.g. advertising goes well but when connection is established ble_evt_handler() crashes in case BLE_GAP_EVT_CONNECTED block

Reading the doc it seems that implementing the 1st bullet above should take care of lowering the power but apparently something else is not set correctly.

Any help will be highly appreciated

Thanks in advance

Parents Reply Children
  • Hi Susheel, 

    Thanks for your response. 

    your 2nd code snippet is in the 'heart' of vPortSuppressTicksAndSleep() in port_cmsys_systick.c which is part of the freertos package (sort of 'system file' in higher OSes)

    Do you mean to replace this in place (vPortSuppressTicksAndSleep()) or add the 1st snippet to vApplicationIdleHook() which is in the application file (main.c)

  • Hi Susheel, 

    I've added the 1st snippet to the idle task hook, unfortunately its still in the mA region..

    Is there a way to tell what was the event that caused sd_app_evt_wait() to return ?

  • You should be able to tell by looking into below registers immediately after sd_app_evt_wait.

    (NVIC->ISPR[0] | NVIC->ISPR[1])

    and exclude softdevice specific bits __NRF_NVIC_SD_IRQS_0 (in NVIC->ISPR[0]  ) and __NRF_NVIC_SD_IRQS_1 (in NVIC->ISPR[1]) mentioned in nrf_nvic.h

  • Hi, 

    I followed your advice and placed a breakpoint right after sd_app_evt_wait()

    • __NRF_NVIC_SD_IRQS_0 (nrf_nvic.h) calculated value is : 0x4200F903
    • NVIC->ISPR[0] (@0xE0000100) = 0x02002801 / 0x02000801 

    It seems that all NVIC's bits are SD related (RNG(occasional), RTC0, RADIO & NVMC_IRQ).

    In this case shouldn't the app remain a sleep ?

  • For me it looks like

    0x02002801 are

    0- POWER/CLOCK, 

    11 - RTC0

    13 RNG

    25 SWI5

    all of which should owned by softdevice. 

    I am sorry, there is a flaw in my suggestion, if your application has any higher priority interrupt that is waking your system then our breakpoint here will not work as that interrupt will already have been serviced by the time your breakpoint is hit.

    Can you start by looking at NVIC->ISER[0] bit to see which application interrupts are enabled and start by  disabling those interrupts from your application at the peripheral level. I mean you need to disable that application interrupt inside the peripheral module that is generating that interrupt (NRF_XXX->INTENCLR) and leave it as it is in NVIC. This way we disable the interrupt at the source one by one to see which interrupt is causing your system to wake that frequently.

Related