1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/ztest.h>
8
9 #define ALIGN_MS_BOUNDARY \
10 do { \
11 uint32_t t = k_uptime_get_32(); \
12 while (t == k_uptime_get_32()) \
13 Z_SPIN_DELAY(50); \
14 } while (0)
15
16 struct timer_data {
17 int duration_count;
18 int stop_count;
19 };
20 static void duration_expire(struct k_timer *timer);
21 static void stop_expire(struct k_timer *timer);
22
23 /** TESTPOINT: init timer via K_TIMER_DEFINE */
24 K_TIMER_DEFINE(ktimer, duration_expire, stop_expire);
25
26 static ZTEST_BMEM struct timer_data tdata;
27
28 #define DURATION 100
29 #define LESS_DURATION 70
30
31 /**
32 * @defgroup kernel_clock_tests Clock Operations
33 * @ingroup all_tests
34 * @{
35 * @}
36 *
37 * @addtogroup kernel_clock_tests
38 * @{
39 */
40
41 /**
42 * @brief Test clock uptime APIs functionality
43 *
44 * @see k_uptime_get(), k_uptime_get_32(), k_uptime_delta()
45 */
ZTEST_USER(clock,test_clock_uptime)46 ZTEST_USER(clock, test_clock_uptime)
47 {
48 uint64_t t64, t32;
49 int64_t d64 = 0;
50
51 /**TESTPOINT: uptime elapse*/
52 t64 = k_uptime_get();
53 while (k_uptime_get() < (t64 + 5)) {
54 Z_SPIN_DELAY(50);
55 }
56
57 /**TESTPOINT: uptime elapse lower 32-bit*/
58 t32 = k_uptime_get_32();
59 while (k_uptime_get_32() < (t32 + 5)) {
60 Z_SPIN_DELAY(50);
61 }
62
63 /**TESTPOINT: uptime straddled ms boundary*/
64 t32 = k_uptime_get_32();
65 ALIGN_MS_BOUNDARY;
66 zassert_true(k_uptime_get_32() > t32);
67
68 /**TESTPOINT: uptime delta*/
69 d64 = k_uptime_delta(&d64);
70 while (k_uptime_delta(&d64) == 0) {
71 Z_SPIN_DELAY(50);
72 }
73 }
74
75 /**
76 * @brief Test 32-bit clock cycle functionality
77 *
78 * @details
79 * Test Objective:
80 * - The kernel architecture provide a 32bit monotonically increasing
81 * cycle counter
82 * - This routine tests the k_cycle_get_32() and k_uptime_get_32()
83 * k_cycle_get_32() get cycles by accessing hardware clock.
84 * k_uptime_get_32() return cycles by transforming ticks into cycles.
85 *
86 * Testing techniques
87 * - Functional and black box testing
88 *
89 * Prerequisite Condition:
90 * - N/A
91 *
92 * Input Specifications:
93 * - N/A
94 *
95 * Expected Test Result:
96 * - The timer increases monotonically
97 *
98 * Pass/Fail criteria:
99 * - Success if cycles increase monotonically, failure otherwise.
100 *
101 * Test Procedure:
102 * -# At milli-second boundary, get cycles repeatedly by k_cycle_get_32()
103 * till cycles increased
104 * -# At milli-second boundary, get cycles repeatedly by k_uptime_get_32()
105 * till cycles increased
106 * -# Cross check cycles gotten by k_cycle_get_32() and k_uptime_get_32(),
107 * the delta cycle should be greater than 1 milli-second.
108 *
109 * Assumptions and Constraints
110 * - N/A
111 *
112 * @see k_cycle_get_32(), k_uptime_get_32()
113 */
114
ZTEST(clock,test_clock_cycle_32)115 ZTEST(clock, test_clock_cycle_32)
116 {
117 uint32_t c32, c0, c1, t32;
118
119 /**TESTPOINT: cycle elapse*/
120 ALIGN_MS_BOUNDARY;
121 c32 = k_cycle_get_32();
122 /*break if cycle counter wrap around*/
123 while (k_cycle_get_32() > c32 &&
124 k_cycle_get_32() < (c32 + k_ticks_to_cyc_floor32(1))) {
125 Z_SPIN_DELAY(50);
126 }
127
128 /**TESTPOINT: cycle/uptime cross check*/
129 c0 = k_cycle_get_32();
130 ALIGN_MS_BOUNDARY;
131 t32 = k_uptime_get_32();
132 while (t32 == k_uptime_get_32()) {
133 Z_SPIN_DELAY(50);
134 }
135
136 c1 = k_uptime_get_32();
137 /*avoid cycle counter wrap around*/
138 if (c1 > c0) {
139 /* delta cycle should be greater than 1 milli-second*/
140 zassert_true((c1 - c0) > (sys_clock_hw_cycles_per_sec() / MSEC_PER_SEC));
141 /* delta NS should be greater than 1 milli-second */
142 zassert_true((uint32_t)k_cyc_to_ns_floor64(c1 - c0) >
143 (NSEC_PER_SEC / MSEC_PER_SEC));
144 }
145 }
146
147 /**
148 * @brief Test 64-bit clock cycle functionality
149 */
ZTEST(clock,test_clock_cycle_64)150 ZTEST(clock, test_clock_cycle_64)
151 {
152 uint32_t d32;
153 uint64_t d64;
154 uint32_t t32[2];
155 uint64_t t64[2];
156
157 if (!IS_ENABLED(CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER)) {
158 ztest_test_skip();
159 }
160
161 t64[0] = k_cycle_get_64();
162 t32[0] = k_cycle_get_32();
163
164 k_msleep(1);
165
166 t32[1] = k_cycle_get_32();
167 t64[1] = k_cycle_get_64();
168
169 d32 = MIN(t32[1] - t32[0], t32[0] - t32[1]);
170 d64 = MIN(t64[1] - t64[0], t64[1] - t64[0]);
171
172 zassert_true(d64 >= d32,
173 "k_cycle_get() (64-bit): d64: %" PRIu64 " < d32: %u", d64, d32);
174
175 zassert_true(d64 < (d32 << 1),
176 "k_cycle_get() (64-bit): d64: %" PRIu64 " >= 2 * d32: %u",
177 d64, (d32 << 1));
178 }
179
180 /*
181 *help function
182 */
duration_expire(struct k_timer * timer)183 static void duration_expire(struct k_timer *timer)
184 {
185 tdata.duration_count++;
186 }
187
stop_expire(struct k_timer * timer)188 static void stop_expire(struct k_timer *timer)
189 {
190 tdata.stop_count++;
191 }
192
init_data_count(void)193 static void init_data_count(void)
194 {
195 tdata.duration_count = 0;
196 tdata.stop_count = 0;
197 }
198
199 /**
200 * @brief Test millisecond time duration
201 *
202 * @details initialize a timer, then providing time duration in
203 * millisecond, and check the duration time whether correct.
204 *
205 * @see k_timer_init(), k_timer_start(), k_timer_stop(),
206 * k_busy_wait()
207 *
208 *
209 */
210
ZTEST(clock,test_ms_time_duration)211 ZTEST(clock, test_ms_time_duration)
212 {
213 init_data_count();
214 k_timer_start(&ktimer, K_MSEC(DURATION), K_NO_WAIT);
215
216 /** TESTPOINT: waiting time less than duration and check the count*/
217 k_busy_wait(LESS_DURATION * 1000);
218 zassert_true(tdata.duration_count == 0);
219 zassert_true(tdata.stop_count == 0);
220
221 /** TESTPOINT: proving duration in millisecond */
222 init_data_count();
223 k_timer_start(&ktimer, K_MSEC(100), K_MSEC(50));
224
225 /** TESTPOINT: waiting time more than duration and check the count */
226 k_usleep(1); /* align to tick */
227 k_busy_wait((DURATION + 1) * 1000);
228 zassert_true(tdata.duration_count == 1, "duration %u not 1",
229 tdata.duration_count);
230 zassert_true(tdata.stop_count == 0,
231 "stop %u not 0", tdata.stop_count);
232
233 /** cleanup environment */
234 k_timer_stop(&ktimer);
235 }
236
237 /**
238 * @}
239 */
240
241 extern void *common_setup(void);
242 ZTEST_SUITE(clock, NULL, common_setup, NULL, NULL, NULL);
243