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

High power consumption of softdevice

Hello!

I am working on firmware for device that has freertos in the base and implements BLE beacon and 1 service with 7 characteristics. Everything works. But power consumption is too high.

After plenty of tests on final HW, I've created playground based on ble_app_hrs_freertos_pca10040_s132 sample project and switched to sparkfun board.

When have just FreeRTOS with no user-defined tasks, consumption is about 1uA.

After I call  ble_stack_init with code below, I got about 500uA. It is without advertising at all.

static void ble_stack_init(void)
{
    ret_code_t err_code;

    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}

When beacon is enabled I have cca 650uA.

When GATT and beacon are working I have cca 750uA.

I measure with multimeter.

Results seems fine for me except for those 500uA after stack is initialized. Why is it so high? What can I do to lower it?

  • SDK v 15.0
  • NRF_LOG_ENABLED is 0
  • Using RELEASE configuration.
  • Tried S132 and S140 - result is the same
Parents
  • Hi Elias, 

    What are the clock configurations you are using? When you enable the softdevice, it will start RTC0 as a house keeping timer. This needs LFCLK.

  • Hi Aryan,

    I use defaults from ble_app_hrs_freertos_pca10040_s132 example.

    // <e> NRFX_RTC_ENABLED - nrfx_rtc - RTC peripheral driver
    //==========================================================
    #ifndef NRFX_RTC_ENABLED
    #define NRFX_RTC_ENABLED 0
    #endif
    // <q> NRFX_RTC0_ENABLED  - Enable RTC0 instance
     
    
    #ifndef NRFX_RTC0_ENABLED
    #define NRFX_RTC0_ENABLED 0
    #endif
    
    // <q> NRFX_RTC1_ENABLED  - Enable RTC1 instance
     
    
    #ifndef NRFX_RTC1_ENABLED
    #define NRFX_RTC1_ENABLED 0
    #endif
    
    // <q> NRFX_RTC2_ENABLED  - Enable RTC2 instance
     
    
    #ifndef NRFX_RTC2_ENABLED
    #define NRFX_RTC2_ENABLED 0
    #endif
    
    // <o> NRFX_RTC_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt 
    #ifndef NRFX_RTC_MAXIMUM_LATENCY_US
    #define NRFX_RTC_MAXIMUM_LATENCY_US 2000
    #endif
    
    // <o> NRFX_RTC_DEFAULT_CONFIG_FREQUENCY - Frequency  <16-32768> 
    
    
    #ifndef NRFX_RTC_DEFAULT_CONFIG_FREQUENCY
    #define NRFX_RTC_DEFAULT_CONFIG_FREQUENCY 32768
    #endif
    
    // <q> NRFX_RTC_DEFAULT_CONFIG_RELIABLE  - Ensures safe compare event triggering
     
    
    #ifndef NRFX_RTC_DEFAULT_CONFIG_RELIABLE
    #define NRFX_RTC_DEFAULT_CONFIG_RELIABLE 0
    #endif
    
    // <o> NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY
    #define NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY 7
    #endif
    
    // <e> NRFX_RTC_CONFIG_LOG_ENABLED - Enables logging in the module.
    //==========================================================
    #ifndef NRFX_RTC_CONFIG_LOG_ENABLED
    #define NRFX_RTC_CONFIG_LOG_ENABLED 0
    #endif
    // <o> NRFX_RTC_CONFIG_LOG_LEVEL  - Default Severity level
     
    // <0=> Off 
    // <1=> Error 
    // <2=> Warning 
    // <3=> Info 
    // <4=> Debug 
    
    #ifndef NRFX_RTC_CONFIG_LOG_LEVEL
    #define NRFX_RTC_CONFIG_LOG_LEVEL 3
    #endif
    
    // <o> NRFX_RTC_CONFIG_INFO_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_RTC_CONFIG_INFO_COLOR
    #define NRFX_RTC_CONFIG_INFO_COLOR 0
    #endif
    
    // <o> NRFX_RTC_CONFIG_DEBUG_COLOR  - ANSI escape code prefix.
     
    // <0=> Default 
    // <1=> Black 
    // <2=> Red 
    // <3=> Green 
    // <4=> Yellow 
    // <5=> Blue 
    // <6=> Magenta 
    // <7=> Cyan 
    // <8=> White 
    
    #ifndef NRFX_RTC_CONFIG_DEBUG_COLOR
    #define NRFX_RTC_CONFIG_DEBUG_COLOR 0
    #endif

    Anything else I can provide?

  • yes, if you use sd_app_evt_wait in PCA10040 DK for some reason, the average current while advertising jumps to 7mA, but with __WFE it is 900uA. Something is fishy, but i guess for now you can use _WFE !!??

  • We are developing very low power device. And 900uA is too much for us.

    Also information...

    once I get more or less normal consumption cca 600uA (GATT + BEACON) when put nrf_pwr_mgmt_run() in one of the tasks while in port_cmsis_systick.c WFE was used.

  • Hi Aryan,

    I had reported excessive current consumed by the hrs_freertos demo in SDK 14.2 in private ticket 201725, opened March 7 2018. Another Nordic engineer asked me to try that #if 0, which solved the problem. Presumably that led to it being put it into SDK 15.

    I find that even with SDK 15.0, if I change the code back to using sd_app_evt_wait(), I get an increase of 13mA in my application (derived from hrs_freertos). Whatever the underlying problem was in SDK 14.2 or S132 5.1.0, it does not seem to be fixed in SDK 15.0 or S132 6.0.0, so the workaround is still necessary.

    Eric

  • In addition to the FPU and SAADC interrupt-issues Elias Löwe mentions further down, I ran into another issue:

    sd_app_evt_wait();
    returns immidiately the first time it is called (it is also reported here) and power consumption is many milliamps. You probably used WFE in SDK15 instead because you ran into this bug/issue that seems to be intermiettent..

    It works for me if I duplicate a second call

    #ifdef SOFTDEVICE_PRESENT
                if (nrf_sdh_is_enabled())
                {
                    uint32_t err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                    err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                }
                else
    #endif

    If it just need to be called again, then why doesnt it work when vPortSuppressTicksAndSleep() is called again almost immidiately by the idle task?

    I dont know. Whatever condition that makes sd_app_evt_wait(); return immidiately seems to be triggered again by the the exit and reentereance into vPortSuppressTicksAndSleep().

    In summary, the complete checklist that made it work for me was (I dont use SAADC so it wasnt an issue for me):

    • Install an FPU interrupt handler that clears the FPU errors
    • Call sd_app_ewt_wait() twice in vPortSuppressTicksAndSleep()
Reply
  • In addition to the FPU and SAADC interrupt-issues Elias Löwe mentions further down, I ran into another issue:

    sd_app_evt_wait();
    returns immidiately the first time it is called (it is also reported here) and power consumption is many milliamps. You probably used WFE in SDK15 instead because you ran into this bug/issue that seems to be intermiettent..

    It works for me if I duplicate a second call

    #ifdef SOFTDEVICE_PRESENT
                if (nrf_sdh_is_enabled())
                {
                    uint32_t err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                    err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                }
                else
    #endif

    If it just need to be called again, then why doesnt it work when vPortSuppressTicksAndSleep() is called again almost immidiately by the idle task?

    I dont know. Whatever condition that makes sd_app_evt_wait(); return immidiately seems to be triggered again by the the exit and reentereance into vPortSuppressTicksAndSleep().

    In summary, the complete checklist that made it work for me was (I dont use SAADC so it wasnt an issue for me):

    • Install an FPU interrupt handler that clears the FPU errors
    • Call sd_app_ewt_wait() twice in vPortSuppressTicksAndSleep()
Children
No Data
Related