1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <string.h>
9
10 #include <hal/nrf_egu.h>
11 #include <hal/nrf_ppi.h>
12 #include <hal/nrf_timer.h>
13
14 #include <zephyr/ztest.h>
15
16 #define TIMER_NO 2
17 #define TIMER_INSTANCE NRFX_CONCAT_2(NRF_TIMER, TIMER_NO)
18 #define TIMER_IRQ TIMER2_IRQn
19 #define TIMER_INT NRF_TIMER_INT_COMPARE0_MASK
20 #define TIMER_PRIORITY 5
21 #define TIMER_DELAY_TICKS 100
22 #define EGU_DELAY_USEC 200
23
24 struct timer_isr_context {
25 unsigned int egu_channel;
26 };
27
28 #define NRF_NEGUs 6
29 #define NRF_NEGU_NEVENTS 16
30 static const NRF_EGU_Type *EGU[NRF_NEGUs] = {
31 NRF_EGU0, NRF_EGU1, NRF_EGU2, NRF_EGU3, NRF_EGU4, NRF_EGU5
32 };
33
ZTEST(nrf_egu_tests,test_channels_count)34 ZTEST(nrf_egu_tests, test_channels_count)
35 {
36 for (int i = 0; i < NRF_NEGUs; i++) {
37 zassert_equal(16, nrf_egu_channel_count(EGU[i]),
38 "NRF_EGU%d incorrect number of channels", i);
39 }
40 }
41
ZTEST(nrf_egu_tests,test_task_address_get)42 ZTEST(nrf_egu_tests, test_task_address_get)
43 {
44 nrf_egu_task_t egu_tasks[NRF_NEGU_NEVENTS] = {
45 NRF_EGU_TASK_TRIGGER0, NRF_EGU_TASK_TRIGGER1, NRF_EGU_TASK_TRIGGER2,
46 NRF_EGU_TASK_TRIGGER3, NRF_EGU_TASK_TRIGGER4, NRF_EGU_TASK_TRIGGER5,
47 NRF_EGU_TASK_TRIGGER6, NRF_EGU_TASK_TRIGGER7, NRF_EGU_TASK_TRIGGER8,
48 NRF_EGU_TASK_TRIGGER9, NRF_EGU_TASK_TRIGGER10, NRF_EGU_TASK_TRIGGER11,
49 NRF_EGU_TASK_TRIGGER12, NRF_EGU_TASK_TRIGGER13, NRF_EGU_TASK_TRIGGER14,
50 NRF_EGU_TASK_TRIGGER15
51 };
52
53 for (int i = 0; i < NRF_NEGUs; i++) {
54 for (int j = 0; j < NRF_NEGU_NEVENTS; j++) {
55 zassert_equal((size_t)&EGU[i]->TASKS_TRIGGER[j],
56 nrf_egu_task_address_get(EGU[i], egu_tasks[j]),
57 "NRF_EGU_%i incorrect address of task trigger %i", i, j);
58 }
59 }
60 }
61
ZTEST(nrf_egu_tests,test_event_address_get)62 ZTEST(nrf_egu_tests, test_event_address_get)
63 {
64 nrf_egu_event_t egu_events[NRF_NEGU_NEVENTS] = {
65 NRF_EGU_EVENT_TRIGGERED0, NRF_EGU_EVENT_TRIGGERED1,
66 NRF_EGU_EVENT_TRIGGERED2, NRF_EGU_EVENT_TRIGGERED3,
67 NRF_EGU_EVENT_TRIGGERED4, NRF_EGU_EVENT_TRIGGERED5,
68 NRF_EGU_EVENT_TRIGGERED6, NRF_EGU_EVENT_TRIGGERED7,
69 NRF_EGU_EVENT_TRIGGERED8, NRF_EGU_EVENT_TRIGGERED9,
70 NRF_EGU_EVENT_TRIGGERED10, NRF_EGU_EVENT_TRIGGERED11,
71 NRF_EGU_EVENT_TRIGGERED12, NRF_EGU_EVENT_TRIGGERED13,
72 NRF_EGU_EVENT_TRIGGERED14, NRF_EGU_EVENT_TRIGGERED15
73 };
74
75 for (int i = 0; i < NRF_NEGUs; i++) {
76 for (int j = 0; j < NRF_NEGU_NEVENTS; j++) {
77 zassert_equal((size_t)&EGU[i]->EVENTS_TRIGGERED[j],
78 nrf_egu_event_address_get(EGU[i], egu_events[j]),
79 "NRF_EGU_%i incorrect address of event trigger %i", i, j);
80 }
81 }
82 }
83
ZTEST(nrf_egu_tests,test_channel_int_get)84 ZTEST(nrf_egu_tests, test_channel_int_get)
85 {
86 nrf_egu_int_mask_t egu_masks[NRF_NEGU_NEVENTS] = {
87 NRF_EGU_INT_TRIGGERED0, NRF_EGU_INT_TRIGGERED1, NRF_EGU_INT_TRIGGERED2,
88 NRF_EGU_INT_TRIGGERED3, NRF_EGU_INT_TRIGGERED4, NRF_EGU_INT_TRIGGERED5,
89 NRF_EGU_INT_TRIGGERED6, NRF_EGU_INT_TRIGGERED7, NRF_EGU_INT_TRIGGERED8,
90 NRF_EGU_INT_TRIGGERED9, NRF_EGU_INT_TRIGGERED10, NRF_EGU_INT_TRIGGERED11,
91 NRF_EGU_INT_TRIGGERED12, NRF_EGU_INT_TRIGGERED13, NRF_EGU_INT_TRIGGERED14,
92 NRF_EGU_INT_TRIGGERED15
93 };
94
95 for (int i = 0; i < NRF_NEGU_NEVENTS; i++) {
96 zassert_equal(egu_masks[i], nrf_egu_channel_int_get(i),
97 "Incorrect offset for channel %i", i);
98 }
99 }
100
101 struct SWI_trigger_assert_parameter {
102 bool triggered[EGU5_CH_NUM];
103 uint32_t call_count;
104 };
105
106 static struct SWI_trigger_assert_parameter event_triggered_flag;
107
SWI5_trigger_function(const void * param)108 void SWI5_trigger_function(const void *param)
109 {
110 event_triggered_flag.call_count++;
111 for (uint8_t i = 0; i < nrf_egu_channel_count(NRF_EGU5); i++) {
112 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
113
114 event_triggered_flag.triggered[i] = nrf_egu_event_check(NRF_EGU5, check_event);
115 if (event_triggered_flag.triggered[i]) {
116 nrf_egu_event_clear(NRF_EGU5, check_event);
117 }
118 }
119 }
120
ZTEST(nrf_egu_tests,test_task_trigger_not_int)121 ZTEST(nrf_egu_tests, test_task_trigger_not_int)
122 {
123 nrf_egu_int_disable(NRF_EGU5, NRF_EGU_INT_TRIGGERED1);
124 zassert_equal(0, nrf_egu_int_enable_check(NRF_EGU5, NRF_EGU_INT_TRIGGERED1),
125 "interrupt has not been disabled");
126 memset(&event_triggered_flag, 0, sizeof(event_triggered_flag));
127 irq_connect_dynamic(SWI5_EGU5_IRQn, 0, SWI5_trigger_function, NULL, BIT(0));
128 irq_enable(SWI5_EGU5_IRQn);
129 nrf_egu_task_t task_to_trigger = nrf_egu_trigger_task_get(0);
130
131 nrf_egu_task_trigger(NRF_EGU5, task_to_trigger);
132
133 k_busy_wait(1000);
134 irq_disable(SWI5_EGU5_IRQn);
135 nrf_egu_int_disable(NRF_EGU5, NRF_EGU_INT_TRIGGERED1);
136
137 zassert_equal(0, event_triggered_flag.call_count, "interrupt has been called");
138 for (int i = 0 ; i < NRF_NEGU_NEVENTS; i++) {
139 zassert_false(event_triggered_flag.triggered[i], "Event %i has been triggered", i);
140 }
141
142 zassert_true(nrf_egu_event_check(NRF_EGU5, nrf_egu_triggered_event_get(0)),
143 "event has not been triggered");
144 for (uint8_t i = 1; i < nrf_egu_channel_count(NRF_EGU5); i++) {
145 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
146
147 zassert_false(nrf_egu_event_check(NRF_EGU5, check_event),
148 "event %d has been triggered, but it shouldn't", i);
149 }
150 }
151
ZTEST(nrf_egu_tests,test_task_trigger)152 ZTEST(nrf_egu_tests, test_task_trigger)
153 {
154 nrf_egu_int_enable(NRF_EGU5, NRF_EGU_INT_TRIGGERED0);
155 zassert_equal(NRF_EGU_INT_TRIGGERED0,
156 nrf_egu_int_enable_check(NRF_EGU5, NRF_EGU_INT_TRIGGERED0),
157 "failed to enable interrupt");
158 memset(&event_triggered_flag, 0, sizeof(event_triggered_flag));
159 irq_connect_dynamic(SWI5_EGU5_IRQn, 0, SWI5_trigger_function, NULL, BIT(0));
160 irq_enable(SWI5_EGU5_IRQn);
161 nrf_egu_task_t task_to_trigger = nrf_egu_trigger_task_get(0);
162
163 nrf_egu_task_trigger(NRF_EGU5, task_to_trigger);
164
165 k_busy_wait(1000);
166 irq_disable(SWI5_EGU5_IRQn);
167 nrf_egu_int_disable(NRF_EGU5, NRF_EGU_INT_TRIGGERED0);
168
169 zassert_equal(1, event_triggered_flag.call_count, "zassert failed count = %d ",
170 event_triggered_flag.call_count);
171
172 zassert_true(event_triggered_flag.triggered[0], "Event 0 has not been triggered");
173 for (int i = 1 ; i < NRF_NEGU_NEVENTS; i++) {
174 zassert_false(event_triggered_flag.triggered[i], "Event %i has been triggered", i);
175 }
176
177 for (uint8_t i = 0; i < nrf_egu_channel_count(NRF_EGU5); i++) {
178 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
179
180 zassert_false(nrf_egu_event_check(NRF_EGU5, check_event),
181 "event %d has been triggered, but it shouldn't", i);
182 }
183 }
184
ZTEST(nrf_egu_tests,test_task_configure_not_trigger)185 ZTEST(nrf_egu_tests, test_task_configure_not_trigger)
186 {
187 nrf_egu_int_mask_t egu_int_mask = nrf_egu_channel_int_get(0);
188
189 zassert_equal(NRF_EGU_INT_TRIGGERED0, egu_int_mask, "interrupt mask is invalid");
190 nrf_egu_int_enable(NRF_EGU5, egu_int_mask);
191 zassert_equal(egu_int_mask, nrf_egu_int_enable_check(NRF_EGU5, egu_int_mask),
192 "failed to enable interrupt");
193 memset(&event_triggered_flag, 0, sizeof(event_triggered_flag));
194 irq_connect_dynamic(SWI5_EGU5_IRQn, 0, SWI5_trigger_function, NULL, BIT(0));
195 irq_enable(SWI5_EGU5_IRQn);
196
197 k_busy_wait(1000);
198 irq_disable(SWI5_EGU5_IRQn);
199 nrf_egu_int_disable(NRF_EGU5, egu_int_mask);
200
201 zassert_equal(0, event_triggered_flag.call_count, "interrupt has been called");
202 for (int i = 0 ; i < NRF_NEGU_NEVENTS; i++) {
203 zassert_false(event_triggered_flag.triggered[i], "Event %i has been triggered", i);
204 }
205
206 for (uint8_t i = 0; i < nrf_egu_channel_count(NRF_EGU5); i++) {
207 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
208
209 zassert_false(nrf_egu_event_check(NRF_EGU5, check_event),
210 "event %d has been triggered, but it shouldn't", i);
211 }
212 }
213
timer_isr(const void * timer_isr_ctx)214 static void timer_isr(const void *timer_isr_ctx)
215 {
216 struct timer_isr_context *ctx = (struct timer_isr_context *)timer_isr_ctx;
217
218 if (ctx) {
219 nrf_egu_task_trigger(NRF_EGU5, nrf_egu_trigger_task_get(ctx->egu_channel));
220 }
221
222 nrf_timer_event_clear(TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0);
223 nrf_timer_int_disable(TIMER_INSTANCE, TIMER_INT);
224 }
225
ZTEST(nrf_egu_tests,test_trigger_from_another_irq)226 ZTEST(nrf_egu_tests, test_trigger_from_another_irq)
227 {
228 uint32_t call_cnt_expected = event_triggered_flag.call_count + 1;
229 static struct timer_isr_context timer_isr_ctx = {
230 .egu_channel = 0
231 };
232
233 /* Timer cleanup */
234 nrf_timer_event_clear(TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0);
235 nrf_timer_task_trigger(TIMER_INSTANCE, NRF_TIMER_TASK_STOP);
236 nrf_timer_task_trigger(TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR);
237
238 /* Timer setup */
239 irq_connect_dynamic(TIMER_IRQ, TIMER_PRIORITY, timer_isr, &timer_isr_ctx, 0);
240 irq_enable(TIMER_IRQ);
241
242 nrf_timer_mode_set(TIMER_INSTANCE, NRF_TIMER_MODE_TIMER);
243 nrf_timer_bit_width_set(TIMER_INSTANCE, TIMER_BITMODE_BITMODE_16Bit);
244 nrf_timer_prescaler_set(TIMER_INSTANCE,
245 NRF_TIMER_PRESCALER_CALCULATE(
246 NRF_TIMER_BASE_FREQUENCY_GET(TIMER_INSTANCE),
247 NRFX_MHZ_TO_HZ(1)));
248 nrf_timer_cc_set(TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, TIMER_DELAY_TICKS);
249 nrf_timer_int_enable(TIMER_INSTANCE, TIMER_INT);
250
251 /* EGU setup */
252 nrf_egu_int_enable(NRF_EGU5, NRF_EGU_INT_TRIGGERED0);
253 irq_connect_dynamic(SWI5_EGU5_IRQn, 0, SWI5_trigger_function, NULL, BIT(0));
254 irq_enable(SWI5_EGU5_IRQn);
255
256 nrf_timer_task_trigger(TIMER_INSTANCE, NRF_TIMER_TASK_START);
257 k_busy_wait(EGU_DELAY_USEC);
258
259 zassert_equal(call_cnt_expected, event_triggered_flag.call_count,
260 "interrupt called unexpected number of times %d",
261 event_triggered_flag.call_count);
262 }
263
264 static struct SWI_trigger_assert_parameter SWI4_event_triggered_flag;
265
SWI4_trigger_function(const void * param)266 static void SWI4_trigger_function(const void *param)
267 {
268 for (uint8_t i = 0; i < nrf_egu_channel_count(NRF_EGU4); i++) {
269 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
270
271 SWI4_event_triggered_flag.triggered[i] = nrf_egu_event_check(NRF_EGU4, check_event);
272 if (SWI4_event_triggered_flag.triggered[i]) {
273 nrf_egu_event_clear(NRF_EGU4, check_event);
274 }
275 }
276 }
277
ZTEST(nrf_egu_tests,test_trigger_by_PPI)278 ZTEST(nrf_egu_tests, test_trigger_by_PPI)
279 {
280 nrf_ppi_channel_enable(NRF_PPI, NRF_PPI_CHANNEL0);
281 nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL0,
282 nrf_egu_event_address_get(NRF_EGU3, NRF_EGU_EVENT_TRIGGERED0),
283 nrf_egu_task_address_get(NRF_EGU4, NRF_EGU_TASK_TRIGGER0));
284
285 memset(&SWI4_event_triggered_flag, 0, sizeof(SWI4_event_triggered_flag));
286 irq_connect_dynamic(SWI4_EGU4_IRQn, 0, SWI4_trigger_function, NULL, BIT(0));
287
288 /* configure egu4 */
289 nrf_egu_int_enable(NRF_EGU4, NRF_EGU_INT_TRIGGERED0);
290 irq_enable(SWI4_EGU4_IRQn);
291
292 /* trigger egu3 */
293 nrf_egu_task_trigger(NRF_EGU3, NRF_EGU_TASK_TRIGGER0);
294
295 k_busy_wait(1000);
296 irq_disable(SWI4_EGU4_IRQn);
297 nrf_egu_int_disable(NRF_EGU4, NRF_EGU_INT_TRIGGERED0);
298
299 /* EGU3 should forward the trigger to EGU4 via PPI, and SWI4 IRQ is expected */
300 /* IRQ for EGU3 is not enabled */
301
302 zassert_true(SWI4_event_triggered_flag.triggered[0], "Event 0 has not been triggered");
303 for (int i = 1 ; i < NRF_NEGU_NEVENTS; i++) {
304 zassert_false(SWI4_event_triggered_flag.triggered[i],
305 "Event %i has been triggered", i);
306 }
307
308 for (uint8_t i = 0; i < nrf_egu_channel_count(NRF_EGU4); i++) {
309 const nrf_egu_event_t check_event = nrf_egu_triggered_event_get(i);
310
311 zassert_false(nrf_egu_event_check(NRF_EGU4, check_event),
312 "event %d has been triggered, but it shouldn't", i);
313 }
314 }
315
test_clean_egu(void * ignored)316 static void test_clean_egu(void *ignored)
317 {
318 ARG_UNUSED(ignored);
319 memset(NRF_EGU5, 0, sizeof(*NRF_EGU5));
320 }
321
322 ZTEST_SUITE(nrf_egu_tests, NULL, NULL, test_clean_egu, test_clean_egu, NULL);
323