1 /*
2 * Copyright (c) 2019 Nordic Semiconductor ASA.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/arch/cpu.h>
9 #include <cmsis_core.h>
10 #include <zephyr/sys/barrier.h>
11
12 /* Offset for the Direct interrupt used in this test. */
13 #define DIRECT_ISR_OFFSET (CONFIG_NUM_IRQS - 1)
14
15 static volatile int test_flag;
16
arm_direct_isr_handler_0(const void * args)17 void arm_direct_isr_handler_0(const void *args)
18 {
19 ARG_UNUSED(args);
20
21 test_flag = 1;
22 }
23
arm_direct_isr_handler_1(const void * args)24 void arm_direct_isr_handler_1(const void *args)
25 {
26 ARG_UNUSED(args);
27
28 test_flag = 2;
29 }
30
31 /**
32 * @brief Test the ARM Dynamic Direct Interrupts functionality.
33 * @ingroup kernel_arch_interrupt_tests
34 */
ZTEST(arm_irq_advanced_features,test_arm_dynamic_direct_interrupts)35 ZTEST(arm_irq_advanced_features, test_arm_dynamic_direct_interrupts)
36 {
37 int post_flag = 0;
38
39 /* Place the dynamic interrupt dispatcher (with no rescheduling)
40 * in the ROM ISR table.
41 */
42 ARM_IRQ_DIRECT_DYNAMIC_CONNECT(DIRECT_ISR_OFFSET, 0, 0, no_reschedule);
43
44 /* Ensure the IRQ is disabled before enabling it at run time */
45 irq_disable(DIRECT_ISR_OFFSET);
46
47 /* Attach the ISR handler at run time. */
48 irq_connect_dynamic(DIRECT_ISR_OFFSET, 0 /* highest priority */, arm_direct_isr_handler_0,
49 NULL, 0);
50
51 /* Enable and pend the interrupt */
52 irq_enable(DIRECT_ISR_OFFSET);
53 NVIC_SetPendingIRQ(DIRECT_ISR_OFFSET);
54
55 /*
56 * Instruction barriers to make sure the NVIC IRQ is
57 * set to pending state before 'test_flag' is checked.
58 */
59 barrier_dsync_fence_full();
60 barrier_isync_fence_full();
61
62 /* Confirm test flag is set by the dynamic direct ISR handler. */
63 post_flag = test_flag;
64 zassert_true(post_flag == 1, "Test flag not set by ISR0\n");
65
66 post_flag = 0;
67 irq_disable(DIRECT_ISR_OFFSET);
68
69 /* Attach an alternative ISR handler at run-time. */
70 irq_connect_dynamic(DIRECT_ISR_OFFSET, 0 /* highest priority */, arm_direct_isr_handler_1,
71 NULL, 0);
72
73 /* Enable and pend the interrupt */
74 irq_enable(DIRECT_ISR_OFFSET);
75 NVIC_SetPendingIRQ(DIRECT_ISR_OFFSET);
76
77 /*
78 * Instruction barriers to make sure the NVIC IRQ is
79 * set to pending state before 'test_flag' is checked.
80 */
81 barrier_dsync_fence_full();
82 barrier_isync_fence_full();
83
84 /* Confirm test flag is set by the dynamic direct ISR handler. */
85 post_flag = test_flag;
86 zassert_true(post_flag == 2, "Test flag not set by ISR1\n");
87 }
88