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