1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/types.h>
10 
11 struct timer_data {
12 	int expire_cnt;
13 	int stop_cnt;
14 	int64_t timestamp;
15 };
16 
17 #define DURATION 100
18 #define PERIOD 50
19 #define EXPIRE_TIMES 4
20 #define WITHIN_ERROR(var, target, epsilon) (llabs((int64_t) ((target) - (var))) <= (epsilon))
21 
22 /* ms can be converted precisely to ticks only when a ms is exactly
23  * represented by an integral number of ticks.  If the conversion is
24  * not precise, then the reverse conversion of a difference in ms can
25  * end up being off by a tick depending on the relative error between
26  * the first and second ms conversion, and we need to adjust the
27  * tolerance interval.
28  */
29 #define INEXACT_MS_CONVERT ((CONFIG_SYS_CLOCK_TICKS_PER_SEC % MSEC_PER_SEC) != 0)
30 
31 #if CONFIG_NRF_RTC_TIMER
32 /* On Nordic SOCs one or both of the tick and busy-wait clocks may
33  * derive from sources that have slews that sum to +/- 13%.
34  */
35 #define BUSY_TICK_SLEW_PPM 130000U
36 #else
37 /* On other platforms assume the clocks are perfectly aligned. */
38 #define BUSY_TICK_SLEW_PPM 0U
39 #endif
40 #define PPM_DIVISOR 1000000U
41 
42 /* If the tick clock is faster or slower than the busywait clock the
43  * remaining time for a partially elapsed timer in ticks will be
44  * larger or smaller than expected by a value that depends on the slew
45  * between the two clocks.  Produce a maximum error for a given
46  * duration in microseconds.
47  */
48 #define BUSY_SLEW_THRESHOLD_TICKS(_us)					\
49 	k_us_to_ticks_ceil32((_us) * (uint64_t)BUSY_TICK_SLEW_PPM	\
50 			     / PPM_DIVISOR)
51 
52 static void duration_expire(struct k_timer *timer);
53 static void duration_stop(struct k_timer *timer);
54 
55 /** TESTPOINT: init timer via K_TIMER_DEFINE */
56 K_TIMER_DEFINE(ktimer, duration_expire, duration_stop);
57 
58 static struct k_timer duration_timer;
59 static struct k_timer period0_timer;
60 static struct k_timer expire_timer;
61 static struct k_timer sync_timer;
62 static struct k_timer periodicity_timer;
63 static struct k_timer status_timer;
64 static struct k_timer status_anytime_timer;
65 static struct k_timer status_sync_timer;
66 static struct k_timer remain_timer;
67 
68 static ZTEST_BMEM struct timer_data tdata;
69 
70 #define TIMER_ASSERT(exp, tmr)			 \
71 	do {					 \
72 		if (!(exp)) {			 \
73 			k_timer_stop(tmr);	 \
74 			zassert_true(exp); \
75 		}				 \
76 	} while (0)
77 
init_timer_data(void)78 static void init_timer_data(void)
79 {
80 	tdata.expire_cnt = 0;
81 	tdata.stop_cnt = 0;
82 
83 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
84 		k_usleep(1); /* align to tick */
85 	}
86 
87 	tdata.timestamp = k_uptime_get();
88 }
89 
interval_check(int64_t interval,int64_t desired)90 static bool interval_check(int64_t interval, int64_t desired)
91 {
92 	int64_t slop = INEXACT_MS_CONVERT ? 1 : 0;
93 
94 	/* Tickless kernels will advance time inside of an ISR, so it
95 	 * is always possible (especially with high tick rates and
96 	 * slow CPUs) for us to arrive at the uptime check above too
97 	 * late to see a full period elapse before the next period.
98 	 * We can alias at both sides of the interval, so two
99 	 * one-ticks deltas (NOT one two-tick delta!)
100 	 */
101 	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
102 		slop += 2 * k_ticks_to_ms_ceil32(1);
103 	}
104 
105 	if (!WITHIN_ERROR(interval, desired, slop)) {
106 		return false;
107 	}
108 
109 	return true;
110 }
111 
112 /* entry routines */
duration_expire(struct k_timer * timer)113 static void duration_expire(struct k_timer *timer)
114 {
115 	/** TESTPOINT: expire function */
116 	int64_t interval = k_uptime_delta(&tdata.timestamp);
117 
118 	tdata.expire_cnt++;
119 	if (tdata.expire_cnt == 1) {
120 		TIMER_ASSERT(interval_check(interval, DURATION), timer);
121 	} else {
122 		TIMER_ASSERT(interval_check(interval, PERIOD), timer);
123 	}
124 
125 	if (tdata.expire_cnt >= EXPIRE_TIMES) {
126 		k_timer_stop(timer);
127 	}
128 }
129 
duration_stop(struct k_timer * timer)130 static void duration_stop(struct k_timer *timer)
131 {
132 	tdata.stop_cnt++;
133 }
134 
period0_expire(struct k_timer * timer)135 static void period0_expire(struct k_timer *timer)
136 {
137 	tdata.expire_cnt++;
138 }
139 
status_expire(struct k_timer * timer)140 static void status_expire(struct k_timer *timer)
141 {
142 	/** TESTPOINT: status get upon timer expired */
143 	TIMER_ASSERT(k_timer_status_get(timer) == 1, timer);
144 	/** TESTPOINT: remaining get upon timer expired */
145 	TIMER_ASSERT(k_timer_remaining_get(timer) >= PERIOD, timer);
146 
147 	if (tdata.expire_cnt >= EXPIRE_TIMES) {
148 		k_timer_stop(timer);
149 	}
150 }
151 
busy_wait_ms(int32_t ms)152 static void busy_wait_ms(int32_t ms)
153 {
154 	k_busy_wait(ms*1000);
155 }
156 
status_stop(struct k_timer * timer)157 static void status_stop(struct k_timer *timer)
158 {
159 	/** TESTPOINT: remaining get upon timer stopped */
160 	TIMER_ASSERT(k_timer_remaining_get(timer) == 0, timer);
161 }
162 
163 /**
164  * @brief Tests for the Timer kernel object
165  * @defgroup kernel_timer_tests Timer
166  * @ingroup all_tests
167  * @{
168  * @}
169  */
170 
171 /**
172  * @brief Test duration and period of Timer
173  *
174  * Validates initial duration and period of timer.
175  *
176  * It initializes the timer with k_timer_init(), then starts the timer
177  * using k_timer_start() with specific initial duration and period.
178  * Stops the timer using k_timer_stop() and checks for proper completion
179  * of duration and period.
180  *
181  * @ingroup kernel_timer_tests
182  *
183  * @see k_timer_init(), k_timer_start(), k_timer_stop(), k_uptime_get(),
184  * k_busy_wait()
185  */
ZTEST_USER(timer_api,test_timer_duration_period)186 ZTEST_USER(timer_api, test_timer_duration_period)
187 {
188 	init_timer_data();
189 	/** TESTPOINT: init timer via k_timer_init */
190 	k_timer_start(&duration_timer, K_MSEC(DURATION), K_MSEC(PERIOD));
191 	busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
192 	/** TESTPOINT: check expire and stop times */
193 	TIMER_ASSERT(tdata.expire_cnt == EXPIRE_TIMES, &duration_timer);
194 	TIMER_ASSERT(tdata.stop_cnt == 1, &duration_timer);
195 
196 	k_timer_start(&duration_timer, K_FOREVER, K_MSEC(PERIOD));
197 	TIMER_ASSERT(tdata.stop_cnt == 1, &duration_timer);
198 	/* cleanup environment */
199 	k_timer_stop(&duration_timer);
200 }
201 
202 /**
203  *
204  * @brief Test restart the timer
205  *
206  * @details Validates initial duration and period of timer. Start the timer with
207  * specific duration and period. Then starts the timer again, and check
208  * the status of timer.
209  *
210  * @ingroup kernel_timer_tests
211  *
212  * @see k_timer_init(), k_timer_start(), k_timer_stop, k_uptime_get(),
213  * k_busy_wait()
214  *
215  */
ZTEST_USER(timer_api,test_timer_restart)216 ZTEST_USER(timer_api, test_timer_restart)
217 {
218 	init_timer_data();
219 	k_timer_start(&status_anytime_timer, K_MSEC(DURATION),
220 		      K_MSEC(PERIOD));
221 	busy_wait_ms(DURATION + PERIOD * (EXPIRE_TIMES - 1) + PERIOD / 2);
222 
223 	/** TESTPOINT: restart the timer */
224 	k_timer_start(&status_anytime_timer, K_MSEC(DURATION),
225 		      K_MSEC(PERIOD));
226 	/* Restart timer, timer's status is reset to zero */
227 	TIMER_ASSERT(k_timer_status_get(&status_anytime_timer) == 0,
228 		     &status_anytime_timer);
229 
230 	/* cleanup environment */
231 	k_timer_stop(&status_anytime_timer);
232 }
233 
234 
235 /**
236  * @brief Test Timer with zero period value
237  *
238  * Validates initial timer duration, keeping timer period to zero.
239  * Basically, acting as one-shot timer.
240  * It initializes the timer with k_timer_init(), then starts the timer
241  * using k_timer_start() with specific initial duration and period as
242  * zero. Stops the timer using k_timer_stop() and checks for proper
243  * completion.
244  *
245  * @ingroup kernel_timer_tests
246  *
247  * @see k_timer_init(), k_timer_start(), k_timer_stop(), k_uptime_get(),
248  * k_busy_wait()
249  */
ZTEST_USER(timer_api,test_timer_period_0)250 ZTEST_USER(timer_api, test_timer_period_0)
251 {
252 	init_timer_data();
253 	/** TESTPOINT: set period 0 */
254 	k_timer_start(&period0_timer,
255 		      K_TICKS(k_ms_to_ticks_floor32(DURATION)
256 			      - BUSY_SLEW_THRESHOLD_TICKS(DURATION
257 							  * USEC_PER_MSEC)),
258 		      K_NO_WAIT);
259 	/* Need to wait at least 2 durations to ensure one-shot behavior. */
260 	busy_wait_ms(2 * DURATION + 1);
261 
262 	/** TESTPOINT: ensure it is one-shot timer */
263 	TIMER_ASSERT((tdata.expire_cnt == 1)
264 		     || (INEXACT_MS_CONVERT
265 			 && (tdata.expire_cnt == 0)), &period0_timer);
266 	TIMER_ASSERT(tdata.stop_cnt == 0, &period0_timer);
267 
268 	/* cleanup environment */
269 	k_timer_stop(&period0_timer);
270 }
271 
272 /**
273  * @brief Test Timer with K_FOREVER period value
274  *
275  * Validates initial timer duration, keeping timer period to K_FOREVER.
276  * Basically, acting as one-shot timer.
277  * It initializes the timer with k_timer_init(), then starts the timer
278  * using k_timer_start() with specific initial duration and period as
279  * zero. Stops the timer using k_timer_stop() and checks for proper
280  * completion.
281  *
282  * @ingroup kernel_timer_tests
283  *
284  * @see k_timer_init(), k_timer_start(), k_timer_stop(), k_uptime_get(),
285  * k_busy_wait()
286  */
ZTEST_USER(timer_api,test_timer_period_k_forever)287 ZTEST_USER(timer_api, test_timer_period_k_forever)
288 {
289 	init_timer_data();
290 	/** TESTPOINT: set period 0 */
291 	k_timer_start(
292 		&period0_timer,
293 		K_TICKS(k_ms_to_ticks_floor32(DURATION) -
294 			BUSY_SLEW_THRESHOLD_TICKS(DURATION * USEC_PER_MSEC)),
295 		K_FOREVER);
296 	tdata.timestamp = k_uptime_get();
297 
298 	/* Need to wait at least 2 durations to ensure one-shot behavior. */
299 	busy_wait_ms(2 * DURATION + 1);
300 
301 	/** TESTPOINT: ensure it is one-shot timer */
302 	TIMER_ASSERT((tdata.expire_cnt == 1) ||
303 			     (INEXACT_MS_CONVERT && (tdata.expire_cnt == 0)),
304 		     &period0_timer);
305 	TIMER_ASSERT(tdata.stop_cnt == 0, &period0_timer);
306 
307 	/* cleanup environment */
308 	k_timer_stop(&period0_timer);
309 }
310 
311 /**
312  * @brief Test Timer without any timer expiry callback function
313  *
314  * Validates timer without any expiry_fn(set to NULL). expiry_fn() is a
315  * function that is invoked each time the timer expires.
316  *
317  * It initializes the timer with k_timer_init(), then starts the timer
318  * using k_timer_start(). Stops the timer using k_timer_stop() and
319  * checks for expire_cnt to zero, as expiry_fn was not defined at all.
320  *
321  * @ingroup kernel_timer_tests
322  *
323  * @see k_timer_init(), k_timer_start(), k_timer_stop(), k_uptime_get(),
324  * k_busy_wait()
325  */
ZTEST_USER(timer_api,test_timer_expirefn_null)326 ZTEST_USER(timer_api, test_timer_expirefn_null)
327 {
328 	init_timer_data();
329 	/** TESTPOINT: expire function NULL */
330 	k_timer_start(&expire_timer, K_MSEC(DURATION), K_MSEC(PERIOD));
331 	busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
332 
333 	k_timer_stop(&expire_timer);
334 	/** TESTPOINT: expire handler is not invoked */
335 	TIMER_ASSERT(tdata.expire_cnt == 0, &expire_timer);
336 	/** TESTPOINT: stop handler is invoked */
337 	TIMER_ASSERT(tdata.stop_cnt == 1, &expire_timer);
338 
339 	/* cleanup environment */
340 	k_timer_stop(&expire_timer);
341 }
342 
343 /* Wait for the next expiration of an OS timer tick, to synchronize
344  * test start
345  */
tick_sync(void)346 static void tick_sync(void)
347 {
348 	k_timer_start(&sync_timer, K_NO_WAIT, K_MSEC(1));
349 	k_timer_status_sync(&sync_timer);
350 	k_timer_stop(&sync_timer);
351 }
352 
353 /**
354  * @brief Test to check timer periodicity
355  *
356  * Timer test to check for the predictability with which the timer
357  * expires depending on the period configured.
358  *
359  * It initializes the timer with k_timer_init(), then starts the timer
360  * using k_timer_start() with specific period. It resets the timer’s
361  * status to zero with k_timer_status_sync and identifies the delta
362  * between each timer expiry to check for the timer expiration period
363  * correctness. Finally, stops the timer using k_timer_stop().
364  *
365  * @ingroup kernel_timer_tests
366  *
367  * @see k_timer_init(), k_timer_start(), k_timer_status_sync(),
368  * k_timer_stop(), k_uptime_get(), k_uptime_delta()
369  */
ZTEST_USER(timer_api,test_timer_periodicity)370 ZTEST_USER(timer_api, test_timer_periodicity)
371 {
372 	uint64_t period_ms = k_ticks_to_ms_floor64(k_ms_to_ticks_ceil32(PERIOD));
373 	int64_t delta;
374 
375 	/* Start at a tick boundary, otherwise a tick expiring between
376 	 * the unlocked (and unlockable) start/uptime/sync steps below
377 	 * will throw off the math.
378 	 */
379 	tick_sync();
380 
381 	init_timer_data();
382 	/** TESTPOINT: set duration 0 */
383 	k_timer_start(&periodicity_timer, K_NO_WAIT, K_MSEC(PERIOD));
384 
385 	/* clear the expiration that would have happened due to
386 	 * whatever duration that was set. Since timer is likely
387 	 * to fire before call to k_timer_status_sync(), we have
388 	 * to synchronize twice to ensure that the timestamp will
389 	 * be fetched as soon as possible after timer firing.
390 	 */
391 	k_timer_status_sync(&periodicity_timer);
392 	k_timer_status_sync(&periodicity_timer);
393 	tdata.timestamp = k_uptime_get();
394 
395 	for (int i = 0; i < EXPIRE_TIMES; i++) {
396 		/** TESTPOINT: expired times returned by status sync */
397 		TIMER_ASSERT(k_timer_status_sync(&periodicity_timer) == 1,
398 			     &periodicity_timer);
399 
400 		delta = k_uptime_delta(&tdata.timestamp);
401 
402 		/** TESTPOINT: check if timer fired within 1ms of the
403 		 *  expected period (firing time).
404 		 *
405 		 * Please note, that expected firing time is not the
406 		 * one requested, as the kernel uses the ticks to manage
407 		 * time. The actual period will be equal to [tick time]
408 		 * multiplied by k_ms_to_ticks_ceil32(PERIOD).
409 		 *
410 		 * In the case of inexact conversion the delta will
411 		 * occasionally be one less than the expected number.
412 		 */
413 		TIMER_ASSERT(WITHIN_ERROR(delta, period_ms, 1)
414 			     || (INEXACT_MS_CONVERT
415 				 && (delta == period_ms - 1)),
416 			     &periodicity_timer);
417 	}
418 
419 	/* cleanup environment */
420 	k_timer_stop(&periodicity_timer);
421 }
422 
423 /**
424  * @brief Test Timer status and time remaining before next expiry
425  *
426  * Timer test to validate timer status and next trigger expiry time
427  *
428  * It initializes the timer with k_timer_init(), then starts the timer
429  * using k_timer_start() and checks for timer current status with
430  * k_timer_status_get() and remaining time before next expiry using
431  * k_timer_remaining_get(). Stops the timer using k_timer_stop().
432  *
433  * @ingroup kernel_timer_tests
434  *
435  * @see k_timer_init(), k_timer_start(), k_timer_status_get(),
436  * k_timer_remaining_get(), k_timer_stop()
437  */
ZTEST_USER(timer_api,test_timer_status_get)438 ZTEST_USER(timer_api, test_timer_status_get)
439 {
440 	init_timer_data();
441 	k_timer_start(&status_timer, K_MSEC(DURATION), K_MSEC(PERIOD));
442 	/** TESTPOINT: status get upon timer starts */
443 	TIMER_ASSERT(k_timer_status_get(&status_timer) == 0, &status_timer);
444 	/** TESTPOINT: remaining get upon timer starts */
445 	TIMER_ASSERT(k_timer_remaining_get(&status_timer) >= DURATION / 2,
446 		     &status_timer);
447 
448 	/* cleanup environment */
449 	k_timer_stop(&status_timer);
450 }
451 
452 /**
453  * @brief Test Timer status randomly after certain duration
454  *
455  * Validate timer status function using k_timer_status_get().
456  *
457  * It initializes the timer with k_timer_init(), then starts the timer
458  * using k_timer_start() with specific initial duration and period.
459  * Checks for timer status randomly after certain duration.
460  * Stops the timer using k_timer_stop().
461  *
462  * @ingroup kernel_timer_tests
463  *
464  * @see k_timer_init(), k_timer_start(), k_timer_status_get(),
465  * k_timer_stop(), k_busy_wait()
466  */
ZTEST_USER(timer_api,test_timer_status_get_anytime)467 ZTEST_USER(timer_api, test_timer_status_get_anytime)
468 {
469 	init_timer_data();
470 	k_timer_start(&status_anytime_timer, K_MSEC(DURATION),
471 		      K_MSEC(PERIOD));
472 	busy_wait_ms(DURATION + PERIOD * (EXPIRE_TIMES - 1) + PERIOD / 2);
473 
474 	/** TESTPOINT: status get at any time */
475 	TIMER_ASSERT(k_timer_status_get(&status_anytime_timer) == EXPIRE_TIMES,
476 		     &status_anytime_timer);
477 	busy_wait_ms(PERIOD);
478 	TIMER_ASSERT(k_timer_status_get(&status_anytime_timer) == 1,
479 		     &status_anytime_timer);
480 
481 	/* cleanup environment */
482 	k_timer_stop(&status_anytime_timer);
483 }
484 
485 /**
486  * @brief Test Timer thread synchronization
487  *
488  * Validate thread synchronization by blocking the calling thread until
489  * the timer expires.
490  *
491  * It initializes the timer with k_timer_init(), then starts the timer
492  * using k_timer_start() and checks timer status with
493  * k_timer_status_sync() for thread synchronization with expiry count.
494  * Stops the timer using k_timer_stop.
495  *
496  * @ingroup kernel_timer_tests
497  *
498  * @see k_timer_init(), k_timer_start(), k_timer_status_sync(),
499  * k_timer_stop()
500  */
ZTEST_USER(timer_api,test_timer_status_sync)501 ZTEST_USER(timer_api, test_timer_status_sync)
502 {
503 	init_timer_data();
504 	k_timer_start(&status_sync_timer, K_MSEC(DURATION), K_MSEC(PERIOD));
505 
506 	for (int i = 0; i < EXPIRE_TIMES; i++) {
507 		/** TESTPOINT: check timer not expire */
508 		TIMER_ASSERT(tdata.expire_cnt == i, &status_sync_timer);
509 		/** TESTPOINT: expired times returned by status sync */
510 		TIMER_ASSERT(k_timer_status_sync(&status_sync_timer) == 1,
511 			     &status_sync_timer);
512 		/** TESTPOINT: check timer not expire */
513 		TIMER_ASSERT(tdata.expire_cnt == (i + 1), &status_sync_timer);
514 	}
515 
516 	init_timer_data();
517 	k_timer_start(&status_sync_timer, K_MSEC(DURATION), K_MSEC(PERIOD));
518 	busy_wait_ms(PERIOD*2);
519 	zassert_true(k_timer_status_sync(&status_sync_timer));
520 
521 	/* cleanup environment */
522 	k_timer_stop(&status_sync_timer);
523 	zassert_false(k_timer_status_sync(&status_sync_timer));
524 }
525 
526 /**
527  * @brief Test statically defined Timer init
528  *
529  * Validate statically defined timer init using K_TIMER_DEFINE
530  *
531  * It creates prototype of K_TIMER_DEFINE to statically define timer
532  * init and starts the timer with k_timer_start() with specific initial
533  * duration and period. Stops the timer using k_timer_stop() and checks
534  * for proper completion of duration and period.
535  *
536  * @ingroup kernel_timer_tests
537  *
538  * @see k_timer_start(), K_TIMER_DEFINE(), k_timer_stop()
539  * k_uptime_get(), k_busy_wait()
540  */
ZTEST_USER(timer_api,test_timer_k_define)541 ZTEST_USER(timer_api, test_timer_k_define)
542 {
543 	init_timer_data();
544 	/** TESTPOINT: init timer via k_timer_init */
545 	k_timer_start(&ktimer, K_MSEC(DURATION), K_MSEC(PERIOD));
546 	busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
547 
548 	/** TESTPOINT: check expire and stop times */
549 	TIMER_ASSERT(tdata.expire_cnt == EXPIRE_TIMES, &ktimer);
550 	TIMER_ASSERT(tdata.stop_cnt == 1, &ktimer);
551 
552 	/* cleanup environment */
553 	k_timer_stop(&ktimer);
554 
555 	init_timer_data();
556 	/** TESTPOINT: init timer via k_timer_init */
557 	k_timer_start(&ktimer, K_MSEC(DURATION), K_MSEC(PERIOD));
558 
559 	/* Call the k_timer_start() again to make sure that
560 	 * the initial timeout request gets cancelled and new
561 	 * one will get added.
562 	 */
563 	busy_wait_ms(DURATION / 2);
564 	k_timer_start(&ktimer, K_MSEC(DURATION), K_MSEC(PERIOD));
565 	tdata.timestamp = k_uptime_get();
566 	busy_wait_ms(DURATION + PERIOD * EXPIRE_TIMES + PERIOD / 2);
567 
568 	/** TESTPOINT: check expire and stop times */
569 	TIMER_ASSERT(tdata.expire_cnt == EXPIRE_TIMES, &ktimer);
570 	TIMER_ASSERT(tdata.stop_cnt == 1, &ktimer);
571 
572 	/* cleanup environment */
573 	k_timer_stop(&ktimer);
574 }
575 
576 static void user_data_timer_handler(struct k_timer *timer);
577 
578 K_TIMER_DEFINE(timer0, user_data_timer_handler, NULL);
579 K_TIMER_DEFINE(timer1, user_data_timer_handler, NULL);
580 K_TIMER_DEFINE(timer2, user_data_timer_handler, NULL);
581 K_TIMER_DEFINE(timer3, user_data_timer_handler, NULL);
582 K_TIMER_DEFINE(timer4, user_data_timer_handler, NULL);
583 
584 static ZTEST_DMEM struct k_timer *user_data_timer[5] = {
585 	&timer0, &timer1, &timer2, &timer3, &timer4
586 };
587 
588 static const intptr_t user_data[5] = { 0x1337, 0xbabe, 0xd00d, 0xdeaf, 0xfade };
589 
590 static ZTEST_BMEM int user_data_correct[5];
591 
user_data_timer_handler(struct k_timer * timer)592 static void user_data_timer_handler(struct k_timer *timer)
593 {
594 	int timer_num = timer == user_data_timer[0] ? 0 :
595 			timer == user_data_timer[1] ? 1 :
596 			timer == user_data_timer[2] ? 2 :
597 			timer == user_data_timer[3] ? 3 :
598 			timer == user_data_timer[4] ? 4 : -1;
599 
600 	if (timer_num == -1) {
601 		return;
602 	}
603 
604 	intptr_t data_retrieved = (intptr_t)k_timer_user_data_get(timer);
605 
606 	user_data_correct[timer_num] = user_data[timer_num] == data_retrieved;
607 }
608 
609 /**
610  * @brief Test user-specific data associated with timer
611  *
612  * Validate user-specific data associated with timer
613  *
614  * It creates prototype of K_TIMER_DEFINE and starts the timer using
615  * k_timer_start() with specific initial duration, along with associated
616  * user data using k_timer_user_data_set and k_timer_user_data_get().
617  * Stops the timer using k_timer_stop() and checks for correct data
618  * retrieval after timer completion.
619  *
620  * @ingroup kernel_timer_tests
621  *
622  * @see K_TIMER_DEFINE(), k_timer_user_data_set(), k_timer_start(),
623  * k_timer_user_data_get(), k_timer_stop()
624  */
ZTEST_USER(timer_api,test_timer_user_data)625 ZTEST_USER(timer_api, test_timer_user_data)
626 {
627 	int ii;
628 
629 	for (ii = 0; ii < 5; ii++) {
630 		intptr_t check;
631 
632 		k_timer_user_data_set(user_data_timer[ii],
633 				      (void *)user_data[ii]);
634 		check = (intptr_t)k_timer_user_data_get(user_data_timer[ii]);
635 
636 		zassert_true(check == user_data[ii]);
637 	}
638 
639 	for (ii = 0; ii < 5; ii++) {
640 		k_timer_start(user_data_timer[ii], K_MSEC(50 + ii * 50),
641 			      K_NO_WAIT);
642 	}
643 
644 	uint32_t wait_ms = 50 * ii + 50;
645 
646 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
647 		k_msleep(wait_ms);
648 	} else {
649 		uint32_t wait_us = 1000 * wait_ms;
650 
651 		k_busy_wait(wait_us + (wait_us * BUSY_TICK_SLEW_PPM) / PPM_DIVISOR);
652 	}
653 
654 	for (ii = 0; ii < 5; ii++) {
655 		k_timer_stop(user_data_timer[ii]);
656 	}
657 
658 	for (ii = 0; ii < 5; ii++) {
659 		zassert_true(user_data_correct[ii]);
660 	}
661 }
662 
663 /**
664  * @brief Test accuracy of k_timer_remaining_get()
665  *
666  * Validate countdown of time to expiration
667  *
668  * Starts a timer, busy-waits for half the DURATION, then checks the
669  * remaining time to expiration and stops the timer. The remaining time
670  * should reflect the passage of at least the busy-wait interval.
671  *
672  * @ingroup kernel_timer_tests
673  *
674  * @see k_timer_init(), k_timer_start(), k_timer_stop(),
675  * k_timer_remaining_get()
676  */
677 
ZTEST_USER(timer_api,test_timer_remaining)678 ZTEST_USER(timer_api, test_timer_remaining)
679 {
680 	uint32_t dur_ticks = k_ms_to_ticks_ceil32(DURATION);
681 	uint32_t target_rem_ticks = k_ms_to_ticks_ceil32(DURATION / 2);
682 	uint32_t rem_ms, rem_ticks, exp_ticks;
683 	int32_t delta_ticks;
684 	uint32_t slew_ticks;
685 	uint64_t now;
686 
687 
688 	init_timer_data();
689 	k_timer_start(&remain_timer, K_MSEC(DURATION), K_NO_WAIT);
690 	busy_wait_ms(DURATION / 2);
691 	rem_ticks = k_timer_remaining_ticks(&remain_timer);
692 	now = k_uptime_ticks();
693 	rem_ms = k_timer_remaining_get(&remain_timer);
694 	exp_ticks = k_timer_expires_ticks(&remain_timer);
695 	k_timer_stop(&remain_timer);
696 	TIMER_ASSERT(tdata.expire_cnt == 0, &remain_timer);
697 	TIMER_ASSERT(tdata.stop_cnt == 1, &remain_timer);
698 
699 	/*
700 	 * While the busy_wait_ms() works with the maximum possible resolution,
701 	 * the k_timer api is limited by the system tick abstraction. As result
702 	 * the value obtained through k_timer_remaining_get() could be larger
703 	 * than actual remaining time with maximum error equal to one tick.
704 	 */
705 	zassert_true(rem_ms <= (DURATION / 2) + k_ticks_to_ms_floor64(1),
706 		     NULL);
707 
708 	/* Half the value of DURATION in ticks may not be the value of
709 	 * half DURATION in ticks, when DURATION/2 is not an integer
710 	 * multiple of ticks, so target_rem_ticks is used rather than
711 	 * dur_ticks/2.  Also set a threshold based on expected clock
712 	 * skew.
713 	 */
714 	delta_ticks = (int32_t)(rem_ticks - target_rem_ticks);
715 	slew_ticks = BUSY_SLEW_THRESHOLD_TICKS(DURATION * USEC_PER_MSEC / 2U);
716 	zassert_true(abs(delta_ticks) <= MAX(slew_ticks, 1U),
717 		     "tick/busy slew %d larger than test threshold %u",
718 		     delta_ticks, slew_ticks);
719 
720 	/* Note +1 tick precision: even though we're calculating in
721 	 * ticks, we're waiting in k_busy_wait(), not for a timer
722 	 * interrupt, so it's possible for that to take 1 tick longer
723 	 * than expected on systems where the requested microsecond
724 	 * delay cannot be exactly represented as an integer number of
725 	 * ticks.
726 	 * As above, use higher tolerance on platforms where the clock used
727 	 * by the kernel timer and the one used for busy-waiting may be skewed.
728 	 */
729 	zassert_true(((int64_t)exp_ticks - (int64_t)now)
730 		     <= (dur_ticks / 2) + 1 + slew_ticks, NULL);
731 }
732 
ZTEST_USER(timer_api,test_timeout_abs)733 ZTEST_USER(timer_api, test_timeout_abs)
734 {
735 #ifdef CONFIG_TIMEOUT_64BIT
736 	const uint64_t exp_ms = 10000000;
737 	uint64_t rem_ticks;
738 	uint64_t exp_ticks = k_ms_to_ticks_ceil64(exp_ms);
739 	k_timeout_t t = K_TIMEOUT_ABS_TICKS(exp_ticks), t2;
740 	uint64_t t0, t1;
741 
742 	/* Check the other generator macros to make sure they produce
743 	 * the same (whiteboxed) converted values
744 	 */
745 	t2 = K_TIMEOUT_ABS_MS(exp_ms);
746 	zassert_true(t2.ticks == t.ticks);
747 
748 	t2 = K_TIMEOUT_ABS_US(1000 * exp_ms);
749 	zassert_true(t2.ticks == t.ticks);
750 
751 	t2 = K_TIMEOUT_ABS_NS(1000 * 1000 * exp_ms);
752 	zassert_true(t2.ticks == t.ticks);
753 
754 	t2 = K_TIMEOUT_ABS_CYC(k_ms_to_cyc_ceil64(exp_ms));
755 	zassert_true(t2.ticks == t.ticks);
756 
757 	/* Now set the timeout and make sure the expiration time is
758 	 * correct vs. current time.  Tick units and tick alignment
759 	 * makes this math exact, no slop is needed.  Note that time
760 	 * is advancing always, so we add a retry condition to be sure
761 	 * that a tick advance did not happen between our reads of
762 	 * "now" and "expires".
763 	 */
764 	init_timer_data();
765 	k_timer_start(&remain_timer, t, K_FOREVER);
766 
767 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
768 		k_usleep(1);
769 	}
770 
771 	do {
772 		t0 = k_uptime_ticks();
773 		rem_ticks = k_timer_remaining_ticks(&remain_timer);
774 		t1 = k_uptime_ticks();
775 	} while (t0 != t1);
776 
777 	zassert_true(t0 + rem_ticks == exp_ticks,
778 		     "Wrong remaining: now %lld rem %lld expires %lld (%d)",
779 		     (uint64_t)t0, (uint64_t)rem_ticks, (uint64_t)exp_ticks,
780 		     t0+rem_ticks-exp_ticks);
781 
782 	k_timer_stop(&remain_timer);
783 #endif
784 }
785 
ZTEST_USER(timer_api,test_sleep_abs)786 ZTEST_USER(timer_api, test_sleep_abs)
787 {
788 	if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
789 		/* k_sleep is not supported when multithreading is off. */
790 		return;
791 	}
792 
793 	const int sleep_ticks = 50;
794 	int64_t start, end;
795 
796 	k_usleep(1); /* tick align */
797 
798 	start = k_uptime_ticks();
799 	k_sleep(K_TIMEOUT_ABS_TICKS(start + sleep_ticks));
800 	end = k_uptime_ticks();
801 
802 	/* Systems with very high tick rates and/or slow idle resume
803 	 * (I've seen this on intel_adsp) can occasionally take more
804 	 * than a tick to return from k_sleep().  Set a 100us real
805 	 *  time slop or more depending on the time to resume
806 	 */
807 	k_ticks_t late = end - (start + sleep_ticks);
808 	int slop = MAX(2, k_us_to_ticks_ceil32(250));
809 
810 	zassert_true(late >= 0 && late <= slop,
811 		     "expected wakeup at %lld, got %lld (late %lld)",
812 		     start + sleep_ticks, end, late);
813 
814 	/* Let's test that an absolute delay awakes at the correct time
815 	 * even if the system did not get some ticks announcements
816 	 */
817 	int tickless_wait = 5;
818 
819 	start = end;
820 	k_busy_wait(k_ticks_to_us_ceil32(tickless_wait));
821 	/* We expect to not have got <tickless_wait> tick announcements,
822 	 * as there is currently nothing scheduled
823 	 */
824 	k_sleep(K_TIMEOUT_ABS_TICKS(start + sleep_ticks));
825 	end = k_uptime_ticks();
826 	late = end - (start + sleep_ticks);
827 
828 	zassert_true(late >= 0 && late <= slop,
829 		     "expected wakeup at %lld, got %lld (late %lld)",
830 		     start + sleep_ticks, end, late);
831 
832 }
833 
timer_init(struct k_timer * timer,k_timer_expiry_t expiry_fn,k_timer_stop_t stop_fn)834 static void timer_init(struct k_timer *timer, k_timer_expiry_t expiry_fn,
835 		       k_timer_stop_t stop_fn)
836 {
837 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
838 		k_object_access_grant(timer, k_current_get());
839 	}
840 
841 	k_timer_init(timer, expiry_fn, stop_fn);
842 }
843 
setup_timer_api(void)844 void *setup_timer_api(void)
845 {
846 	timer_init(&duration_timer, duration_expire, duration_stop);
847 	timer_init(&period0_timer, period0_expire, NULL);
848 	timer_init(&expire_timer, NULL, duration_stop);
849 	timer_init(&sync_timer, NULL, NULL);
850 	timer_init(&periodicity_timer, NULL, NULL);
851 	timer_init(&status_timer, status_expire, status_stop);
852 	timer_init(&status_anytime_timer, NULL, NULL);
853 	timer_init(&status_sync_timer, duration_expire, duration_stop);
854 	timer_init(&remain_timer, duration_expire, duration_stop);
855 
856 	if (IS_ENABLED(CONFIG_MULTITHREADING)) {
857 		k_thread_access_grant(k_current_get(), &ktimer, &timer0, &timer1,
858 			      &timer2, &timer3, &timer4);
859 	}
860 
861 	return NULL;
862 }
863 
864 ZTEST_SUITE(timer_api, NULL, setup_timer_api, NULL, NULL, NULL);
865