Overview
In this lesson, we will take a closer look at power management in an nRF5x SoC. We will go over all the details for the two power saving modes available on an nRF5x SoC: System On and System Off and the two sub power saving modes accessible in the System On. The API’s needed to configure them with and without SoftDevice are examined thoroughly with hands-on exercises. Finally, we will touch on the how to measure the current drained by an nRF5x SoC.
Power Management Unit (PMU)
Inside an nRF5x SoC there is a dedicated complex hardware to manage the power consumed by the CPU, and each&every system block and peripheral including the RAM memory. The name of this module is the Power Management Unit (PMU), which manages both the clocking and power on per unit level.

By default, the PMU automatically detects which power and clock resources are required by the different components in the system at any given time. It will then start/stop and choose operation modes in supply regulators and clock sources, without user interaction, to achieve the lowest power consumption possible. In addition to that, it facilitates two explicit sleep modes ( System On and System Off ) that we can put the SoC into, which is the focus of this lesson.
Further more, the PMU can allow us to configure RAM retention during System Off or System On. Through this feature, we can set which RAM blocks to be retained (kept On) during System On/System Off sleep modes. The advantages of not retaining RAM content is that the overall current consumption is reduced. This is useful in some applications.
Power saving modes available in an nRF5x SoC
There are two sleep modes available in the nRF5x family :
Sleep Mode | Expected SoC current | Return point from sleep |
System On | Few micro amps. | The interrupt handler caused the wake up, then execution is returned right after the sleep call.
Note: To keep the SoC in sleep while its not needed, the call to sleep must be put in the lowest priority execution mode which is |
System Off | Few hundreds nano amps.
|
System Reset. |
- System On : The most commonly used sleep mode. The expected SoC current is few micro amps. It has two types :
- Constant latency: constant latency on the expense of higher current. This is done by keeping all internal voltage regulators and oscillators running.
- Low power (default) : lower current on the expense of latency. The internal regulators and oscillators will be switched on/off automatically by the PMU based on the peripherals/system blocks demand.
- System Off : This mode puts the SoC in a deep sleep mode. CPU is down, all clocks and most peripherals are fully disabled. The CPU can NOT wake up on interrupts. There are only a few limited wake up sources from System Off: GPIO, NFC and pin reset. The device always resets when waking up from system Off with the possibility of selected RAM blocks retention. The expected SoC current is few hundreds nano amps (sub micro current) .
Consult with your SoC Product Specification document(PS) – Chapter Power and clock management about the exact expected SoC current on different sleep modes. These currents are labeled as ION(System On sleep mode current) and IOFF (System Off sleep mode current). They are usually given on different operation conditions and RAM retention configurations as shown in the examples below:


System On mode
System On is the most used power saving mode. Entering the System On will put the CPU to sleep (idle) and the PMU will automatically shut down any peripheral not used. The power requirement of a peripheral is directly related to its activity level, and the activity level of a peripheral is usually raised and lowered when specific tasks are triggered or events are generated( See Lesson 6 to refresh your memory on tasks and events ).
However, when a SoftDevice is used, the low frequency clock(LFCLK) and at least RTC0 will always remain active and is usually used for SoftDevice time keeping, so that the nRF5x can wake up on a BLE event or any other registered events. It can also wake up on interrupts from any peripheral. To enter system On low power mode, a call to WFE
or WFI
assembly instruction is needed. This is typically achieved by calling nrf_pwr_mgmt_run()
which calls sd_app_evt_wait()
if a SoftDevice is used, or __WFE()
macro, if no SoftDevice is used. Note that sd_app_evt_wait()
itself uses WFE
assembly instruction internally.
Action | Without SoftDevice | With SoftDevice |
Enter System On sleep mode | nrf_pwr_mgmt_run() or __ WFE() or __WFI() . |
nrf_pwr_mgmt_run() or sd_app_evt_wait() . |
Exit System On sleep mode | On an interrupt or a peripheral event that is configured to trigger an interrupt. | On an interrupt or a peripheral event that is configured to trigger an interrupt. |
For optimal power saving, the System On mode should be the default state of your firmware and that is why almost all nRF5 SDK examples enters System On low power mode in the main()
function inside an infinite loop. In this way, the CPU is awake only when it is needed.
An example is shown below where the System On sleep mode is the default state of the firmware. This is achieved by placing the call to sleep nrf_pwr_mgmt_run()
in main()
inside an infinite loop:

