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