Skip to content

Commit

Permalink
tests: benchmarks: multicore: Add test for S2RAM and watchdog
Browse files Browse the repository at this point in the history
Add test that combinest functional check (feeding the watchdog works)
with non-functional check (current consumption).

Confirm that when watchdog is enabled:
- cpu may enter low power states like IDLE or S2RAM;
- after leaving low power state, WDT will NOT fire when feed on time.

Signed-off-by: Sebastian Głąb <[email protected]>
  • Loading branch information
nordic-segl committed Nov 12, 2024
1 parent ff130b3 commit dfefd8d
Show file tree
Hide file tree
Showing 15 changed files with 339 additions and 0 deletions.
19 changes: 19 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (c) 2024 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_wdt)

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

config TEST_SLEEP_DURATION_MS
int "Amount of time (in miliseconds) the core is sleeping"
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"
10 changes: 10 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/Kconfig.sysbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

source "${ZEPHYR_BASE}/share/sysbuild/Kconfig"

config REMOTE_BOARD
string "The board used for remote target"
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/ {
aliases {
watchdog0 = &wdt010;
};
};

&wdt010 {
status = "okay";
};
5 changes: 5 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG_PRINTK=y
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_ASSERT=y
CONFIG_WATCHDOG=y
20 changes: 20 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/prj_s2ram.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CONFIG_PM=y
CONFIG_PM_S2RAM=y
CONFIG_PM_S2RAM_CUSTOM_MARKING=y
CONFIG_POWEROFF=y
CONFIG_SOC_NRF54H20_NO_MRAM_LATENCY=n

CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y

# Enable for debugging purposes only
CONFIG_BOOT_BANNER=n
CONFIG_NCS_BOOT_BANNER=n
CONFIG_PRINTK=n
CONFIG_LOG=n
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_SERIAL=n

CONFIG_WATCHDOG=y
CONFIG_ASSERT=y
12 changes: 12 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/remote/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Copyright (c) 2024 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_wdt/remote/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

config TEST_SLEEP_DURATION_MS
int "Amount of time (in miliseconds) the core is sleeping"
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,15 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/ {
aliases {
watchdog0 = &wdt010;
};
};

&wdt010 {
status = "okay";
};
5 changes: 5 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/remote/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG_PRINTK=y
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_ASSERT=y
CONFIG_WATCHDOG=y
10 changes: 10 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/remote/prj_s2ram.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CONFIG_PM=y
CONFIG_POWEROFF=y

CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_SERIAL=n
CONFIG_BOOT_BANNER=n
CONFIG_SOC_NRF54H20_NO_MRAM_LATENCY=n

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

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(idle_wdt, LOG_LEVEL_INF);

#include <zephyr/kernel.h>
#include <zephyr/drivers/watchdog.h>

#define WDT_WINDOW_MAX (200)

/* Watchdog related variables */
static const struct device *const my_wdt_device = DEVICE_DT_GET(DT_ALIAS(watchdog0));
static struct wdt_timeout_cfg m_cfg_wdt0;
static int my_wdt_channel;

/* No init section will contain WDT_TAG if watchdog has fired */
#define WDT_TAG (12345678U)

#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
#define NOINIT_SECTION ".dtcm_noinit.test_wdt"
#else
#define NOINIT_SECTION ".noinit.test_wdt"
#endif
static volatile uint32_t wdt_status __attribute__((section(NOINIT_SECTION)));

/* Variables used to make CPU active for ~1 second */
static struct k_timer my_timer;
static bool timer_expired;

static void wdt_int_cb(const struct device *wdt_dev, int channel_id)
{
ARG_UNUSED(wdt_dev);
ARG_UNUSED(channel_id);
wdt_status = WDT_TAG;
}

void my_timer_handler(struct k_timer *dummy)
{
timer_expired = true;
}

