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