1 /*
2  * Copyright (c) 2019 Intel Corp.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 
10 /*
11  * precision timing tests in an emulation environment are not reliable.
12  * if the test passes at least once, we know it works properly, so we
13  * attempt to repeat the test RETRIES times before reporting failure.
14  */
15 
16 #define RETRIES		10
17 
18 /*
19  * We need to know how many ticks will elapse when we ask for the
20  * shortest possible tick timeout.  That's generally 1, but in some
21  * cases it may be more.  On Nordic paths that take 5 or 6 ticks may
22  * be observed depending on clock stability and alignment. The base
23  * rate assumes 3 ticks for non-timeout effects so increase the
24  * maximum effect of timeout to 3 ticks on this platform.
25  */
26 
27 #if defined(CONFIG_NRF_RTC_TIMER) && (CONFIG_SYS_CLOCK_TICKS_PER_SEC > 16384)
28 /* The overhead of k_usleep() adds three ticks per loop iteration on
29  * nRF51, which has a slow CPU clock.
30  */
31 #define MAXIMUM_SHORTEST_TICKS (IS_ENABLED(CONFIG_SOC_SERIES_NRF51X) ? 6 : 3)
32 /* Similar situation for TI CC13XX/CC26XX RTC kernel timer due to the
33  * limitation that a value too close to the current time cannot be
34  * loaded to its comparator.
35  */
36 #elif defined(CONFIG_CC13XX_CC26XX_RTC_TIMER) && \
37 	(CONFIG_SYS_CLOCK_TICKS_PER_SEC > 16384)
38 #define MAXIMUM_SHORTEST_TICKS 3
39 #elif defined(CONFIG_SILABS_SLEEPTIMER_TIMER) && (CONFIG_SYS_CLOCK_TICKS_PER_SEC > 16384)
40 /* Similar situation for Silabs devices using sleeptimer due to the
41  * limitation that a value too close to the current time cannot be
42  * loaded to its comparator.
43  */
44 #define MAXIMUM_SHORTEST_TICKS 2
45 #else
46 #define MAXIMUM_SHORTEST_TICKS 1
47 #endif
48 
49 /*
50  * Theory of operation: we can't use absolute units (e.g., "sleep for
51  * 10us") in testing k_usleep() because the granularity of sleeps is
52  * highly dependent on the hardware's capabilities and kernel
53  * configuration. Instead, we test that k_usleep() actually sleeps for
54  * the minimum possible duration, which is nominally two ticks.  So,
55  * we loop k_usleep()ing for as many iterations as should comprise a
56  * second, and check to see that a total of one second has elapsed.
57  */
58 
59 #define LOOPS (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 2)
60 
61 /* It should never iterate faster than the tick rate.  However the
62  * app, sleep, and timeout layers may each add a tick alignment with
63  * fast tick rates, and cycle layer may inject another to guarantee
64  * the timeout deadline is met.
65  */
66 #define LOWER_BOUND_MS	((1000 * LOOPS) / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
67 #define UPPER_BOUND_MS	(((3 + MAXIMUM_SHORTEST_TICKS) * 1000 * LOOPS)	\
68 			 / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
69 
ZTEST_USER(sleep,test_usleep)70 ZTEST_USER(sleep, test_usleep)
71 {
72 	int retries = 0;
73 	int64_t elapsed_ms = 0;
74 
75 	while (retries < RETRIES) {
76 		int64_t start_ms;
77 		int64_t end_ms;
78 		int i;
79 
80 		++retries;
81 		start_ms = k_uptime_get();
82 
83 		for (i = 0; i < LOOPS; ++i) {
84 			k_usleep(1);
85 		}
86 
87 		end_ms = k_uptime_get();
88 		elapsed_ms = end_ms - start_ms;
89 
90 		/* if at first you don't succeed, keep sucking. */
91 
92 		if ((elapsed_ms >= LOWER_BOUND_MS) &&
93 		    (elapsed_ms <= UPPER_BOUND_MS)) {
94 			break;
95 		}
96 	}
97 
98 	zassert_true(elapsed_ms >= LOWER_BOUND_MS, "short sleep");
99 	zassert_true(elapsed_ms <= UPPER_BOUND_MS, "overslept");
100 }
101