1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/tc_util.h>
9 #include <zephyr/ztest.h>
10
test_frequency(void)11 int test_frequency(void)
12 {
13 volatile uint32_t start, end;
14 uint32_t delta, pct;
15
16 TC_PRINT("Testing system tick frequency\n");
17
18 start = k_cycle_get_32();
19 k_sleep(K_MSEC(1000));
20 end = k_cycle_get_32();
21
22 delta = end - start;
23 pct = (uint64_t)delta * 100U / sys_clock_hw_cycles_per_sec();
24
25 printk("delta: %u expected: %u %u%%\n", delta,
26 sys_clock_hw_cycles_per_sec(), pct);
27
28 /* Heuristic: if we're more than 10% off, throw an error */
29 if (pct < 90 || pct > 110) {
30 TC_PRINT("Clock calibration is way off!\n");
31 return -1;
32 }
33
34 return 0;
35 }
36
37 /**
38 * @brief Test monotonic timer
39 *
40 * Validates monotonic timer's clock calibration.
41 *
42 * It reads the System clock’s h/w timer frequency value continuously
43 * using k_cycle_get_32() to verify its working and correctness.
44 * It also checks system tick frequency by checking the delta error
45 * between generated and system clock provided HW cycles per sec values.
46 *
47 * @ingroup kernel_timer_tests
48 *
49 * @see k_cycle_get_32(), sys_clock_hw_cycles_per_sec()
50 */
ZTEST(timer_fn,test_timer)51 ZTEST(timer_fn, test_timer)
52 {
53 volatile uint32_t t_last, t_now;
54 uint32_t i, errors;
55 int32_t diff;
56
57 errors = 0U;
58
59 TC_PRINT("k_ticks_to_cyc_floor32(1) = %d\n",
60 k_ticks_to_cyc_floor32(1));
61 TC_PRINT("sys_clock_hw_cycles_per_sec() = %d\n",
62 sys_clock_hw_cycles_per_sec());
63
64 t_last = k_cycle_get_32();
65
66 for (i = 0U; i < 1000000; i++) {
67 t_now = k_cycle_get_32();
68
69 if (t_now < t_last) {
70 diff = t_now - t_last;
71 TC_PRINT("diff = %d (t_last = %u : t_now = %u);"
72 "i = %u\n", diff, t_last, t_now, i);
73 errors++;
74 }
75 t_last = t_now;
76 }
77
78 zassert_false(errors, "errors = %d\n", errors);
79
80 zassert_false(test_frequency(), "test frequency failed");
81 }
82
83 ZTEST_SUITE(timer_fn, NULL, NULL, NULL, NULL, NULL);
84