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 #elif defined(CONFIG_SOC_NRF54H20_CPUPPR) && (CONFIG_SYS_CLOCK_TICKS_PER_SEC > 16384)
46 /* Similar for nRF54H20 cpuppr (RISC-V core), it has a slow CPU clock
47 * compared to other cores, causing the increased overhead.
48 */
49 #define MAXIMUM_SHORTEST_TICKS 4
50 #else
51 #define MAXIMUM_SHORTEST_TICKS 1
52 #endif
53
54 /*
55 * Theory of operation: we can't use absolute units (e.g., "sleep for
56 * 10us") in testing k_usleep() because the granularity of sleeps is
57 * highly dependent on the hardware's capabilities and kernel
58 * configuration. Instead, we test that k_usleep() actually sleeps for
59 * the minimum possible duration, which is nominally two ticks. So,
60 * we loop k_usleep()ing for as many iterations as should comprise a
61 * second, and check to see that a total of one second has elapsed.
62 */
63
64 #define LOOPS (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 2)
65
66 /* It should never iterate faster than the tick rate. However the
67 * app, sleep, and timeout layers may each add a tick alignment with
68 * fast tick rates, and cycle layer may inject another to guarantee
69 * the timeout deadline is met.
70 */
71 #define LOWER_BOUND_MS ((1000 * LOOPS) / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
72 #define UPPER_BOUND_MS (((3 + MAXIMUM_SHORTEST_TICKS) * 1000 * LOOPS) \
73 / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
74
ZTEST_USER(sleep,test_usleep)75 ZTEST_USER(sleep, test_usleep)
76 {
77 int retries = 0;
78 int64_t elapsed_ms = 0;
79
80 while (retries < RETRIES) {
81 int64_t start_ms;
82 int64_t end_ms;
83 int i;
84
85 ++retries;
86 start_ms = k_uptime_get();
87
88 for (i = 0; i < LOOPS; ++i) {
89 k_usleep(1);
90 }
91
92 end_ms = k_uptime_get();
93 elapsed_ms = end_ms - start_ms;
94
95 /* if at first you don't succeed, keep sucking. */
96
97 if ((elapsed_ms >= LOWER_BOUND_MS) &&
98 (elapsed_ms <= UPPER_BOUND_MS)) {
99 break;
100 }
101 }
102
103 zassert_true(elapsed_ms >= LOWER_BOUND_MS, "short sleep");
104 zassert_true(elapsed_ms <= UPPER_BOUND_MS, "overslept");
105 }
106