int main(void)
{
int ret;
int counter = 0;

LOG_INF("Multicore idle_wdt test on %s", CONFIG_BOARD_TARGET);
LOG_INF("Main sleeps for %d ms", CONFIG_TEST_SLEEP_DURATION_MS);

k_timer_init(&my_timer, my_timer_handler, NULL);

ret = device_is_ready(my_wdt_device);
if (!ret) {
LOG_ERR("WDT device %s is not ready", my_wdt_device->name);
}
__ASSERT(ret, "WDT device %s is not ready\n", my_wdt_device->name);

/* When watchdog fires, variable wdt_status is set to the value of WDT_TAG
* in WDT callback wdt_int_cb(). Then, target is reset.
* Check value of wdt_status to prevent reset loop.
*/
if (wdt_status == WDT_TAG) {
LOG_INF("Watchod has fired");
/* Pinreset shall "recover" test to initial state */
wdt_status = 0U;
__ASSERT(false, "Watchod has fired\n");
} else {
LOG_INF("Reset wasn't due to watchdog.");
}

LOG_INF("wdt_status = %u", wdt_status);
/* Clear flag that is set when the watchdog fires */
wdt_status = 0U;
LOG_INF("wdt_status = %u", wdt_status);

/* Configure Watchdog */
m_cfg_wdt0.callback = wdt_int_cb;
m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC;
m_cfg_wdt0.window.min = 0U;
m_cfg_wdt0.window.max = WDT_WINDOW_MAX;
my_wdt_channel = wdt_install_timeout(my_wdt_device, &m_cfg_wdt0);
if (my_wdt_channel < 0) {
LOG_ERR("wdt_install_timeout() returned %d", my_wdt_channel);
__ASSERT(false, "wdt_install_timeout() returned %d\n", my_wdt_channel);
}

/* Start Watchdog */
ret = wdt_setup(my_wdt_device, WDT_OPT_PAUSE_HALTED_BY_DBG | WDT_OPT_PAUSE_IN_SLEEP);
if (ret < 0) {
LOG_ERR("wdt_setup() returned %d", ret);
__ASSERT(false, "wdt_setup() returned %d\n", ret);
}

/* Run test forever */
while (1) {
timer_expired = false;

/* start a one-shot timer that expires after 1 second */
k_timer_start(&my_timer, K_MSEC(1000), K_NO_WAIT);

/* Keep CPU active for ~ 1 second */
while (!timer_expired) {
ret = wdt_feed(my_wdt_device, my_wdt_channel);
if (ret < 0) {
LOG_ERR("wdt_feed() returned: %d", ret);
/* Stop watchdog */
wdt_disable(my_wdt_device);
__ASSERT(false, "wdt_feed() returned: %d\n", ret);
}
k_busy_wait(10000);
k_yield();
}

LOG_INF("Run %d", counter);
counter++;

/* Sleep / enter low power state
* Watchdog was started with option WDT_OPT_PAUSE_IN_SLEEP thus
* it shall not reset the core during sleep.
*/
k_msleep(CONFIG_TEST_SLEEP_DURATION_MS);
}

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

if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "")
message(FATAL_ERROR "REMOTE_BOARD must be set to a valid board name")
endif()

# Add remote project
ExternalZephyrProject_Add(
APPLICATION remote
SOURCE_DIR ${APP_DIR}/remote
BOARD ${SB_CONFIG_REMOTE_BOARD}
BOARD_REVISION ${BOARD_REVISION}
)

# Add a dependency so that the remote image will be built and flashed first
add_dependencies(idle_wdt remote)
# Add dependency so that the remote image is flashed first.
sysbuild_add_dependencies(FLASH idle_wdt remote)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad"
46 changes: 46 additions & 0 deletions tests/benchmarks/multicore/idle_wdt/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
common:
sysbuild: true
tags: ci_build ci_tests_benchmarks_multicore
platform_allow:
- nrf54h20dk/nrf54h20/cpuapp
integration_platforms:
- nrf54h20dk/nrf54h20/cpuapp

tests:
benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.no_sleep:
extra_args:
SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf
harness: console
harness_config:
type: multi_line
ordered: true
regex:
- "Multicore idle_wdt test on"
- "Run 0"
- "Run 1"

benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.idle:
tags: ppk_power_measure
extra_args:
SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf
idle_wdt_CONF_FILE=prj_s2ram.conf
remote_CONF_FILE=prj_s2ram.conf
idle_wdt_CONFIG_TEST_SLEEP_DURATION_MS=500
remote_CONFIG_TEST_SLEEP_DURATION_MS=500
harness: pytest
harness_config:
fixture: ppk_power_measure
pytest_root:
- "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_idle"

benchmarks.multicore.idle_wdt.nrf54h20dk_cpuapp_cpurad.s2ram:
tags: ppk_power_measure
extra_args:
SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf
idle_wdt_CONF_FILE=prj_s2ram.conf
remote_CONF_FILE=prj_s2ram.conf
harness: pytest
harness_config:
fixture: ppk_power_measure
pytest_root:
- "${CUSTOM_ROOT_TEST_DIR}/test_measure_power_consumption.py::test_measure_and_data_dump_pwm_and_s2ram"

0 comments on commit dfefd8d

Please sign in to comment.