blob: 35f42220fb8f893943aa32b79cbb175333d5017d [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/interrupt_util.h>
#define ISR_DYN_ARG 0xab249cfd
static unsigned int handler_has_run;
static uintptr_t handler_test_result;
static void dyn_isr(const void *arg)
{
ARG_UNUSED(arg);
handler_test_result = (uintptr_t)arg;
handler_has_run++;
}
#if defined(CONFIG_GEN_SW_ISR_TABLE)
extern struct _isr_table_entry _sw_isr_table[];
/**
* @brief Test dynamic ISR installation
*
* @ingroup kernel_interrupt_tests
*
* @details This routine locates an unused entry in the software ISR table,
* installs a dynamic ISR to the unused entry by calling the dynamic
* configured function, and verifies that the ISR is successfully installed
* by checking the software ISR table entry.
*
* @see arch_irq_connect_dynamic()
*/
ZTEST(interrupt_feature, test_isr_dynamic)
{
int i;
const void *argval;
for (i = 0; i < (CONFIG_NUM_IRQS - CONFIG_GEN_IRQ_START_VECTOR); i++) {
if (_sw_isr_table[i].isr == z_irq_spurious) {
break;
}
}
zassert_true(_sw_isr_table[i].isr == z_irq_spurious,
"could not find slot for dynamic isr");
printk("installing dynamic ISR for IRQ %d\n",
CONFIG_GEN_IRQ_START_VECTOR + i);
argval = (const void *)&i;
arch_irq_connect_dynamic(i + CONFIG_GEN_IRQ_START_VECTOR, 0, dyn_isr,
argval, 0);
zassert_true(_sw_isr_table[i].isr == dyn_isr &&
_sw_isr_table[i].arg == argval,
"dynamic isr did not install successfully");
}
#else
/*
* For testing arch such as x86, x86_64 and posix which support dynamic
* interrupt but without SW ISR table, we test it by applying for a
* dynamic interrupt and then trigger it to check if happened correctly.
*/
#if defined(CONFIG_X86)
#define IV_IRQS 32 /* start of vectors available for x86 IRQs */
#define TEST_IRQ_DYN_LINE 25
#elif defined(CONFIG_ARCH_POSIX)
#define TEST_IRQ_DYN_LINE 5
#endif
void test_isr_dynamic(void)
{
int vector_num;
/**TESTPOINT: configuration of interrupts dynamically at runtime */
vector_num = arch_irq_connect_dynamic(TEST_IRQ_DYN_LINE, 1, dyn_isr,
(void *)ISR_DYN_ARG, 0);
#if defined(CONFIG_X86_64)
/* The isr table for x86_64 is visiable, so check it up here */
extern void (*x86_irq_funcs[])(const void *);
extern const void *x86_irq_args[];
zassert_true(x86_irq_funcs[vector_num - IV_IRQS] == dyn_isr &&
x86_irq_args[vector_num - IV_IRQS] == (void *)ISR_DYN_ARG,
"dynamic isr did not install successfully");
#endif
TC_PRINT("vector(%d)\n", vector_num);
zassert_true(vector_num > 0,
"irq connect dynamic failed");
zassert_equal(handler_has_run, 0,
"handler has run before interrupt trigger");
irq_enable(TEST_IRQ_DYN_LINE);
trigger_irq(vector_num);
zassert_equal(handler_has_run, 1,
"interrupt triggered but handler has not run(%d)",
handler_has_run);
/**TESTPOINT: pass word-sized parameter to interrupt */
zassert_equal(handler_test_result, ISR_DYN_ARG,
"parameter(0x%lx) in handler is not correct",
handler_test_result);
trigger_irq(vector_num);
/**TESTPOINT: interrupt triggered again */
zassert_equal(handler_has_run, 2,
"interrupt triggered but handler has not run(%d)",
handler_has_run);
}
#endif /* CONFIG_GEN_SW_ISR_TABLE */