<nRF5 SDK Installation Path>\examples\ble_peripheral\ble_app_blinky
– Example where the System On sleep mode is the default firmware stateIn your product code, a similar fashion of calling the sleep function must be followed to achieve optimal power saving.
We have mentioned that there are two sub modes in the System On saving mode:
- Constant latency.
- Low power(Default).
Depending on the application, we can configure the System On sleep mode to be either having constant latency characteristic, which makes the enter sleep/wake up from sleep time deterministic, or having the maximum power saving characteristic.
The default one is actually the Low power(maximum power saving characteristic), to switch between these two sub modes, we can use the APIs below:
Action | Without SoftDevice | With SoftDevice |
Set System On – Low power sub mode | NRF_POWER->TASKS_LOWPWR=1 (Direct memory write) |
sd_power_mode_set(NRF_POWER_MODE_LOWPWR) |
Set System On – Constant latency sub mode | NRF_POWER->TASKS_CONSTLAT=1 (Direct memory write) |
sd_power_mode_set(NRF_POWER_MODE_CONSTLAT) |
Side Note : __WFE()
and __WFI()
are two macros defined in cmsis_gcc.h
which invoke the WFE
and WFI
ARM assembly instructions respectively. In previous SDK versions, these two macros were implemented as inline C functions. This is the why they are called inline functions and macros interchangeably.

__WFE()
, __WFI()
macros implementationsWFE
and WFI
are ARM assembly instructions for entering power saving modes.
WFI
– wait for interrupt. The processor will enter sleep mode, and wake on the next interrupt.
WFE
– wait for event. The processor will enter sleep mode, and wake on the next interrupt OR event flag in the CPU event register. Event here is not related to the event/tasks registers in the peripherals/system blocks. It is a special register in the ARM Core. An event can be generated in a number of ways, for example by executing SEV
instruction.
System Off mode
System Off is the deepest power saving mode the system can enter. In this mode, the system’s core functionality is powered down and all ongoing tasks are terminated. The device can be put into System Off mode using the POWER register interface of the PMU.
When in System Off mode, the device can be woken up through one of the following signals:
- The DETECT signal, optionally generated by the GPIO peripheral.
- The ANADETECT signal, optionally generated by the LPCOMP module.
- The SENSE signal, optionally generated by the NFC module to “wake-on-field” (If applicable in the SoC).
- A reset.
When the system wakes up from System Off mode, it gets reset. This is a huge difference in comparison to the System On sleep mode, and its also the reason why this mode is as not frequently used as the System On sleep mode. System Off sleep mode has fewer application usages when compared with the System On sleep mode.
Action | Without SoftDevice | With SoftDevice |
Enter System Off sleep mode | NRF_POWER->SYSTEMOFF=1 (Direct memory write) or
|
nrf_pwr_mgmt_shutdown() or sd_power_system_off() |
Exit System Off sleep mode | 1. The DETECT signal, optionally generated by the GPIO peripheral
2. The ANADETECT signal, optionally generated by the LPCOMP module 3. The SENSE signal, optionally generated by the NFC module to “wake-on-field” 4. A reset
|
1. The DETECT signal, optionally generated by the GPIO peripheral
2. The ANADETECT signal, optionally generated by the LPCOMP module 3. The SENSE signal, optionally generated by the NFC module to “wake-on-field” 4. A reset |
Power Management Library
Even though there are several methods to interact with the power management unit(PMU), the power management library is the most recommended one to use. It provides a simplified API to enter the System On, System OFF sleeps modes. It also includes extra features. For instance, It can allow us to configure an automatic sleep after a configurable time of inactivity(NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED). In addition to that, we can configure it to set a GPIO(and hence an LED) on/off when the CPU is running, so that we can keep track of when the CPU is active or asleep(NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED). The library also takes into account the SoftDeivce when its included and provides a safe API to enter the sleep modes.
The nrf_pwr_mgmt_run()
function offered by the power management library is the recommend method to enter the System On sleep mode and manage the extra features (if enabled) whether SoftDevice is used or not. It does a number of housekeeping to make sure that entering and exiting sleep is safe and error-free. We can see from the screenshot below that it use the __WFE()
macro which calls the WFE
ARM instruction, in addition to preparations before entering and after exiting sleep.

