blob: 6a21c8ac7dafe8ee051684e375e16b3b74e7c5c4 [file] [log] [blame]
/*
* Copyright (c) 2019 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
static volatile int test_flag;
void arm_zero_latency_isr_handler(const void *args)
{
ARG_UNUSED(args);
test_flag = 1;
}
ZTEST(arm_irq_advanced_features, test_arm_zero_latency_irqs)
{
if (!IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
TC_PRINT("Skipped (Cortex-M Mainline only)\n");
return;
}
/* Determine an NVIC IRQ line that is not currently in use. */
int i, key;
int init_flag, post_flag;
init_flag = test_flag;
zassert_false(init_flag, "Test flag not initialized to zero\n");
for (i = CONFIG_NUM_IRQS - 1; i >= 0; i--) {
if (NVIC_GetEnableIRQ(i) == 0) {
/*
* Interrupts configured statically with IRQ_CONNECT(.)
* are automatically enabled. NVIC_GetEnableIRQ()
* returning false, here, implies that the IRQ line is
* either not implemented or it is not enabled, thus,
* currently not in use by Zephyr.
*/
/* Set the NVIC line to pending. */
NVIC_SetPendingIRQ(i);
if (NVIC_GetPendingIRQ(i)) {
/*
* If the NVIC line is pending, it is
* guaranteed that it is implemented; clear the
* line.
*/
NVIC_ClearPendingIRQ(i);
if (!NVIC_GetPendingIRQ(i)) {
/*
* If the NVIC line can be successfully
* un-pended, it is guaranteed that it
* can be used for software interrupt
* triggering. Return the NVIC line
* number.
*/
break;
}
}
}
}
zassert_true(i >= 0,
"No available IRQ line to configure as zero-latency\n");
TC_PRINT("Available IRQ line: %u\n", i);
/* Configure the available IRQ line as zero-latency. */
arch_irq_connect_dynamic(i, 0 /* Unused */,
arm_zero_latency_isr_handler,
NULL,
IRQ_ZERO_LATENCY);
NVIC_ClearPendingIRQ(i);
NVIC_EnableIRQ(i);
/* Lock interrupts */
key = irq_lock();
/* Set the zero-latency IRQ to pending state. */
NVIC_SetPendingIRQ(i);
/*
* Instruction barriers to make sure the NVIC IRQ is
* set to pending state before 'test_flag' is checked.
*/
__DSB();
__ISB();
/* Confirm test flag is set by the zero-latency ISR handler. */
post_flag = test_flag;
zassert_true(post_flag == 1, "Test flag not set by ISR\n");
irq_unlock(key);
}
/**
* @}
*/