1 /*
2 * Copyright (c) 2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8 #include <zephyr/ztest_error_hook.h>
9
10 /* Macro declarations */
11
12 #define DELAY K_MSEC(50)
13 #define SHORT_TIMEOUT K_MSEC(100)
14 #define LONG_TIMEOUT K_MSEC(1000)
15
16 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
17
18 static struct k_thread treceiver;
19 static struct k_thread textra1;
20 static struct k_thread textra2;
21
22 static K_THREAD_STACK_DEFINE(sreceiver, STACK_SIZE);
23 static K_THREAD_STACK_DEFINE(sextra1, STACK_SIZE);
24 static K_THREAD_STACK_DEFINE(sextra2, STACK_SIZE);
25
26 static K_EVENT_DEFINE(test_event);
27 static K_EVENT_DEFINE(sync_event);
28 static struct k_event init_event;
29 static struct k_event deliver_event;
30
31 static K_SEM_DEFINE(receiver_sem, 0, 1);
32 static K_SEM_DEFINE(sync_sem, 0, 1);
33
34 volatile static uint32_t test_events;
35
36 /**
37 * @ingroup kernel_event_tests
38 * @{
39 */
40
entry_extra1(void * p1,void * p2,void * p3)41 static void entry_extra1(void *p1, void *p2, void *p3)
42 {
43 uint32_t events;
44
45 events = k_event_wait_all(&sync_event, 0x33, true, K_FOREVER);
46
47 k_event_post(&test_event, events);
48 }
49
entry_extra2(void * p1,void * p2,void * p3)50 static void entry_extra2(void *p1, void *p2, void *p3)
51 {
52 uint32_t events;
53
54 events = k_event_wait(&sync_event, 0x3300, true, K_FOREVER);
55
56 k_event_post(&test_event, events);
57 }
58
59 /**
60 * Test the k_event_init() API.
61 *
62 * This is a white-box test to verify that the k_event_init() API initializes
63 * the fields of a k_event structure as expected.
64 */
65
ZTEST(sys_events,test_k_event_init)66 ZTEST(sys_events, test_k_event_init)
67 {
68 k_event_init(&init_event);
69
70 zassert_true(init_event.events == 0);
71 }
72
receive_existing_events(void)73 static void receive_existing_events(void)
74 {
75 /*
76 * Sync point 1-1 : test_event contains events 0x1234.
77 * Test for events 0x2448 (no waiting)--expect an error
78 */
79
80 k_sem_take(&sync_sem, K_FOREVER);
81 test_events = k_event_wait(&test_event, 0x2448, false, K_NO_WAIT);
82 k_sem_give(&receiver_sem);
83
84 /*
85 * Sync point 1-2 : test_event still contains event 0x1234.
86 * Test for events 0x2448 (with waiting)--expect an error
87 */
88
89 k_sem_take(&sync_sem, K_FOREVER);
90 test_events = k_event_wait(&test_event, 0x2448, false, SHORT_TIMEOUT);
91 k_sem_give(&receiver_sem);
92
93 /*
94 * Sync point 1-3: test_event still contains event 0x1234.
95 * Test for events 0x1235 (no waiting)--expect an error
96 */
97
98 k_sem_take(&sync_sem, K_FOREVER);
99 test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
100 k_sem_give(&receiver_sem);
101
102 /*
103 * Sync point 1-4: test_event still contains event 0x1234.
104 * Test for events 0x1235 (no waiting)--expect an error
105 */
106
107 k_sem_take(&sync_sem, K_FOREVER);
108 test_events = k_event_wait_all(&test_event, 0x1235, false, K_NO_WAIT);
109 k_sem_give(&receiver_sem);
110
111 /*
112 * Sync point 1-5: test_event still contains event 0x1234.
113 * Test for events 0x0235. Expect 0x0234 to be returned.
114 */
115
116 k_sem_take(&sync_sem, K_FOREVER);
117 test_events = k_event_wait(&test_event, 0x0235, false, K_NO_WAIT);
118 k_sem_give(&receiver_sem);
119
120 /*
121 * Sync point 1-6: test_event still contains event 0x1234.
122 * Test for events 0x1234. Expect 0x1234 to be returned.
123 */
124
125 k_sem_take(&sync_sem, K_FOREVER);
126 test_events = k_event_wait_all(&test_event, 0x1234, false, K_NO_WAIT);
127 k_sem_give(&receiver_sem);
128 }
129
reset_on_receive(void)130 static void reset_on_receive(void)
131 {
132 /* Sync point 2-1 - with reset */
133
134 k_sem_take(&sync_sem, K_FOREVER);
135 test_events = k_event_wait_all(&test_event, 0x1234, true,
136 SHORT_TIMEOUT);
137 k_sem_give(&receiver_sem);
138
139 /* Sync point 2-2 - with reset */
140
141 k_sem_take(&sync_sem, K_FOREVER);
142 test_events = k_event_wait(&test_event, 0x120000, true, SHORT_TIMEOUT);
143 k_sem_give(&receiver_sem);
144
145 /* Sync point 2-3 - with reset */
146
147 k_sem_take(&sync_sem, K_FOREVER);
148 test_events = k_event_wait_all(&test_event, 0x248001, true,
149 SHORT_TIMEOUT);
150 k_sem_give(&receiver_sem);
151
152 /* Sync point 2-4 - with reset */
153
154 k_sem_take(&sync_sem, K_FOREVER);
155 test_events = k_event_wait(&test_event, 0x123458, true,
156 SHORT_TIMEOUT);
157 k_sem_give(&receiver_sem);
158 }
159
160 /**
161 * receiver helper task
162 */
163
receiver(void * p1,void * p2,void * p3)164 static void receiver(void *p1, void *p2, void *p3)
165 {
166 receive_existing_events();
167
168 reset_on_receive();
169 }
170
171 /**
172 * Works with receive_existing_events() to test the waiting for events
173 * when some events have already been sent. No additional events are sent
174 * to the event object during this block of testing.
175 */
test_receive_existing_events(void)176 static void test_receive_existing_events(void)
177 {
178 int rv;
179
180 /*
181 * Sync point 1-1.
182 * K_NO_WAIT, k_event_wait(), no matches
183 */
184
185 k_sem_give(&sync_sem);
186 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
187 zassert_true(rv == 0);
188 zassert_true(test_events == 0);
189
190 /*
191 * Sync point 1-2.
192 * Short timeout, k_event_wait(), no expected matches
193 */
194
195 k_sem_give(&sync_sem);
196 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
197 zassert_true(rv == 0);
198 zassert_true(test_events == 0);
199
200 /*
201 * Sync point 1-3.
202 * K_NO_WAIT, k_event_wait_all(), incomplete match
203 */
204
205 k_sem_give(&sync_sem);
206 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
207 zassert_true(rv == 0);
208 zassert_true(test_events == 0);
209
210 /*
211 * Sync point 1-4.
212 * Short timeout, k_event_wait_all(), incomplete match
213 */
214
215 k_sem_give(&sync_sem);
216 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
217 zassert_true(rv == 0);
218 zassert_true(test_events == 0);
219
220 /*
221 * Sync point 1-5.
222 * Short timeout, k_event_wait_all(), incomplete match
223 */
224
225 k_sem_give(&sync_sem);
226 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
227 zassert_true(rv == 0);
228 zassert_true(test_events == 0x234);
229
230 /*
231 * Sync point 1-6.
232 * Short timeout, k_event_wait_all(), incomplete match
233 */
234
235 k_sem_give(&sync_sem);
236 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
237 zassert_true(rv == 0);
238 zassert_true(test_events == 0x1234);
239 }
240
241 /**
242 * Works with reset_on_receive() to verify that the events stored in the
243 * event object are reset at the appropriate times.
244 */
245
test_reset_on_receive(void)246 static void test_reset_on_receive(void)
247 {
248 int rv;
249
250 /*
251 * Sync point 2-1. Clear events before receive.
252 * Short timeout, k_event_wait_all(), incomplete match
253 */
254
255 k_sem_give(&sync_sem);
256 k_sleep(DELAY); /* Give receiver thread time to run */
257 k_event_post(&test_event, 0x123);
258 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
259 zassert_true(rv == 0);
260 zassert_true(test_events == 0);
261 zassert_true(test_event.events == 0x123);
262
263 /*
264 * Sync point 2-2. Clear events before receive.
265 * Short timeout, k_event_wait(), no matches
266 */
267
268 k_sem_give(&sync_sem);
269 k_sleep(DELAY);
270 k_event_post(&test_event, 0x248);
271 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
272 zassert_true(rv == 0);
273 zassert_true(test_events == 0);
274 zassert_true(test_event.events == 0x248);
275
276 /*
277 * Sync point 2-3. Clear events before receive.
278 * Short timeout, k_event_wait_all(), complete match
279 */
280
281 k_sem_give(&sync_sem);
282 k_sleep(DELAY);
283 k_event_post(&test_event, 0x248021);
284 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
285 zassert_true(rv == 0);
286 zassert_true(test_events == 0x248001);
287 zassert_true(test_event.events == 0x248021);
288
289 /*
290 * Sync point 2-4. Clear events before receive.
291 * Short timeout, k_event_wait(), partial match
292 */
293
294 k_sem_give(&sync_sem);
295 k_sleep(DELAY);
296 k_event_post(&test_event, 0x123456);
297 rv = k_sem_take(&receiver_sem, LONG_TIMEOUT);
298 zassert_true(rv == 0);
299 zassert_true(test_events == 0x123450);
300 zassert_true(test_event.events == 0x123456);
301
302 k_event_set(&test_event, 0x0); /* Clear events */
303
304 k_sem_give(&sync_sem);
305 }
306
test_wake_multiple_threads(void)307 void test_wake_multiple_threads(void)
308 {
309 uint32_t events;
310
311 /*
312 * The extra threads are expected to be waiting on <sync_event>
313 * Wake them both up.
314 */
315
316 k_event_set(&sync_event, 0xfff);
317
318 /*
319 * The extra threads send back the events they received. Wait
320 * for all of them.
321 */
322
323 events = k_event_wait_all(&test_event, 0x333, false, SHORT_TIMEOUT);
324
325 zassert_true(events == 0x333);
326 }
327
328 /**
329 * Test basic k_event_post() and k_event_set() APIs.
330 *
331 * Tests the basic k_event_post() and k_event_set() API. This does not
332 * involve waking or receiving events.
333 */
334
ZTEST(sys_events,test_event_deliver)335 ZTEST(sys_events, test_event_deliver)
336 {
337 uint32_t events;
338
339 k_event_init(&deliver_event);
340
341 zassert_true(deliver_event.events == 0);
342
343 /*
344 * Verify k_event_post() and k_event_set() update the
345 * events stored in the deliver_event object as expected.
346 */
347
348 events = 0xAAAA;
349 k_event_post(&deliver_event, events);
350 zassert_true(deliver_event.events == events);
351
352 events |= 0x55555ABC;
353 k_event_post(&deliver_event, events);
354 zassert_true(deliver_event.events == events);
355
356 events = 0xAAAA0000;
357 k_event_set(&deliver_event, events);
358 zassert_true(deliver_event.events == events);
359 }
360
361 /**
362 * Test delivery and reception of events.
363 *
364 * Testing both the delivery and reception of events involves the use of
365 * multiple threads and uses the following event related APIs:
366 * k_event_post(), k_event_set(), k_event_wait() and k_event_wait_all().
367 */
368
ZTEST(sys_events,test_event_receive)369 ZTEST(sys_events, test_event_receive)
370 {
371
372 /* Create helper threads */
373
374 k_event_set(&test_event, 0x1234);
375
376 (void) k_thread_create(&treceiver, sreceiver, STACK_SIZE,
377 receiver, NULL, NULL, NULL,
378 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
379
380 (void) k_thread_create(&textra1, sextra1, STACK_SIZE,
381 entry_extra1, NULL, NULL, NULL,
382 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
383
384 (void) k_thread_create(&textra2, sextra2, STACK_SIZE,
385 entry_extra2, NULL, NULL, NULL,
386 K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
387
388 test_receive_existing_events();
389
390 test_reset_on_receive();
391
392 test_wake_multiple_threads();
393 }
394
sys_events_setup(void)395 void *sys_events_setup(void)
396 {
397 k_thread_access_grant(k_current_get(), &treceiver, &textra1, &textra2,
398 &test_event, &sync_event,
399 &init_event, &deliver_event,
400 &receiver_sem, &sync_sem);
401
402 return NULL;
403 }
404
405 /**
406 * @}
407 */
408 ZTEST_SUITE(sys_events, NULL, sys_events_setup,
409 ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
410