nrf_pwr_mgmt_run()
function of the Power Management Library to safely enter System On sleep mode and manage extra featuresThe API’s of the Power Management Library are available in the nrf_pwr_mgmt.h
header file. Summary of the APIs is provided below:
API | Usage | Parameters |
nrf_pwr_mgmt_init() | Initialize the power management library. | None |
nrf_pwr_mgmt_run() | Enter System On sleep mode and manage extra features if any are enabled. | None |
nrf_pwr_mgmt_shutdown() | Enter System Off sleep mode. | nrf_pwr_mgmt_shutdown_t enumeration |
nrf_pwr_mgmt_feed() | Only applicable when the feature.
NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED is enabled . It is called to reset the counter and hence prevent the automatic sleep. This is covered in-depth in exercise 3 of this lesson. |
None |
NRF_PWR_MGMT_HANDLER_REGISTER() | Macro for registering a shutdown handler to be called before entering System Off sleep mode. Useful for doing application-level housekeeping before entering System Off sleep mode. We will utilize this macro in the intermediate level of this course once we talk about Device Firmware Upgrade (DFU). | Event handler and a priority number |
The power management library has the following extra features, that can be enabled/disabled in the SDK configuration header file sdk_config.h
:

The table below summarizes these feature:
Feature |
Description |
NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED |
Set a GPIO(and hence an LED) on/off when the CPU is running, so that we can keep track of when the CPU is active or asleep. This feature is covered in exercise 2 of this lesson . |
NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED |
Allow us to configure an automatic sleep after a configurable time of inactivity.This is a very useful feature to automatically power down the device if not used for some time.
Note: Requires the RTC to be configured. This feature is covered in exercise 3 of this lesson. |
NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED |
This feature is used with the Logger Module to trace and log CPU usage (0% – 100%).
This feature is useful in the development and profiling phases of your product design cycle. CPU usage is computed and logged (through RTT , UART , or a file ) every second. |
NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED |
To handle sleep/exiting sleep when the Floating Point Unit of the SoC is used ( If applicable and enabled in the build configuration) |
NRF_PWR_MGMT_CONFIG_USE_SCHEDULER |
Applicable If the firmware is configured to use the Scheduler software module. |
By this we have covered the PMU, the available sleeping modes, and the Power Management Library which is the recommended software interface to interact with the PMU.
Next, we will do some hands-on exercises. First exercise is on how to setup the Power Management Library and use it to safely enter&exit System On sleep mode. Second exercise is on the use of the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
feature of the library. Third exercise is on the NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED
feature of the library.
Lesson 14 – Exercises
Exercise 1: Setting up the Power Management Library
In this exercise, we will learn how to setup the power management library, and practice entering&exiting the System On sleep mode.
The code from Lesson10 – Exercise2 is used as the code base. In Lesson10 – Exercise2, we setup an interrupt-based system to control LED1 through push button 1 and push button 2. Pressing button1 calls button1_handler()
and turns LED1 ON. Pressing button 2 calls button2_handler()
and turns LED1 OFF. The nRF52840-DK is used as the hardware platform. We used the __SEV()
followed by two __WFE()
macros to enter the System On sleep mode.
The reason why we used this trio, instead of just calling one __WFE()
is because if the event flag is set when __WFE()
is called, the function will clear the event flag and return immediately, therefore it will not enter sleep mode. On the other hand, calling __SEV()
(Set Event flag) sets the event flag, so __SEV()
followed by __WFE()
will clear the event flag without going to sleep. Then we are sure that in the next __WFE()
the CPU will go to sleep(System On sleep mode).

