Skip to content

Commit 3bff4c9

Browse files
erdemsimsekcarlescufi
authored andcommitted
samples: benchmarks: Add nRF7120 System ON idle power consumption sample
Add a standalone demo sample showing System ON idle power consumption on the nRF7120 DK. The sample sleeps for a configurable duration (10 s by default) on the SoC's default GRTC-backed system timer, wakes up, and prints a wake counter. Exposes a Kconfig choice of RAM retention levels backed by the ram_pwrdn library (64/128/256/512 KiB, full retention by default, or powering down whatever the image itself does not use), each named as its own sample.yaml build variant. Prints a reminder at boot to power-cycle the board before taking a reading, since the flashing/debugger connection itself draws extra current. README.rst documents measuring current with a PPK2 in source meter mode via the P601 connector. Signed-off-by: Erdem Simsek <erdem.simsek@nordicsemi.no>
1 parent 4607de4 commit 3bff4c9

8 files changed

Lines changed: 368 additions & 0 deletions

File tree

CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@
518518
/samples/app_jwt/ @nrfconnect/ncs-modem @ayla-nordicsemi
519519
/samples/basic/ @nrfconnect/ncs-co-build-system
520520
/samples/benchmarks/coremark/ @nrfconnect/ncs-blenders
521+
/samples/benchmarks/power_consumption/ @nrfconnect/ncs-malago
521522
/samples/bluetooth/nrf_auraconfig/ @nrfconnect/ncs-audio
522523
/samples/bluetooth/central_and_peripheral_hrs/ @nrfconnect/ncs-blenders
523524
/samples/bluetooth/central_bas/ @nrfconnect/ncs-blenders
@@ -647,6 +648,7 @@
647648
/samples/app_jwt/*.rst @nrfconnect/ncs-modem-doc @ayla-nordicsemi
648649
/samples/basic/empty/*.rst @nrfconnect/ncs-doc-leads
649650
/samples/benchmarks/coremark/*.rst @nrfconnect/ncs-blenders-doc
651+
/samples/benchmarks/power_consumption/*.rst @nrfconnect/ncs-blenders-doc
650652
/samples/bluetooth/central_and_peripheral_hrs/*.rst @nrfconnect/ncs-blenders-doc
651653
/samples/bluetooth/central_bas/*.rst @nrfconnect/ncs-blenders-doc
652654
/samples/bluetooth/nrf_auraconfig/*.rst @nrfconnect/ncs-audio-doc

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ Other samples
785785

786786
* Added:
787787

788+
* The :ref:`power_consumption_sample` sample for evaluating System ON Idle power consumption with configurable application RAM retention on the nRF7120 SoC.
788789
* The :ref:`vtf_monitoring_sample` sample that demonstrates how to capture voltage, temperature, and frequency data using the :ref:`vtf_monitoring` subsystem.
789790
* The :ref:`pulse_meas` sample that checks the pulse width of an externally provided signal.
790791
* The :ref:`rtfw_timer_gpio_sample` and :ref:`rtfw_hid_sample` samples demonstrating the RTFW control, fast-path, and event-delivery mechanisms.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#
2+
# Copyright (c) 2026 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
9+
project(power_consumption)
10+
11+
target_sources(app PRIVATE src/main.c)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# Copyright (c) 2026 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
mainmenu "nRF7120 System ON Idle power consumption benchmark"
8+
9+
config SAMPLE_POWER_CONSUMPTION_IDLE_SECONDS
10+
int "System ON idle duration in seconds"
11+
range 1 3600
12+
default 10
13+
help
14+
Duration of the sleep period (through k_sleep(), on this SoC's default
15+
GRTC-backed system timer) before waking up, printing the wake
16+
counter, and sleeping again.
17+
18+
choice SAMPLE_POWER_CONSUMPTION_RAM_RETAIN
19+
prompt "RAM retention level during System ON Idle"
20+
default SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_FULL
21+
help
22+
Controls the amount of application RAM that remains powered during System ON
23+
Idle, using the ram_pwrdn library (see
24+
nrf/doc/nrf/libraries/others/ram_pwrdn.rst). Total amount of SRAM on
25+
nrf7120dk/nrf7120/cpuapp is 1016 KiB, not 1024 KiB -- keep this in
26+
mind when reading the option names below.
27+
28+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K
29+
bool "Retain only the first 64 KiB of application RAM, power down the rest"
30+
select RAM_POWER_DOWN_LIBRARY
31+
help
32+
Calls power_down_ram() once at boot to power down everything past
33+
the first 64 KiB of application RAM (out of 1016 KiB total).
34+
35+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_128K
36+
bool "Retain only the first 128 KiB of application RAM, power down the rest"
37+
select RAM_POWER_DOWN_LIBRARY
38+
help
39+
Calls power_down_ram() once at boot to power down everything past
40+
the first 128 KiB of application RAM (out of 1016 KiB total).
41+
42+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_256K
43+
bool "Retain only the first 256 KiB of application RAM, power down the rest"
44+
select RAM_POWER_DOWN_LIBRARY
45+
help
46+
Calls power_down_ram() once at boot to power down everything past
47+
the first 256 KiB of application RAM (out of 1016 KiB total).
48+
49+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_512K
50+
bool "Retain only the first 512 KiB of application RAM, power down the rest"
51+
select RAM_POWER_DOWN_LIBRARY
52+
help
53+
Calls power_down_ram() once at boot to power down everything past
54+
the first 512 KiB of application RAM (out of 1016 KiB total, so
55+
this leaves slightly more than half of RAM powered down, not
56+
exactly half).
57+
58+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_FULL
59+
bool "Retain all RAM (default) -- nothing is powered down"
60+
help
61+
No RAM power-down call is made at all. This is the default: by
62+
default, all RAM must stay retained.
63+
64+
config SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_UNUSED_ONLY
65+
bool "Power down whatever this image itself does not use"
66+
select RAM_POWER_DOWN_LIBRARY
67+
help
68+
Calls power_down_unused_ram() instead of a fixed KiB boundary --
69+
the ram_pwrdn library computes the unused range itself, from the
70+
end of the running image to the end of application RAM. Whichever
71+
RAM section still holds live image/stack data is left powered,
72+
same as every other tier above.
73+
74+
endchoice
75+
76+
source "Kconfig.zephyr"
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
.. _power_consumption_sample:
2+
3+
.. ncs-sample::
4+
:title: Power consumption (System ON Idle)
5+
6+
The Power consumption (System ON Idle) sample demonstrates how to evaluate the power consumption of the nRF7120 SoC during the System ON Idle state.
7+
The sample application is set to periodically sleep for a configurable duration, after which the device wakes up from sleep, printing the wake up count.
8+
In addition to that, the sample demonstrates the different RAM retention levels available through the :ref:`lib_ram_pwrdn` library.
9+
10+
Requirements
11+
************
12+
13+
The sample supports the following development kit:
14+
15+
.. table-from-sample-yaml::
16+
17+
The sample also requires a `Power Profiler Kit II (PPK2)`_, for measuring current consumption.
18+
19+
Overview
20+
********
21+
22+
At boot, the sample performs the following operations:
23+
24+
1. Prints a reminder to switch the board's power off and back on before taking a power measurement (see `Measuring the power consumption`_).
25+
#. Applies the user-configured RAM retention level.
26+
#. Enters a periodic loop, where it:
27+
28+
a. Transits to sleep (System ON Idle) for a period of :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_IDLE_SECONDS` (10 seconds by default).
29+
#. Wakes up from sleep.
30+
#. Prints the wake-up counter value.
31+
#. Transits to sleep again.
32+
33+
RAM retention levels
34+
=====================
35+
36+
By default, all application RAM is retained during System ON Idle.
37+
The sample's own Kconfig allows the user to configure the amount of RAM that is retained, exposing a choice of retention levels, each backed by the :ref:`lib_ram_pwrdn` library:
38+
39+
.. list-table::
40+
:header-rows: 1
41+
42+
* - Kconfig option
43+
- Behavior
44+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_FULL` (default)
45+
- All RAM stays retained.
46+
No RAM is powered down.
47+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K`
48+
- Only the first 64 KiB of RAM stays retained; the rest is powered down.
49+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_128K`
50+
- Only the first 128 KiB of RAM stays retained; the rest is powered down.
51+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_256K`
52+
- Only the first 256 KiB of RAM stays retained; the rest is powered down.
53+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_512K`
54+
- Only the first 512 KiB of RAM stays retained; the rest is powered down.
55+
* - :kconfig:option:`CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_UNUSED_ONLY`
56+
- Powers down all RAM that is left unused by the sample application image, using the library's own automatic detection (``power_down_unused_ram()``), instead of a fixed KiB boundary.
57+
58+
Building and running
59+
********************
60+
61+
.. |sample path| replace:: :file:`nrf/samples/benchmarks/power_consumption`
62+
63+
.. include:: /includes/build_and_run.txt
64+
65+
The default configuration (all RAM retained) is built with:
66+
67+
.. code-block:: console
68+
69+
west build -p always -b nrf7120dk/nrf7120/cpuapp nrf/samples/benchmarks/power_consumption
70+
71+
To build the sample with any other of the supported RAM retention levels, pass the matching Kconfig option on the command line, for example:
72+
73+
.. code-block:: console
74+
75+
west build -p always -b nrf7120dk/nrf7120/cpuapp nrf/samples/benchmarks/power_consumption -- -DCONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K=y
76+
77+
The same supported six configurations are also given in the :file:`tests.yaml` file (for example ``sample.benchmarks.power_consumption.ram_retain_64k``), for use with ``west build -T <name>`` or Twister.
78+
79+
Testing
80+
========
81+
82+
|test_sample|
83+
84+
Measuring the power consumption
85+
-------------------------------
86+
87+
.. important::
88+
The debugger or SWD connection used during flashing draws additional current and can leave the target in a state that does not reflect its true standalone power consumption.
89+
Always power-cycle the target after flashing before taking a reading, as described in **Step 8** below.
90+
91+
**P601** is a 1x3 header (pin 1 ``P5V0``, pin 2 ``VBAT_5V0``, pin 3 ``GND``), normally bridged by the **JP601** shunt jumper so ``P5V0`` feeds straight through to ``VBAT_5V0``.
92+
To measure current with a PPK2 in source meter mode, complete the following steps:
93+
94+
1. Remove the **JP601** shunt jumper from **P601**.
95+
#. Connect the PPK2's **Vout** to **P601** pin 2 (``VBAT_5V0``).
96+
#. Connect the PPK2's **GND** to **P601** pin 3 (``GND``).
97+
#. Connect the USB cable to the DK to flash the image (the DK's interface MCU/debugger runs on its own USB-derived supply; with the **JP601** shunt removed, the nRF7120 itself is powered only from **P601** pin 2, i.e. the PPK2, throughout).
98+
#. In the PPK2 app, select **Source Meter** mode and enable power output with **3.6 V** as the supply voltage.
99+
#. Run ``west flash`` to flash the image.
100+
#. Remove the USB cable.
101+
#. Toggle the PPK2's **Enable power output** control off and back on.
102+
This power-cycles the target now that the debugger is disconnected, giving an accurate measurement.
103+
104+
Sample output
105+
**************
106+
107+
The sample shows the following output:
108+
109+
.. code-block:: console
110+
111+
Power consumption demo ready.
112+
Switch the board's power off and back on now to get correct power consumption readings.
113+
114+
Woken up 1 time(s)
115+
Woken up 2 time(s)
116+
Woken up 3 time(s)
117+
118+
Dependencies
119+
************
120+
121+
This sample uses the following |NCS| library:
122+
123+
* :ref:`lib_ram_pwrdn`
124+
125+
It uses the following Zephyr library:
126+
127+
* :ref:`zephyr:kernel_api`
128+
129+
In addition, the non-secure build uses the following secure firmware component:
130+
131+
* :ref:`Trusted Firmware-M <ug_tfm>`
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Serial console is on by default so the reset-button prompt and the
2+
# wake counter are visible out of the box. For the most accurate current
3+
# reading, disable it (see README.rst) -- logging over UART measurably
4+
# raises the current draw.
5+
CONFIG_SERIAL=y
6+
CONFIG_CONSOLE=y
7+
CONFIG_UART_CONSOLE=y
8+
9+
# Required so the console (UART) can actually be suspended around each
10+
# idle window (see main.c) -- without this, the UART peripheral (and
11+
# whatever clock it depends on) stays fully active for the whole "idle"
12+
# window, which dominates the measured current.
13+
CONFIG_PM_DEVICE=y
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/device.h>
8+
#include <zephyr/devicetree.h>
9+
#include <zephyr/kernel.h>
10+
#include <zephyr/pm/device.h>
11+
12+
#if defined(CONFIG_RAM_POWER_DOWN_LIBRARY)
13+
#include <ram_pwrdn.h>
14+
#endif
15+
16+
#define IDLE_TIME K_SECONDS(CONFIG_SAMPLE_POWER_CONSUMPTION_IDLE_SECONDS)
17+
18+
static void configure_ram_retention(void)
19+
{
20+
#if defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_UNUSED_ONLY)
21+
power_down_unused_ram();
22+
#elif defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K) || \
23+
defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_128K) || \
24+
defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_256K) || \
25+
defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_512K)
26+
uintptr_t ram_start = DT_REG_ADDR(DT_CHOSEN(zephyr_sram));
27+
uintptr_t ram_end = ram_start + DT_REG_SIZE(DT_CHOSEN(zephyr_sram));
28+
29+
#if defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K)
30+
uintptr_t retained_size = 64U * 1024U;
31+
#elif defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_128K)
32+
uintptr_t retained_size = 128U * 1024U;
33+
#elif defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_256K)
34+
uintptr_t retained_size = 256U * 1024U;
35+
#elif defined(CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_512K)
36+
uintptr_t retained_size = 512U * 1024U;
37+
#endif
38+
39+
power_down_ram(ram_start + retained_size, ram_end);
40+
#endif
41+
/* CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_FULL (default): no
42+
* power-down call at all -- every byte of application RAM stays retained.
43+
*/
44+
}
45+
46+
int main(void)
47+
{
48+
#if defined(CONFIG_SERIAL)
49+
const struct device *const console = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
50+
int err;
51+
52+
if (!device_is_ready(console)) {
53+
return 0;
54+
}
55+
56+
printk("\nPower consumption demo ready.\n"
57+
"Switch the board's power off and back on now to get correct "
58+
"power consumption readings.\n\n");
59+
#endif
60+
61+
configure_ram_retention();
62+
63+
#if defined(CONFIG_SERIAL)
64+
uint32_t wakeups = 0;
65+
#endif
66+
67+
while (true) {
68+
#if defined(CONFIG_SERIAL)
69+
/* Suspend the console (UART) before sleeping -- otherwise it
70+
* stays fully active (and keeps whatever clock it depends on
71+
* requested) for the whole "idle" window, which is the
72+
* single biggest cause of elevated idle current in a sample
73+
* like this.
74+
*/
75+
err = pm_device_action_run(console, PM_DEVICE_ACTION_SUSPEND);
76+
if (err != 0) {
77+
printk("Failed to suspend console: %d\n", err);
78+
return 0;
79+
}
80+
#endif
81+
82+
k_sleep(IDLE_TIME);
83+
84+
#if defined(CONFIG_SERIAL)
85+
err = pm_device_action_run(console, PM_DEVICE_ACTION_RESUME);
86+
if (err != 0) {
87+
return 0;
88+
}
89+
90+
wakeups++;
91+
printk("Woken up %u time(s)\n", wakeups);
92+
#endif
93+
}
94+
95+
return 0;
96+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
sample:
2+
name: Power consumption (System ON Idle)
3+
common:
4+
tags:
5+
- power
6+
- ci_samples_benchmarks
7+
harness: console
8+
harness_config:
9+
type: multi_line
10+
ordered: true
11+
regex:
12+
- "Power consumption demo ready."
13+
- 'Woken up 1 time\(s\)'
14+
platform_allow:
15+
- nrf7120dk/nrf7120/cpuapp
16+
- nrf7120dk/nrf7120/cpuapp/ns
17+
integration_platforms:
18+
- nrf7120dk/nrf7120/cpuapp
19+
- nrf7120dk/nrf7120/cpuapp/ns
20+
tests:
21+
sample.benchmarks.power_consumption.ram_retain_full:
22+
extra_configs:
23+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_FULL=y
24+
sample.benchmarks.power_consumption.ram_retain_64k:
25+
extra_configs:
26+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_64K=y
27+
sample.benchmarks.power_consumption.ram_retain_128k:
28+
extra_configs:
29+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_128K=y
30+
sample.benchmarks.power_consumption.ram_retain_256k:
31+
extra_configs:
32+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_256K=y
33+
sample.benchmarks.power_consumption.ram_retain_512k:
34+
extra_configs:
35+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_512K=y
36+
sample.benchmarks.power_consumption.ram_powerdown_unused:
37+
extra_configs:
38+
- CONFIG_SAMPLE_POWER_CONSUMPTION_RAM_RETAIN_UNUSED_ONLY=y

0 commit comments

Comments
 (0)