tests/kernel/context: Improve to resist parallel threads interrupting

This test assumes that nothing will wake the CPU apart from
the timer set by the test.
But that is not necessarily the case.
Some other platform thread started at boot
may be waking the CPU every now and then.

Let's allow for some spurious wakes while we are testing k_cpu_idle,
while at the same time ensuring we are not just busy waiting
all the way.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
Alberto Escolar Piedras 2024-01-11 14:27:01 +01:00 committed by Carles Cufí
parent 6876f9eea1
commit 972a4d9f6f
2 changed files with 27 additions and 5 deletions

View file

@ -0,0 +1,14 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
config MAX_IDLE_WAKES
int "Maximum number of spurious wakes during k_cpu_idle() test"
default 1 if NRF53_SYNC_RTC
default 0
help
The platform may have some component running in the background while the k_cpu_idle test is
running causing the CPU to awake. With this option we allow for a maximum number of wakes
for each 10ms idle test, which by default should be 0.
# Include Zephyr's Kconfig
source "Kconfig"

View file

@ -212,9 +212,12 @@ void irq_enable_wrapper(int irq)
#if defined(CONFIG_TICKLESS_KERNEL)
static struct k_timer idle_timer;
static volatile bool idle_timer_done;
static void idle_timer_expiry_function(struct k_timer *timer_id)
{
k_timer_stop(&idle_timer);
idle_timer_done = true;
}
static void _test_kernel_cpu_idle(int atomic)
@ -223,6 +226,7 @@ static void _test_kernel_cpu_idle(int atomic)
unsigned int i, key;
uint32_t dur = k_ms_to_ticks_ceil32(10);
uint32_t slop = 1 + k_ms_to_ticks_ceil32(1);
int idle_loops;
/* Set up a time to trigger events to exit idle mode */
k_timer_init(&idle_timer, idle_timer_expiry_function, NULL);
@ -230,13 +234,17 @@ static void _test_kernel_cpu_idle(int atomic)
for (i = 0; i < 5; i++) {
k_usleep(1);
t0 = k_uptime_ticks();
idle_loops = 0;
idle_timer_done = false;
k_timer_start(&idle_timer, K_TICKS(dur), K_NO_WAIT);
key = irq_lock();
if (atomic) {
k_cpu_atomic_idle(key);
} else {
k_cpu_idle();
}
do {
if (atomic) {
k_cpu_atomic_idle(key);
} else {
k_cpu_idle();
}
} while ((idle_loops++ < CONFIG_MAX_IDLE_WAKES) && (idle_timer_done == false));
dt = k_uptime_ticks() - t0;
zassert_true(abs((int32_t) (dt - dur)) <= slop,
"Inaccurate wakeup, idled for %d ticks, expected %d",