In this blog, I would like to share how to optimize the current consumption with FreeRTOS on Nordic nRF5 SDK. I would use the SDK 15.2 (the version of FreeRTOS is bundle with 10.0.0). All the current consumption would be measured at nRF52832 DK Board with Power Profile Kit (PPK).
Here are the topic which covers.
- Native example projects with FreeRTOS
- Optimized the current consumption on the BLE Central and Peripheral with FreeRTOS example (coming soon)

NRF52832 supports on the internal LDO and DCDC mode.


The schematic difference between LDO and DCD is on the DEC4 with 2 additional inductors and 1 capacitor.


On NRF52832 Product Specification,

On NRF52840 Product Specification,

Power Profile Kit (Measurement tool)
The Power Profiler Kit is an easy to use tool for power measurement and optimization of embedded solutions.
The Power Profiler Kit mounts directly on to the nRF51 DK and nRF52 DK through the Arduino Uno Revision 3 standard pin headers, in combination with the special power measurement header on these kits. This allows easy power profiling with a minimum of hardware work needed. There’s also an additional connector for power measurements on external boards, so you can connect and power profile your final hardware as well. It supports VCC levels between 1.8 V and 3.3 V and has an on-board regulator that will supply up to 70 mA of current to external applications.
https://www.nordicsemi.com/Software-and-Tools/Development-Kits/Power-Profiler-Kit

Native FreeRTOS examples inside the Nordic NRF5 SDK
There are two examples to run with FreeRTOS.
- nRF5_SDK_15.2.0_9412b96\examples\peripheral\blinky_freertos (https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.2.0/nrf_freertos_example.html)
- nRF5_SDK_15.2.0_9412b96\examples\ble_peripheral\ble_app_hrs_freertos (https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.2.0/ble_sdk_app_hrs_freertos.html)
Example of the ble_app_hrs_freertos
Advertising Interval = 1000ms,

VDD=3V, DCDC mode

Disable the LOG module

Disable all the button and LEDs

Enable the sd_app_evt_wait() inside the port_cmsis_systick.c

Disable all the timer to run (because we only measure the BLE activity first).

Measurement result on the NRF52832 DK

By comparing on the Nordic Power Online calculator ( https://devzone.nordicsemi.com/nordic/power), it is very similar to the example without FreeRTOS.

The source code of this example can be found at https://github.com/jimmywong2003/nRF5-freeRTOS-current-optimization/tree/master/ble_app_hrs_freertos .
Example of the BLE Central x 2 NUS Client with FreeRTOS
By setting the scanning interval = 1000ms, scanning windows = 50ms, the current consumption profile is showed as below.

- NRF52832 DK Board with DCDC Enabled,
- UART is disabled (because Legacy UART uses around 4xx uA with HCLK together).
- LOG module is disabled (NRF_LOG_BACKEND_RTT_ENABLED = 0, NRF_LOG_ENABLED = 0)


Source Code can be found at https://github.com/jimmywong2003/nRF5-freeRTOS-BLE-Central-or-Peripheral-Example/tree/master/ble_app_multiple_nus_c_freeRTOS
More discussion on the FreeRTOS particular on the difference configurations.
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 0
Get power measurements for the below three scenarios Scenario 1
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 0
Now you have will no power saving as the system is not going to power save mode at all.
Scenario 2
#define configUSE_TICKLESS_IDLE 1
#define configUSE_IDLE_HOOK 0
Now when the idle task is executed then it will suppress tick interrupts and sleep. That means no ticks will happen from the sleep until next expected tasks wakeup time or RTC overflow time. This will save considerable power.
Scenario 3
#define configUSE_TICKLESS_IDLE 0
#define configUSE_IDLE_HOOK 1
Now you are telling the idle task to run your hook in vApplicationIdleHook(). It does not care what you do in there. In your case it is WFI(); You will see power consumption less than scenario 1 but more than scenario 2. This is because your application is going to sleep by WFI which is better than scenario 1 where there was no sleep, but your application is waking up for every tick to update rtos time which is not the case in scenario 2.
Your scenario
This should not be used because your sleeping in your idle hook, two different types of sleeps.
#define configUSE_TICKLESS_IDLE 1
#define configUSE_IDLE_HOOK 1
The idle function first runs your application hook which is WFI() and when it wakes up it supresses tick and sleep. It will repeat this in a cycle whenever the idle task is run. So in your case one wakeup from chip is from WFI (slept from idlehook) and the second wakeup will be from tickless idle sleep. So you are telling the idle task to sleep twice (different types of sleeps )in a loop when ever it gets a chance to run which gives you very unpredictable behavior.
Welcome to provide any comment and feedback. If you think this blog is useful, please give a “Like” as appreciation.
It is in point of fact a nice and useful piece of info. I’m satisfied that you
just shared this useful info with us. Please keep us up to date like
this. Thank you for sharing.
LikeLike
I couldn’t rеfrain from commenting. Very wеll wrіtten!
LikeLike