__WFE()
macroIn this exercise, we will get rid of the macros (__SEV()
and the __WFE()
) and utilize the more capable power management library to put the SoC to sleep (System On mode). The library gives us more options and its safer to use than the macros, especially when a SoftDevice is used and/or when the FPU is used.
The new code will behave exactly the same as before, except this time it uses the power management library. We will build on the new code in the next exercises and enable extra features of the library.
Exercise Steps :
1. Download from Enroll course to see link . Extract the file somewhere on your disk. It is exactly the same code as Lesson 10 – Exercise 2, except the comments and the project name have been changed.
2. Open the project and build it (Project -> Build or press F7) just to make sure that everything is OK. In case of an error, double check that the nRF5SDK global macro is pointing to the right location where the nRF5 SDK is downloaded on your local disk. This can be done by checking the Tools Menu -> Options -> Building -> Global Macros (nRF5SDK) and compare it to the root directory where the nRF5 SDK is downloaded. (You will get all sort of files not found errors if the macro is not matching to where the nRF5 SDK is downloaded on your local machine!).

3. Enable the NRF_PWR_MGMT_ENABLED
in sdk_config.h
by setting it to 1. This macro is the conditional compilation switch to include/exclude the source code of the library with your own project code.
This can be done manually using the code editor as shown in the screenshot below :
Double click on the sdk_config.h
file in the Project Explorer, press Ctrl+F to invoke the search window.

NRF_PWR_MGMT_ENABLED
in sdk_config.h
Or using the CMSIS Configuration wizard, as shown in the screenshots below:
The two methods above are identical. Pick one method that you are most comfortable with.
4. Add implementation files of the power management library and its dependencies. In this step we will add the implementation files of the power management library and all internal software modules used by it(dependencies).
4.1 Create folder nRF_Libraries in the Project Explorer as shown below.
4.2 Right click on the nRF_Libraries, select Add Existing File.., browse to the nRF5 SDK Installation Path and add the following files:
(nRF5 SDK Installation Path)/components/libraries/experimental_section_vars/nrf_section_iter.c
(nRF5 SDK Installation Path)/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c



The first file is the section variables iterator library implementation file. The section variables iterator is used by the power management library, hence its a dependency that must be included in the source code. (Read more about the section variables in the nRF5 SDK here).
The second file is the actual implementation file of the power management library itself.
5. Add paths to the User Include Directories Search Paths to point to the power management library header files and other modules used by the library:
$(nRF5SDK)/components/libraries/pwr_mgmt
$(nRF5SDK)/components/libraries/mutex
$(nRF5SDK)/components/libraries/atomic
Copy from here.
Right click on the Project tab, and select Options…

Select Common, and Predecessor, then double click on User Include Directories. Add the three needed paths, click OK twice, as shown in the screenshots below:
6. Update the Section Placement file flash_placement.xml
. Parts of the power management library code is expected to be placed in a section called pwr_mgmt_data
in the flash. This section must be defined in the Section Placement file flash_placement.xml
as shown in the screenshots below :

Add the following line after the .text
section entry as shown in the screenshot below:
<ProgramSection alignment="4" keep="Yes" load="Yes" name=".pwr_mgmt_data" inputsections="*(SORT(.pwr_mgmt_data*))" address_symbol="__start_pwr_mgmt_data" end_symbol="__stop_pwr_mgmt_data" />
Copy from here. The syntax of the line is explained here and the need for such line is discussed in here.

pwr_mgmt_data
Program SectionMake sure to save the file, and switch perspective to main.c
.
7. Include the header file nrf_pwr_mgmt.h
in your source code.
#include "nrf_pwr_mgmt.h"

8. Call nrf_pwr_mgmt_init() in main()
to initialize the power management library.

