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