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 static volatile int test_flag;
13
arm_zero_latency_isr_handler(const void * args)14 void arm_zero_latency_isr_handler(const void *args)
15 {
16 ARG_UNUSED(args);
17
18 test_flag = 1;
19 }
20
ZTEST(arm_irq_advanced_features,test_arm_zero_latency_irqs)21 ZTEST(arm_irq_advanced_features, test_arm_zero_latency_irqs)
22 {
23
24 if (!IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS)) {
25 TC_PRINT("Skipped (Cortex-M Mainline only)\n");
26
27 return;
28 }
29
30 /* Determine an NVIC IRQ line that is not currently in use. */
31 int i, key;
32 int init_flag, post_flag;
33
34 init_flag = test_flag;
35
36 zassert_false(init_flag, "Test flag not initialized to zero\n");
37
38 for (i = CONFIG_NUM_IRQS - 1; i >= 0; i--) {
39 if (NVIC_GetEnableIRQ(i) == 0) {
40 /*
41 * Interrupts configured statically with IRQ_CONNECT(.)
42 * are automatically enabled. NVIC_GetEnableIRQ()
43 * returning false, here, implies that the IRQ line is
44 * either not implemented or it is not enabled, thus,
45 * currently not in use by Zephyr.
46 */
47
48 /* Set the NVIC line to pending. */
49 NVIC_SetPendingIRQ(i);
50
51 if (NVIC_GetPendingIRQ(i)) {
52 /*
53 * If the NVIC line is pending, it is
54 * guaranteed that it is implemented; clear the
55 * line.
56 */
57 NVIC_ClearPendingIRQ(i);
58
59 if (!NVIC_GetPendingIRQ(i)) {
60 /*
61 * If the NVIC line can be successfully
62 * un-pended, it is guaranteed that it
63 * can be used for software interrupt
64 * triggering. Return the NVIC line
65 * number.
66 */
67 break;
68 }
69 }
70 }
71 }
72
73 zassert_true(i >= 0,
74 "No available IRQ line to configure as zero-latency\n");
75
76 TC_PRINT("Available IRQ line: %u\n", i);
77
78 /* Configure the available IRQ line as zero-latency. */
79
80 arch_irq_connect_dynamic(i, 0 /* Unused */,
81 arm_zero_latency_isr_handler,
82 NULL,
83 IRQ_ZERO_LATENCY);
84
85 NVIC_ClearPendingIRQ(i);
86 NVIC_EnableIRQ(i);
87
88 /* Lock interrupts */
89 key = irq_lock();
90
91 /* Set the zero-latency IRQ to pending state. */
92 NVIC_SetPendingIRQ(i);
93
94 /*
95 * Instruction barriers to make sure the NVIC IRQ is
96 * set to pending state before 'test_flag' is checked.
97 */
98 barrier_dsync_fence_full();
99 barrier_isync_fence_full();
100
101 /* Confirm test flag is set by the zero-latency ISR handler. */
102 post_flag = test_flag;
103 zassert_true(post_flag == 1, "Test flag not set by ISR\n");
104
105 irq_unlock(key);
106 }
107
108 /**
109 * @}
110 */
111