The objective of this blog is to guide the user in the optimization of power on the nRF5340 SoC. The goal is to understand what is needed from a software, hardware, and system level design to minimize the power in your device. This blog is targeted at the nRF5340 SoC, but this information is viable for any nRF52 Series devices except for where we address the use of the dual core in the nRF5340 SoC. A test project was created using the Nordic UART Service (NUS) on the nRF5340 DK and a current measurement of 8uA was achieved during advertising. These results should be the target of your design when completed.
Power optimization is an important element of IoT designs, especially if they are battery powered. The use of nRF Connect SDK with Zephyr RTOS is a powerful tool in the implementation of power management. The interfaces and APIs provided by the power management subsystem in the Zephyr RTOS are designed to be architecture and SoC independent. This enables power management implementations to be easily adapted to different SoCs and architectures. The following sections will describe this subsystem and how you can take advantage of the power saving features when targeting the nRF5340 SoC.
Note this was done in nRF Connect SDK V1.6.0. Please review the changes of Power states depreciated from nRF Connect SDK 1.5.1
The power and clock management system in nRF5340 SoC is optimized for ultra-low power applications to ensure maximum power efficiency. The core of the power and clock management system is the power management unit (PMU). The PMU automatically tracks the power and clock resources required by the different components in the system at any given time. To achieve the lowest power consumption possible, the PMU optimizes the system by evaluating power and clock requests, automatically starting and stopping clock sources, and choosing regulator operation modes. There are some configuration options that enable you to implement extra power management policies.
In asymmetric multiprocessor systems, the most common way for different cores to cooperate is to use a shared memory-based communication. This is done in the nRF5340 SoC using HCI_RPMSG transport, which is part of the Zephyr OpenAMP library. Since the nRF5340 SoC is a dual core device, to minimize power you will need to disable the serial logging in both the application processor and HCI_RPMSG transport. In the build for the nRF5340 SoC, the HCI_RPMSG protocol will automatically be built as a child image in your multi-image build. To disable the serial logging, you will need to modify your prj.conf and hci_rpmsg.conf files.
For the prj.conf file make the changes seen below.
For the hci_rpmsg.conf, create a folder in your project named child_image. Your folder structure should look like this:
Copy the prj.conf file from the following folder into the child_image folder and rename it hci_rpmsg.conf.C:\..\ncs\v1.6.0\zephyr\samples\bluetooth\hci_rpmsg
Then make the modifications to the file as shown below
There are two configurations needed for both system and device power management.
CONFIG_PM: This option enables the board to implement extra power management
policies whenever the kernel becomes idle. The kernel informs the
power management subsystem of the number of ticks until the next kernel
timer is due to expire.
CONFIG_PM_DEVICE: This option enables the device power management interface. The
interface consists of hook functions implemented by device drivers
that get called by the power manager application when the system
is going to suspend state or resuming from suspend state. This allows
device drivers to do any necessary power management operations
like turning off device clocks and peripherals. The device drivers
may also save and restore states in these hook functions.
To enable these, make the changes to the prj.conf file as seen below.
Power Management Subsystem can put an idle system in one of the supported power states, based on the selected power management policy and the duration of the idle time allotted by the kernel. We can place the entire device into any of the 7 following power states:
Runtime active state.
The system is fully powered and active.
Runtime idle state.
Runtime idle is a system sleep state in which all of the cores enter deepest possible idle state and wait for interrupts, no requirements for the devices, leaving them at the states where they are.
Suspend to idle state.
The system goes through a normal platform suspend where it puts all of the cores in deepest possible idle state and may puts peripherals into low-power states. No operating state is lost (ie. the cpu core does not lose execution context), so the system can go back to where it left off easily enough.
In addition to putting peripherals into low-power states all non-boot CPUs are powered off. It should allow more energy to be saved relative to suspend to idle, but the resume latency will generally be greater than for that state. But it should be the same state with suspend to idle state on uniprocesser system.
Suspend to ram state.
This state offers significant energy savings by powering off as much of the system as possible, where memory should be placed into the self-refresh mode to retain its contents. The state of devices and CPUs is saved and held in memory, and it may require some boot- strapping code in ROM to resume the system from it.
Suspend to disk state.
This state offers significant energy savings by powering off as much of the system as possible, including the memory. The contents of memory are written to disk or other non-volatile storage, and on resume it’s read back into memory with the help of boot-strapping code, restores the system to the same point of execution where it went to suspend to disk.
Soft off state.
This state consumes a minimal amount of power and requires a large latency in order to return to runtime active state. The contents of system(CPU and memory) will not be preserved, so the system will be restarted as if from initial power-up and kernel boot.
By using the pm_power_state_force() call, This function overrides decision made by PM policy forcing usage of given power state immediately.
The lowest power state is PM_STATE_SOFT_OFF.
When using the pm_power_state_force() function you need to set a constraint on the pm system to not enter the PM_STATE_SOFT_OFF state until you are ready. By setting this constraint the disabled state cannot be selected by the Zephyr power management policies.
/*Prevent deep sleep (system off) from being entered*/
Then when you are ready to enable the PM_STATE_SOFT_OFF power state, for example, you can enable it using the pm_power_state_force()
When adding peripherals to your project you will create device tree bindings for those peripherals. Within your C code you will need to retrieve a device structure for a driver by name by getting its binding. Below is an example of a call to get that device binding.
First start by making a node identifier for the device you are interested in. Here are some examples of node identifiers
/*Option 1: by node label*/
#define MY_SERIAL DT_NODELABEL(serial0)
/*Option 2: by alias*/
#define MY_SERIAL DT_ALIAS(my_serial)
/*Option 3: by chosen node*/
#define MY_SERIAL DT_CHOSEN(zephyr_console)
/*Option 4: by path*/
#define MY_SERIAL DT_PATH(soc, serial_40002000)
Once you have the node identifier, there are two methods of retrieving a device binding.First method, you can use the device_get_binding();
const struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
const struct device *uart_dev=DEVICE_DT_GET(MY_SERIAL);
Either way works: (please note that DEVICE_DT_GET() was added in Zephyr 2.5)Once you have the binding you can set the device power state by using pm_device_state_set();
int pm_device_state_set(conststructdevice*dev, uint32_t device_power_state,pm_device_cbcb,void*arg)
there are 5 power states available in the pm_device_state_set() call
device is in ACTIVE power state
Normal operation of the device. All device context is retained.
device is in LOW power state
Device context is preserved by the HW and need not be restored by the driver.
device is in SUSPEND power state
Most device context is lost by the hardware. Device drivers must save and restore or reinitialize any context lost by the hardware
device is in force SUSPEND power state
Driver puts the device in suspended state after completing the ongoing transactions and will not process any queued work or will not take any new requests for processing. Most device context is lost by the hardware. Device drivers must save and restore or reinitialize any context lost by the hardware.
device is in OFF power state
Power has been fully removed from the device. The device context is lost when this state is entered, so the OS software will reinitialize the device when powering it back on
By following our example from above the code to set the UART to a low power state would look like the following:
note: we do not have a callback function or other arguments to pass, so they are NULL
Based on the device tree of the board you are using; certain peripherals are enabled by default. If you are not planning on using those peripherals in your project you can disable them in an overlay file.
For example;On the nRF5340 DK both UART0 and UART1 are enabled. If you do not plan on using UART1 in your design write an overlay file to disable UART1 as follows:Create a file named nrf5340dk_nrf5340.overlay and place it in your project directory. NOTE: (The name of the overlay file must match the name of the board you are using. So this must match the dts file it is associated with).The file would need to contain the followingnrf5340dk_nrf5340.overlay
More information on "Setting Device Tree Overlays" can be found in the Zephyr documentation.
Some configuration options will cause a higher internal voltage to be requested, which will be observed as an increase in power consumption.
In summary, after reading this blog you should be able to optimize the power in your nRF5340 design using nRF Connect SDK. We did this by using the following methods:
The Project is not in the repo. It is attached as a zip on this blog
Thanks! I didn't see that on first look...
WesC is this project in the repo? I've been trying to build one myself but struggling to get the lower power levels.
I recently added a project that was used for power verification. Below is a screen capture from the Power Profiler Kit 2 running the project on a nRF5340DK
sorry hit enter by mistake:\ncs\v1.6.0\zephyr\samples\boards\nrf\system_off\ncs\v1.6.0\zephyr\samples\subsys\pm\device_pm