1 /*
2 * Copyright (c) 2022, Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <zephyr/ztest.h>
7 #include <zephyr/drivers/timer/nrf_grtc_timer.h>
8 #include <hal/nrf_grtc.h>
9
10 #define GRTC_SLEW_TICKS 10
11 #define NUMBER_OF_TRIES 2000
12 #define CYC_PER_TICK \
13 ((uint64_t)sys_clock_hw_cycles_per_sec() / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
14 #define TIMER_COUNT_TIME_MS 10
15 #define WAIT_FOR_TIMER_EVENT_TIME_MS TIMER_COUNT_TIME_MS + 5
16
17 static volatile uint8_t compare_isr_call_counter;
18
19 /* GRTC timer compare interrupt handler */
timer_compare_interrupt_handler(int32_t id,uint64_t expire_time,void * user_data)20 static void timer_compare_interrupt_handler(int32_t id, uint64_t expire_time, void *user_data)
21 {
22 compare_isr_call_counter++;
23 TC_PRINT("Compare value reached, user data: '%s'\n", (char *)user_data);
24 TC_PRINT("Call counter: %d\n", compare_isr_call_counter);
25 }
26
ZTEST(nrf_grtc_timer,test_get_ticks)27 ZTEST(nrf_grtc_timer, test_get_ticks)
28 {
29 k_timeout_t t = K_MSEC(1);
30
31 uint64_t grtc_start_value = z_nrf_grtc_timer_startup_value_get();
32 uint64_t exp_ticks = z_nrf_grtc_timer_read() + t.ticks * CYC_PER_TICK;
33 int64_t ticks;
34
35 /* Relative 1ms from now timeout converted to GRTC */
36 ticks = z_nrf_grtc_timer_get_ticks(t);
37 zassert_true((ticks >= exp_ticks) && (ticks <= (exp_ticks + GRTC_SLEW_TICKS)),
38 "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, exp_ticks);
39
40 k_msleep(1);
41
42 for (uint32_t i = 0; i < NUMBER_OF_TRIES; i++) {
43 /* Absolute timeout 1ms in the past */
44 uint64_t curr_tick;
45 uint64_t curr_grtc_tick;
46 uint64_t curr_tick2;
47
48 do {
49 /* GRTC and system tick must be read during single system tick. */
50 curr_tick = sys_clock_tick_get();
51 curr_grtc_tick = z_nrf_grtc_timer_read();
52 curr_tick2 = sys_clock_tick_get();
53 } while (curr_tick != curr_tick2);
54
55 curr_tick += (grtc_start_value / CYC_PER_TICK);
56 t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick - K_MSEC(1).ticks));
57
58 exp_ticks = curr_grtc_tick - K_MSEC(1).ticks * CYC_PER_TICK;
59 ticks = z_nrf_grtc_timer_get_ticks(t);
60
61 zassert_true((ticks >= (exp_ticks - CYC_PER_TICK + 1)) &&
62 (ticks <= (exp_ticks + GRTC_SLEW_TICKS)),
63 "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks,
64 exp_ticks);
65
66 /* Absolute timeout 10ms in the future */
67 do {
68 /* GRTC and system tick must be read during single system tick. */
69 curr_tick = sys_clock_tick_get();
70 curr_grtc_tick = z_nrf_grtc_timer_read();
71 curr_tick2 = sys_clock_tick_get();
72 } while (curr_tick != curr_tick2);
73
74 curr_tick += (grtc_start_value / CYC_PER_TICK);
75 t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick + K_MSEC(10).ticks));
76 exp_ticks = curr_grtc_tick + K_MSEC(10).ticks * CYC_PER_TICK;
77 ticks = z_nrf_grtc_timer_get_ticks(t);
78 zassert_true((ticks >= (exp_ticks - CYC_PER_TICK + 1)) &&
79 (ticks <= (exp_ticks + GRTC_SLEW_TICKS)),
80 "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks,
81 exp_ticks);
82 }
83 }
84
ZTEST(nrf_grtc_timer,test_timer_count_in_compare_mode)85 ZTEST(nrf_grtc_timer, test_timer_count_in_compare_mode)
86 {
87 int err;
88 uint64_t test_ticks = 0;
89 uint64_t compare_value = 0;
90 char user_data[] = "test_timer_count_in_compare_mode\n";
91 int32_t channel = z_nrf_grtc_timer_chan_alloc();
92
93 TC_PRINT("Allocated GRTC channel %d\n", channel);
94 if (channel < 0) {
95 TC_PRINT("Failed to allocate GRTC channel, chan=%d\n", channel);
96 ztest_test_fail();
97 }
98
99 compare_isr_call_counter = 0;
100 test_ticks = z_nrf_grtc_timer_get_ticks(K_MSEC(TIMER_COUNT_TIME_MS));
101 err = z_nrf_grtc_timer_set(channel, test_ticks, timer_compare_interrupt_handler,
102 (void *)user_data);
103
104 zassert_equal(err, 0, "z_nrf_grtc_timer_set raised an error: %d", err);
105
106 z_nrf_grtc_timer_compare_read(channel, &compare_value);
107 zassert_true(K_TIMEOUT_EQ(K_TICKS(compare_value), K_TICKS(test_ticks)),
108 "Compare register set failed");
109 zassert_equal(err, 0, "Unexpected error raised when setting timer, err: %d", err);
110
111 k_sleep(K_MSEC(WAIT_FOR_TIMER_EVENT_TIME_MS));
112
113 TC_PRINT("Compare event generated ?: %d\n", z_nrf_grtc_timer_compare_evt_check(channel));
114 TC_PRINT("Compare event register address: %X\n",
115 z_nrf_grtc_timer_compare_evt_address_get(channel));
116
117 zassert_equal(compare_isr_call_counter, 1, "Compare isr call counter: %d",
118 compare_isr_call_counter);
119 z_nrf_grtc_timer_chan_free(channel);
120 }
121
ZTEST(nrf_grtc_timer,test_timer_abort_in_compare_mode)122 ZTEST(nrf_grtc_timer, test_timer_abort_in_compare_mode)
123 {
124 int err;
125 uint64_t test_ticks = 0;
126 uint64_t compare_value = 0;
127 char user_data[] = "test_timer_abort_in_compare_mode\n";
128 int32_t channel = z_nrf_grtc_timer_chan_alloc();
129
130 TC_PRINT("Allocated GRTC channel %d\n", channel);
131 if (channel < 0) {
132 TC_PRINT("Failed to allocate GRTC channel, chan=%d\n", channel);
133 ztest_test_fail();
134 }
135
136 compare_isr_call_counter = 0;
137 test_ticks = z_nrf_grtc_timer_get_ticks(K_MSEC(TIMER_COUNT_TIME_MS));
138 err = z_nrf_grtc_timer_set(channel, test_ticks, timer_compare_interrupt_handler,
139 (void *)user_data);
140 zassert_equal(err, 0, "z_nrf_grtc_timer_set raised an error: %d", err);
141
142 z_nrf_grtc_timer_abort(channel);
143
144 z_nrf_grtc_timer_compare_read(channel, &compare_value);
145 zassert_true(K_TIMEOUT_EQ(K_TICKS(compare_value), K_TICKS(test_ticks)),
146 "Compare register set failed");
147
148 zassert_equal(err, 0, "Unexpected error raised when setting timer, err: %d", err);
149
150 k_sleep(K_MSEC(WAIT_FOR_TIMER_EVENT_TIME_MS));
151 zassert_equal(compare_isr_call_counter, 0, "Compare isr call counter: %d",
152 compare_isr_call_counter);
153 z_nrf_grtc_timer_chan_free(channel);
154 }
155
156 ZTEST_SUITE(nrf_grtc_timer, NULL, NULL, NULL, NULL, NULL);
157