nrf_pwr_mgmt_init()
to initialize the power management libraryRecommendation: The return status of the nrf_pwr_mgmt_init() function should be checked using the Common application error handler (app_error) library (The APP_ERROR_CHECK()
macro) before proceeding with the code . The Common application error handler (app_error) was covered thoroughly as part of Lesson11 .
9. Replace the macro calls with the nrf_pwr_mgmt_run() as shown below:
10. Compile the project and download to your development board.
The program should behave exactly as in Lesson 10 – Exercise 2. Since we placed the call to sleep nrf_pwr_mgmt_run()
in the main()
inside an infinite loop(line 97), the system will remain in the System On sleep mode all the time, except when an interrupt is triggered.
When an interrupt is triggered, the CPU is woken up and it executes the interrupt handler, then it resumes to the instruction right after the sleep call, since this is an infinite loop, the call to sleep is called again and the system enters System On sleep mode again.
Download solution file from here Enroll course to see link.
Exercise 2: Using the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED feature
In this exercise, we will utilize the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
feature of the power management library to turn an LED ON when the CPU is active and turn it OFF when the CPU is asleep, as a way to visualize the sleep/wake up state of the CPU. The library will handle this automatically once we enable the feature and provide it with the pin number of the LED.
Exercise Steps :
1. We will use the previous exercise code as the code base. Download from Enroll course to see link. It is exactly the same code as the previous exercise solution file, except the comments and the project name have been changed.
2. Open the project and build it (Project -> Build or press F7) just to make sure that everything is OK. In case of an error, double check that the nRF5SDK global macro is pointing to the right location where the nRF5 SDK is downloaded on your local disk. This can be done by checking the Tools Menu -> Options -> Building -> Global Macros (nRF5SDK) and compare it to the root directory where the nRF5 SDK is downloaded . ( You will get all sort of files not found errors if the macro is not matching to where the nRF5 SDK is downloaded on your local machine!).

3. Enable the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
feature of the power management library by setting it to 1 in sdk_config.h
. (You can use the editor or the CMSIS Configuration wizard)

NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
in in sdk_config.h
(Click on the image to enlarge)4. Select the GPIO PIN to be asserted when the CPU goes to sleep NRF_PWR_MGMT_SLEEP_DEBUG_PIN
. This is also done inside the sdk_config.h
file. The value is between 0-47. (You can use the editor or the CMSIS Configuration wizard). We need to check the schematic of the development board to know which PINs are connected to LEDs. For the nRF52840 – DK , we will select pin 16 (P0.16) , which is connected to LED4 on the board.

NRF_PWR_MGMT_SLEEP_DEBUG_PIN.
(Click on the image to enlarge)
NOTE : Since the LEDs on the nRF52840 – DK are active low, the LED will be turned ON when the CPU is active and OFF when the CPU is asleep. This is the sync with the description of the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
which is asserted when the CPU is asleep and de-asserted when the CPU is awake.

5. The code for the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
feature uses the app_util_platform
Utility Functions and Definitions (Platform) library. Therefore, the app_util_platform
is a dependency that must be added in the project.
Right click on the nRF_Libraries, select Add Existing File.., browse to the nRF5 SDK Installation Path and add the following file:
6. Compile and download the code, You can notice that the LED4 is very briefly active when you press button 1 or button 2. This is the only time where the CPU is awake and its reflected in LED4.
This is all you need to configure the NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED
feature, however, our interrupt handlers of the code we have are very small and hence they will execute in a very short period of time, hence, we barely can notice the LEDs. We can add some delay in the handlers so that we can observe the LEDs better. It is ALWAYS a bad idea to add explicit delay in an interrupt handler. We are doing this here just for illustration purposes.
7. Add some delay so that we can visually observe the CPU activity LED better. Do NOT preform this step in your product code.
8. Re-compile and re-download the firmware on the board. You should observe LED4 better now when you press button 1 or button 2. LED4 will be ON only when the CPU is running. I.e. it serves now as an activity LED for the CPU.
Download solution file from here Enroll course to see link.
Exercise 3: Using the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED feature
In this exercise, we will utilize the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
feature of the power management library to automatically put the system into deep sleep (System Off sleep mode) if no user activity was detected within NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
seconds intervals.
It is up to us to decide what to be considered as user activity. This is done by placing the functionnrf_pwr_mgmt_feed()
in the code of interest. In our exercise, we will consider pressing button 1 or button 2 as a user activity, therefore, we will explicitly place calls to nrf_pwr_mgmt_feed()
inside button1 and button2 interrupts handlers. In BLE-enabeled applications, we could place the calls to nrf_pwr_mgmt_feed()
in the receiving/sending stack events handlers as we will see in the intermediate level of this course.
The NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
feature of the power management library, relies on the RTC1 hardware present on the nRF5x SoC to keep the timing. When the feature is set, the RTC1 is configured to act as if its a watchdog, if its not cleared within NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
seconds, the SoC is put into deep sleep mode ( System Off ) . A call to the nrf_pwr_mgmt_feed()
clears the RTC1 countdown.
The Timer library is used internally by the power management library when the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
feature is set. The Timer library allows the power management library to configure and use the RTC1 to act as if its a watchdog.

