From 01f40b9a7429ef94d06715fc2dabd656acaa7186 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 11 Aug 2023 15:41:51 +0300 Subject: [PATCH] tests: kernel: interrupt: Add testcase for shared interrupts This commit introduces a new testcase for shared interrupts. Signed-off-by: Laurentiu Mihalcea --- tests/kernel/interrupt/CMakeLists.txt | 1 + tests/kernel/interrupt/src/shared_irq.c | 182 ++++++++++++++++++++++++ tests/kernel/interrupt/testcase.yaml | 9 ++ 3 files changed, 192 insertions(+) create mode 100644 tests/kernel/interrupt/src/shared_irq.c diff --git a/tests/kernel/interrupt/CMakeLists.txt b/tests/kernel/interrupt/CMakeLists.txt index 20851bb5ff41912..998bfe52926ad26 100644 --- a/tests/kernel/interrupt/CMakeLists.txt +++ b/tests/kernel/interrupt/CMakeLists.txt @@ -17,3 +17,4 @@ target_sources(app PRIVATE target_sources_ifdef(CONFIG_DYNAMIC_INTERRUPTS app PRIVATE src/dynamic_isr.c) target_sources_ifdef(CONFIG_X86 app PRIVATE src/regular_isr.c) +target_sources_ifdef(CONFIG_SHARED_INTERRUPTS app PRIVATE src/shared_irq.c) diff --git a/tests/kernel/interrupt/src/shared_irq.c b/tests/kernel/interrupt/src/shared_irq.c new file mode 100644 index 000000000000000..428353284f08b1c --- /dev/null +++ b/tests/kernel/interrupt/src/shared_irq.c @@ -0,0 +1,182 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if defined(CONFIG_GIC) +#define TEST_IRQ_LINE_1 10 +#define TEST_IRQ_LINE_2 11 +#else +#define TEST_IRQ_LINE_1 (CONFIG_NUM_IRQS - 7) +#define TEST_IRQ_LINE_2 (CONFIG_NUM_IRQS - 6) +#endif + +#define TEST_IRQ_PRIORITY 0 +#define NUM_TEST_ISRS 4 + +static uint32_t test_vector[NUM_TEST_ISRS]; +static uint32_t test_vector_results[NUM_TEST_ISRS] = { + 0xdeadbeef, + 0xcafebabe, + 0xcafebeef, + 0xabcd1234, +}; + +void test_isr_1(const void *data) +{ + int index = POINTER_TO_INT(data); + + test_vector[index] = test_vector_results[index]; +} + +void test_isr_2(const void *data) +{ + int index = POINTER_TO_INT(data); + + test_vector[index] = test_vector_results[index]; +} + +void test_isr_3(const void *data) +{ + int index = POINTER_TO_INT(data); + + test_vector[index] = test_vector_results[index]; +} + +void test_isr_4(const void *data) +{ + int index = POINTER_TO_INT(data); + + test_vector[index] = test_vector_results[index]; +} + +static void reset_test_vector(void) +{ + int i; + + for (i = 0; i < NUM_TEST_ISRS; i++) + test_vector[i] = 0; +} + +ZTEST(interrupt_feature, test_shared_irq) +{ + int i; + + IRQ_CONNECT(TEST_IRQ_LINE_1, TEST_IRQ_PRIORITY, test_isr_1, 0, 0); + IRQ_CONNECT(TEST_IRQ_LINE_1, TEST_IRQ_PRIORITY, test_isr_2, (void *)1, 0); + IRQ_CONNECT(TEST_IRQ_LINE_2, TEST_IRQ_PRIORITY, test_isr_3, (void *)2, 0); + + zassert_true(_shared_irq_table[TEST_IRQ_LINE_1].client_num == 2, + "_shared_irq_table should have 2 clients."); + + zassert_true(_sw_isr_table[TEST_IRQ_LINE_1].isr == shared_isr, + "the ISR for TEST_IRQ_LINE_1 should be shared_isr"); + + zassert_true(_sw_isr_table[TEST_IRQ_LINE_1].arg == + &_shared_irq_table[TEST_IRQ_LINE_1], + "the arg from TEST_IRQ_LINE_1's entry in _sw_isr_table should be _shared_irq_table[TEST_IRQ_LINE_1]"); + + zassert_true(_sw_isr_table[TEST_IRQ_LINE_2].isr == test_isr_3, + "the routine entry from _sw_isr_table[TEST_IRQ_LINE_2] should be test_isr_3"); + + irq_enable(TEST_IRQ_LINE_1); + irq_enable(TEST_IRQ_LINE_2); + + trigger_irq(TEST_IRQ_LINE_1); + trigger_irq(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + /* check results */ + for (i = 0; i < NUM_TEST_ISRS - 1; i++) { + zassert_true(test_vector[i] == test_vector_results[i], + "wrong test_vector value"); + } + + irq_disable(TEST_IRQ_LINE_1); + irq_disable(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + reset_test_vector(); + +#ifdef CONFIG_DYNAMIC_INTERRUPTS + arch_irq_connect_dynamic(TEST_IRQ_LINE_2, TEST_IRQ_PRIORITY, test_isr_4, + (void *)3, 0); + + zassert_true(_shared_irq_table[TEST_IRQ_LINE_2].clients[0].routine == + test_isr_3, + "first client's routine on TEST_IRQ_LINE_2 should be test_isr_3"); + + zassert_true(_shared_irq_table[TEST_IRQ_LINE_2].clients[1].routine == + test_isr_4, + "second client's routine on TEST_IRQ_LINE_2 should be test_isr_4"); + + zassert_true(_sw_isr_table[TEST_IRQ_LINE_2].isr == shared_isr, + "the ISR for TEST_IRQ_LINE_2 should be shared_isr"); + + irq_enable(TEST_IRQ_LINE_2); + + trigger_irq(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + /* check results */ + zassert_true(test_vector[3] == test_vector_results[3], + "wrong test_vector value"); + + irq_disable(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + reset_test_vector(); + + /* note: this will not remove test_isr_3 from the client list since + * the argument is different from the one we used for registration. + */ + arch_irq_disconnect_dynamic(TEST_IRQ_LINE_2, TEST_IRQ_PRIORITY, + test_isr_3, (void *)0xdeadbeef, 0); + + irq_enable(TEST_IRQ_LINE_2); + + trigger_irq(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + zassert_true(!test_vector[0] && !test_vector[1] && + test_vector[3] == test_vector_results[3] && + test_vector[2] == test_vector_results[2], + "wrong test_vector value"); + + irq_disable(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + reset_test_vector(); + + /* this will remove test_isr_3 */ + arch_irq_disconnect_dynamic(TEST_IRQ_LINE_2, TEST_IRQ_PRIORITY, + test_isr_3, (void *)2, 0); + + irq_enable(TEST_IRQ_LINE_2); + + trigger_irq(TEST_IRQ_LINE_2); + + /* wait a bit */ + k_busy_wait(5000); + + zassert_true(test_vector[3] == test_vector_results[3] && + !test_vector[2] && !test_vector[1] && !test_vector[0], + "wrong test_vector value"); +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ +} diff --git a/tests/kernel/interrupt/testcase.yaml b/tests/kernel/interrupt/testcase.yaml index ba94c20b8b449c1..87d18432a1b50ce 100644 --- a/tests/kernel/interrupt/testcase.yaml +++ b/tests/kernel/interrupt/testcase.yaml @@ -6,3 +6,12 @@ tests: - kernel - interrupt filter: not CONFIG_TRUSTED_EXECUTION_NONSECURE + arch.shared_interrupt: + arch_allow: + - arm64 + - arm + tags: + - kernel + - interrupt + extra_configs: + - CONFIG_SHARED_INTERRUPTS=y