Skip to content

Commit

Permalink
tests: benchmarks: multicore: Add idle_counter
Browse files Browse the repository at this point in the history
Add test to validate fast TIMER operation

Signed-off-by: Piotr Krzyzanowski <[email protected]>
  • Loading branch information
nordic-pikr committed Jan 19, 2025
1 parent 5e12525 commit fa77f06
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 0 deletions.
19 changes: 19 additions & 0 deletions tests/benchmarks/multicore/idle_counter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

if(NOT SYSBUILD)
message(FATAL_ERROR
" This is a multi-image application that should be built using sysbuild.\n"
" Add --sysbuild argument to west build command to prepare all the images.")
endif()

project(idle_counter)

target_sources(app PRIVATE src/main.c)
15 changes: 15 additions & 0 deletions tests/benchmarks/multicore/idle_counter/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

config TEST_SLEEP_DURATION_MS
int "Core sleep duration (miliseconds)"
default 1000
help
Set sleep duration to TEST_SLEEP_DURATION_MS miliseconds.
Based on the value of 'min-residency-us' specified for each power state defined in the DTS,
core enters the lowest possible power state.

source "Kconfig.zephyr"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/ {
aliases {
led = &led0;
/delete-property/ led1;
counter = &timer120;
};
};

&timer120 {
status = "okay";
};

/delete-node/ &led1;
16 changes: 16 additions & 0 deletions tests/benchmarks/multicore/idle_counter/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Drivers and peripherals
CONFIG_COUNTER=y

# Enable runtime power management for peripheral
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y

CONFIG_PM=y
CONFIG_PM_S2RAM=y
CONFIG_PM_S2RAM_CUSTOM_MARKING=y
CONFIG_POWEROFF=y
CONFIG_SERIAL=n
CONFIG_BOOT_BANNER=n
CONFIG_LOG=n

CONFIG_ASSERT=y
12 changes: 12 additions & 0 deletions tests/benchmarks/multicore/idle_counter/remote/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(remote)

target_sources(app PRIVATE ../src/main.c)
15 changes: 15 additions & 0 deletions tests/benchmarks/multicore/idle_counter/remote/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

config TEST_SLEEP_DURATION_MS
int "Core sleep duration (miliseconds)"
default 1000
help
Set sleep duration to TEST_SLEEP_DURATION_MS miliseconds.
Based on the value of 'min-residency-us' specified for each power state defined in the DTS,
core enters the lowest possible power state.

source "Kconfig.zephyr"
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>

/ {
aliases {
led = &led1;
counter = &timer130;
};

leds {
compatible = "gpio-leds";
led1: led_1 {
gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>;
label = "Green LED 1";
};
};
};

&gpio9 {
status = "okay";
};

&gpiote130 {
status = "okay";
};

&timer130 {
status = "okay";
};
18 changes: 18 additions & 0 deletions tests/benchmarks/multicore/idle_counter/remote/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Drivers and peripherals
CONFIG_COUNTER=y
CONFIG_GPIO=y

# Enable runtime power management for peripheral
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y

CONFIG_PM=y
CONFIG_PM_S2RAM=y
CONFIG_PM_S2RAM_CUSTOM_MARKING=y
CONFIG_POWEROFF=y
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_SERIAL=n
CONFIG_BOOT_BANNER=n

CONFIG_ASSERT=y
134 changes: 134 additions & 0 deletions tests/benchmarks/multicore/idle_counter/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/counter.h>
#include <zephyr/logging/log.h>
#include <zephyr/devicetree/clocks.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>

LOG_MODULE_REGISTER(idle_counter);

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led), gpios);

#define ALARM_CHANNEL_ID (0)
const struct device *const counter_dev = DEVICE_DT_GET(DT_ALIAS(counter));

static K_SEM_DEFINE(my_sem, 0, 1);

#if defined(CONFIG_CLOCK_CONTROL) && defined(CONFIG_SOC_NRF54H20_CPUAPP)
const uint32_t freq[] = {320, 256, 128, 64};

/*
* Set Global Domain frequency (HSFLL120)
*/
void set_global_domain_frequency(uint32_t freq)
{
int err;
int res;
struct onoff_client cli;
const struct device *hsfll_dev = DEVICE_DT_GET(DT_NODELABEL(hsfll120));
const struct nrf_clock_spec clk_spec_global_hsfll = {.frequency = MHZ(freq)};

LOG_INF("Requested frequency [Hz]: %d", clk_spec_global_hsfll.frequency);
sys_notify_init_spinwait(&cli.notify);
err = nrf_clock_control_request(hsfll_dev, &clk_spec_global_hsfll, &cli);
__ASSERT((err >= 0 && err < 3), "Wrong nrf_clock_control_request return code");
do {
err = sys_notify_fetch_result(&cli.notify, &res);
k_yield();
} while (err == -EAGAIN);
__ASSERT(err == 0, "Wrong clock control request return code");
__ASSERT(res == 0, "Wrong clock control request response");
}
#endif /* CONFIG_CLOCK_CONTROL && CONFIG_SOC_NRF54H20_CPUAPP */