Therefore, we must enable the Timer Library and add all its dependencies before using the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
feature. In addition to that, the RTC hardware requires the low power LFCLK clock source to operate as we mentioned in previous lessons. Therefore, we need to configure the CLOCK driver and request the LFCLK explicitly.
This exercise will include all the steps needed to setup and use the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
feature of the power management library, including configuring both the Timer Library (Step 5) and the CLOCK driver (Step 6).
Exercise Steps:
1. Download from here Enroll course to see link compressed project file. Extract the file somewhere on your disk. It is similier to the previous exercise code base , except the comments and the project name have been changed.
2. Open the project and build it (Project -> Build or press F7) just to make sure that everything is OK. In case of an error, double check that the nRF5SDK global macro is pointing to the right location where the nRF5 SDK is downloaded on your local disk. This can be done by checking Tools Menu -> Options -> Building -> Global Macros (nRF5SDK) and compare it to the root directory where the nRF5 SDK is downloaded . (You will get all sort of files not found errors if the macro is not matching to where the nRF5 SDK is downloaded on your local machine!).

3. Enable the NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
in sdk_config.h
by setting it to 1.
This can be done manually using the code editor as shown in the screenshot below:
Double click on the sdk_config.h
file in the Project Explorer, press Ctrl+F to invoke the search window.

NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
in sdk_config.h
Make sure to save the file after setting the macro to 1.
Or it can be done using the CMSIS Configuration Wizard as shown below (both methods are identical):
4. In a similar fashion to the previous step, set the time of inactivity NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
after which the shutdown procedure(Enter System Off sleep mode) will be triggered to 10 seconds.
This again, can be done using the editor:

NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
to 10 secondsOr using the CMSIS Configuration Wizard:
In your product code you would set the value of NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
based on your product use cases. You can set it to a value between 1 -2097151 seconds (about 24days). 2097151 seconds is the overflow time of the RTC1 hardware on max prescale.
5. Enable the Timer Library and add implementation files, headers and all its dependencies.
5.1 Enable the Timer Library by setting the APP_TIMER_ENABLED
macro in sdk_config.h
to 1. (Using the editor or using the CMSIS Configuration Wizard)

