1 /*
2 * Copyright (c) 2019 Nordic Semiconductor ASA
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
11 #include <zephyr/sys/printk.h>
12
13 #define STAMP_INTERVAL_s 60
14 #define TIMER_DELAY_ms 500
15 #define BUSY_WAIT_ms 100
16
17 static volatile uint32_t na;
18
handler(struct k_timer * timer)19 static void handler(struct k_timer *timer)
20 {
21 ++na;
22 }
23
24 static uint32_t iters;
25 static uint32_t now;
26
tag(void)27 static const char *tag(void)
28 {
29 static char buf[32];
30
31 snprintf(buf, sizeof(buf), "[%6u.%03u] %u: ",
32 now / MSEC_PER_SEC, now % MSEC_PER_SEC, iters);
33 return buf;
34 }
35
ZTEST(starve_fn,test_starve)36 ZTEST(starve_fn, test_starve)
37 {
38 static struct k_timer tmr;
39 static struct k_spinlock lock;
40 uint32_t stamp = 0;
41 uint32_t last_now = 0;
42 uint64_t last_ticks = 0;
43 k_spinlock_key_t key;
44
45 TC_PRINT("Cycle clock runs at %u Hz\n",
46 k_ms_to_cyc_ceil32(MSEC_PER_SEC));
47 TC_PRINT("There are %u cycles per tick (%u Hz ticks)\n",
48 k_ticks_to_cyc_ceil32(1U),
49 k_ms_to_ticks_ceil32(MSEC_PER_SEC));
50
51 k_timer_init(&tmr, handler, NULL);
52 while (true) {
53 now = k_uptime_get_32();
54 if ((now / MSEC_PER_SEC) > CONFIG_APP_STOP_S) {
55 break;
56 }
57
58 ++iters;
59
60 if (now > stamp) {
61 TC_PRINT("%sstill running, would pass at %u s\n",
62 tag(), CONFIG_APP_STOP_S);
63 stamp += STAMP_INTERVAL_s * MSEC_PER_SEC;
64 }
65
66 int32_t now_diff = now - last_now;
67
68 zassert_true(now_diff > 0,
69 "%sTime went backwards by %d: was %u.%03u\n",
70 tag(), -now_diff, last_now / MSEC_PER_SEC,
71 last_now % MSEC_PER_SEC);
72 last_now = now;
73
74 /* Assume tick delta fits in printable 32 bits */
75 uint64_t ticks = sys_clock_tick_get();
76 int64_t ticks_diff = ticks - last_ticks;
77
78 zassert_true(ticks_diff > 0,
79 "%sTicks went backwards by %d\n",
80 tag(), -(int32_t)ticks_diff);
81 last_ticks = ticks;
82
83 uint32_t na_capture = na;
84
85 zassert_equal(na_capture, 0,
86 "%sTimer alarm fired: %u\n",
87 na_capture);
88
89 k_timer_start(&tmr, K_MSEC(TIMER_DELAY_ms), K_NO_WAIT);
90
91 /* Wait with interrupts disabled to increase chance
92 * that overflow is detected.
93 */
94 key = k_spin_lock(&lock);
95 k_busy_wait(BUSY_WAIT_ms * USEC_PER_MSEC);
96 k_spin_unlock(&lock, key);
97 }
98 TC_PRINT("%sCompleted %u iters without failure\n",
99 tag(), iters);
100 }
101
102 ZTEST_SUITE(starve_fn, NULL, NULL, NULL, NULL, NULL);
103