blob: 6c3f3934994b941387bd39cdc15c3ebe95676e53 [file] [log] [blame]
/*
* Copyright (c) 2019 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <arch/cpu.h>
#include <arch/arm/cortex_m/cmsis.h>
static volatile int test_flag;
static volatile int expected_reason = -1;
void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf)
{
TC_PRINT("Caught system error -- reason %d\n", reason);
if (expected_reason == -1) {
printk("Was not expecting a crash\n");
k_fatal_halt(reason);
}
if (reason != expected_reason) {
printk("Wrong crash type got %d expected %d\n", reason,
expected_reason);
k_fatal_halt(reason);
}
expected_reason = -1;
}
void arm_isr_handler(void *args)
{
ARG_UNUSED(args);
test_flag++;
if (test_flag == 1) {
/* Intentional Kernel oops */
expected_reason = K_ERR_KERNEL_OOPS;
k_oops();
} else if (test_flag == 2) {
/* Intentional Kernel panic */
expected_reason = K_ERR_KERNEL_PANIC;
k_panic();
} else if (test_flag == 3) {
/* Intentional ASSERT */
expected_reason = K_ERR_KERNEL_PANIC;
__ASSERT(0, "Intentional assert\n");
}
}
void test_arm_interrupt(void)
{
/* Determine an NVIC IRQ line that is not currently in use. */
int i;
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.
*/
break;
}
}
}
zassert_true(i >= 0,
"No available IRQ line to use in the test\n");
TC_PRINT("Available IRQ line: %u\n", i);
z_arch_irq_connect_dynamic(i, 0 /* highest priority */,
arm_isr_handler,
NULL,
0);
NVIC_ClearPendingIRQ(i);
NVIC_EnableIRQ(i);
for (int j = 1; j <= 3; j++) {
/* Set the dynamic 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();
/* Returning here implies the thread was not aborted. */
/* Confirm test flag is set by the ISR handler. */
post_flag = test_flag;
zassert_true(post_flag == j, "Test flag not set by ISR\n");
}
}
/**
* @}
*/