APP_TIMER_ENABLED
in sdk_config.h
Or using the CMSIS Configuration Wizard:
5.2 Add paths to the User Include Directories Search Paths to point to the Timer library header files and other modules used by the library:
$(nRF5SDK)/components/libraries/timer
$(nRF5SDK)/components/libraries/sortlist
$(nRF5SDK)/components/libraries/atomic_fifo
Copy from here .
Right click on Project entity , and select Options.
Select Common, and Predecessor, then double click on User Include Directories. Add the the needed path, then click OK twice.
5.3 Add the implementation files of the Timer Library and its dependencies.
Right click on the nRF_Libraries, select Add Existing File.., browse to the nRF5 SDK Installation Path and add the following files as shown in the screenshots below:
$(nRF5 SDK Installation Path)/components/libraries/atomic/nrf_atomic.c
$(nRF5 SDK Installation Path)/components/libraries/timer/app_timer2.c
(Select Version 2 which includes new enhancements)
$(nRF5 SDK Installation Path)/components/libraries/timer/drv_rtc.c
$(nRF5 SDK Installation Path)/components/libraries/atomic_fifo/nrf_atfifo.c
$(nRF5 SDK Installation Path)/components/libraries/sortlist/nrf_sortlist.c
5.4 Enable the Version 2 of the timer library app_ timer
by adding the following two macros as shown in the screenshot below
APP_TIMER_V2
APP_TIMER_V2_RTC1_ENABLED
Copy from here.
6. Enable the Clock driver and add implementation files, headers and all its dependencies. This step is not needed if a SoftDevice is used, which is usually the case as we will see in the intermediate level of this course.
As we mentioned earlier the Clock driver is needed to request the LFCLK clock source (turn it On), which is needed by the RTC1 hardware. If a SoftDevice is present on the system, this step is not needed as the LFCLK is already turned On by the SoftDevice.
6.1 Enable the Clock driver by setting the NRF_CLOCK_ENABLED
macros in sdk_config.h
to 1. ( Using the editor or using the CMSIS Configuration Wizard)
Double click on the sdk_config.h
file in the Project Explorer, press Ctrl+F to invoke the search window.
Side Note1: The NRF_CLOCK_ENABLED
is for a legacy API(Layer 3) that works across all nRF5 SDK versions, which internally translate to the latest NRFX API (NRFX_CLOCK_ENABLED
) for SDK v15.0.0 and above. The NRF API is recommended here as it provides backward comparability with previous SDK versions, in addition to that, it is the API used in almost all nRF5 SDK examples.
6.2 Add the implementation files of the Clock driver and its dependencies.
Right click on the nRF_Drivers, select Add Existing File.., browse to the nRF5 SDK Installation Path and add the following files as shown in the screenshots below:
$(nRF5 SDK Installation Path)/integration/nrfx/legacy/nrf_drv_clock.c
$(nRF5 SDK Installation Path)/modules/nrfx/drivers/src/nrfx_clock.c
Side Note2: The first driver file nrf_drv_clock.c
is called the legacy layer file(Layer 3). Its purpose is to translate the former API and configuration settings (nRF5 SDK v14.2.0 and below ) to the new driver API called NRFX introduced with nRF5 SDK V15.0.0 as an attempt to isolate the SoC peripherals’ drivers from the other components of the nRF5 SDK and make them standalone(This is covered thoroughly in Lesson6). The second file nrfx_clock.c
is the actual driver with the latest API”NRFX”. Now, you might ask the question of why don’t we just use the new API “NRFX” directly without the use of the legacy layer. The answer to your question is: Yes . we can do that, but it’s not yet recommended for lack of sufficient documentation, no backward comparability, and in some scenarios the “legacy layer” is serving more of an abstraction layer than just a translation layer. Again, Lesson6 has all the detials about this topic.
7. Include the Timer Library and the Clock driver header files in main.c
.
#include "nrf_drv_clock.h"
#include "app_timer.h"
8. Initialize the clock driver and explicitly request the LFCLK clock source in main()
function as shown below:
nrf_drv_clock_init();
nrf_drv_clock_lfclk_request(NULL);
Recommendation: The status of these functions should be checked using the Common application error handler (app_error) library (The APP_ERROR_CHECK()
macro) before proceeding with the code . The Common application error handler (app_error) was covered thoroughly as part of Lesson11 .
9. Initialize the Timer library.
app_timer_init();
10. We are almost done, what left is to specify which functionality to be considered as “user activity” to reset the countdown of the System Off sleep mode. As we mentioned earlier, this is done by calling nrf_pwr_mgmt_feed()
at the code of interest. We will put two calls to nrf_pwr_mgmt_feed()
, one in button 1 interrupt handler and the other in button 2 interrupt handler.
11. Compile the project and download to your development board. The functionality of this code is similar to Exercise 1, The difference is that if button 1 or button 2 is not pressed within 10 seconds intervals ( which is NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
), the system will enter System Off deep sleep mode(You will notice this by observing that the system will no longer response to pressing button 1 or button 2). The only way to exit System Off sleep mode is to power cycle the board or to reset it.
Download solution file from here Enroll course to see link.
How to measure the SoC current
In order to fully verify the SoC power consumption, we need to measure the current drained by the SoC. To measure the current, some hardware preparations to your board are needed. These preparations are elaborated in the development kit User Guide in a dedicated chapter called Measuring Current.

The preparations differ from method to method. There are four methods to measure the current with different setup complexity, accuracy, and cost :
- Power analyzer. High accuracy, but it is highly unlikely that your hardware team have a Power analyzer and therefore you would need to purchase one(expensive).
- Oscilloscope. Good accuracy. It is very likely that your hardware team already have one.
- Power Profiler Kit II or Power Profiler Kit (Provided By Nordic Semiconductor). Compact and cost-effective. Suitable for early phases of your product design cycle.
- Ampere-meter. Not recommended.
The oscilloscope method is the recommended one as it balance cost and accuracy.

Important Notes :
- Do not power your development board from a USB when measuring current, otherwise readings are invalid.
- Do not measure current with your board in debug mode, otherwise reading are invalid.
Enroll to the to the Nordic nRF5x BLE In-Depth Training Course (Foundation Level) to access full materials.