void counter_handler(const struct device *counter_dev, uint8_t chan_id, uint32_t ticks,
void *user_data)
{
gpio_pin_set_dt(&led, 1);
k_sem_give(&my_sem);
counter_stop(counter_dev);
}

uint32_t start_timer(const struct device *counter_dev)
{
uint32_t start_time;
struct counter_alarm_cfg counter_cfg;

counter_cfg.flags = 0;
counter_cfg.ticks = counter_us_to_ticks(counter_dev, CONFIG_TEST_SLEEP_DURATION_MS * 1000);
counter_cfg.callback = counter_handler;
counter_cfg.user_data = &counter_cfg;
counter_set_channel_alarm(counter_dev, ALARM_CHANNEL_ID, &counter_cfg);

counter_start(counter_dev);
start_time = k_cycle_get_32();

LOG_INF("Counter starts at %u cycle", start_time);

return start_time;
}

void verify_timer(uint32_t start_time)
{
uint32_t elapsed;
int ret;

ret = gpio_pin_set_dt(&led, 0);
__ASSERT(ret == 0, "Unable to turn off LED");
ret = k_sem_take(&my_sem, K_MSEC(CONFIG_TEST_SLEEP_DURATION_MS + 100));
elapsed = k_cycle_get_32() - start_time;
__ASSERT(ret == 0, "Timer callback not called");
ret = gpio_pin_set_dt(&led, 1);
__ASSERT(ret == 0, "Unable to turn on LED");
LOG_INF("Elapsed %u cycles (%uus)", elapsed, k_cyc_to_us_ceil32(elapsed));
__ASSERT(elapsed > k_ms_to_cyc_ceil32(CONFIG_TEST_SLEEP_DURATION_MS - 10) &&
elapsed < k_ms_to_cyc_ceil32(CONFIG_TEST_SLEEP_DURATION_MS + 10),
"expected time to elapse is 1s");
}

int main(void)
{
uint32_t start_time;
int ret;

ret = gpio_is_ready_dt(&led);
__ASSERT(ret, "Error: GPIO Device not ready");

ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
__ASSERT(ret == 0, "Could not configure led GPIO");

/* Wait a bit to solve NRFS request timeout issue. */
k_msleep(600);

while (1) {
ret = gpio_pin_set_dt(&led, 0);
__ASSERT(ret == 0, "Unable to turn off LED");
k_msleep(CONFIG_TEST_SLEEP_DURATION_MS);
ret = gpio_pin_set_dt(&led, 1);
__ASSERT(ret == 0, "Unable to turn on LED");
k_busy_wait(100000);

#if defined(CONFIG_CLOCK_CONTROL) && defined(CONFIG_SOC_NRF54H20_CPUAPP)
for (int i = 0; i <= ARRAY_SIZE(freq); i++) {
start_time = start_timer(counter_dev);
if (i) {
set_global_domain_frequency(freq[i - 1]);
}
verify_timer(start_time);
k_busy_wait(100000);
}
#else
start_time = start_timer(counter_dev);
verify_timer(start_time);
k_busy_wait(100000);
#endif /* CONFIG_CLOCK_CONTROL && CONFIG_SOC_NRF54H20_CPUAPP */
}

return 0;
}
13 changes: 13 additions & 0 deletions tests/benchmarks/multicore/idle_counter/sysbuild.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

# Add remote project
ExternalZephyrProject_Add(
APPLICATION remote
SOURCE_DIR ${ZEPHYR_NRF_MODULE_DIR}/tests/benchmarks/power_consumption/common/remote_sleep_forever
BOARD ${SB_CONFIG_BOARD}/${SB_CONFIG_SOC}/cpurad
BOARD_REVISION ${BOARD_REVISION}
)
18 changes: 18 additions & 0 deletions tests/benchmarks/multicore/idle_counter/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
common:
tags:
- ppk_power_measure
- ci_tests_benchmarks_current_consumption
tests:
benchmarks.power_consumption.counter:
sysbuild: true
integration_platforms:
- nrf54h20dk/nrf54h20/cpuapp
platform_allow:
- nrf54h20dk/nrf54h20/cpuapp
extra_args:
- CONFIG_CLOCK_CONTROL=y
harness: pytest
harness_config:
fixture: ppk_power_measure
pytest_root:
- "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_fast_timer_and_s2ram_with_clock_control"

0 comments on commit fa77f06

Please sign in to comment.