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