1 /*
2  * Copyright (c) 2021 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 
swap64(uint64_t * a,uint64_t * b)10 static void swap64(uint64_t *a, uint64_t *b)
11 {
12 	uint64_t t = *a;
13 	*a = *b;
14 	*b = t;
15 }
16 
msg(uint64_t c64)17 static void msg(uint64_t c64)
18 {
19 	int64_t ms = k_uptime_get();
20 	int s = ms / 1000;
21 	int m = s / 60;
22 	int h = m / 60;
23 	int d = h / 24;
24 
25 	h %= 24;
26 	m %= 60;
27 	s %= 60;
28 	ms %= 1000;
29 
30 	printk("[%03d:%02d:%02d:%02d.%03d]: cycle: %016" PRIx64 "\n", d, h, m, s, (int)ms, c64);
31 }
32 
timeout(uint64_t prev,uint64_t now)33 uint32_t timeout(uint64_t prev, uint64_t now)
34 {
35 	uint64_t next = prev + BIT64(32) - now;
36 
37 	next &= UINT32_MAX;
38 	if (next == 0) {
39 		next = UINT32_MAX;
40 	}
41 
42 	return (uint32_t)next;
43 }
44 
ZTEST(cycle64_tests,test_32bit_wrap_around)45 ZTEST(cycle64_tests, test_32bit_wrap_around)
46 {
47 	enum {
48 		CURR,
49 		PREV,
50 	};
51 
52 	int i;
53 	uint64_t now;
54 	uint64_t c64[2];
55 
56 	printk("32-bit wrap-around should occur every %us\n",
57 	       (uint32_t)(BIT64(32) / (uint32_t)sys_clock_hw_cycles_per_sec()));
58 
59 	printk("[ddd:hh:mm:ss.0ms]\n");
60 
61 	c64[CURR] = k_cycle_get_64();
62 	msg(c64[CURR]);
63 
64 	for (i = 0; i < 2; ++i) {
65 		k_sleep(Z_TIMEOUT_CYC(timeout(c64[CURR], k_cycle_get_64())));
66 
67 		now = k_cycle_get_64();
68 		swap64(&c64[PREV], &c64[CURR]);
69 		c64[CURR] = now;
70 
71 		msg(c64[CURR]);
72 
73 		zassert_equal(((c64[CURR] - c64[PREV]) >> 32), 1,
74 			 "The 64-bit cycle counter did not increment by 2^32");
75 	}
76 }
77 
78 ZTEST_SUITE(cycle64_tests, NULL, NULL, NULL, NULL, NULL);
79