1 /*
2 * Copyright (c) 2017 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include "NRF_RTC.h"
10 #include "NRF_PPI.h"
11 #include "NRF_CLOCK.h"
12 #include "NRF_HW_model_top.h"
13 #include "irq_ctrl.h"
14 #include "irq_sources.h"
15 #include "bs_tracing.h"
16 #include "time_machine_if.h"
17
18 /*
19 * RTC — Real-time counter
20 *
21 * http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52840.ps/rtc.html?cp=2_0_0_23#concept_rvn_vkj_sr
22 */
23
24 /* To simplify, so far it is only modeled what the current BLE controller uses
25 *
26 * NOT modelled:
27 * * TICK events
28 * * the delay in tasks or in the synchronization of configuration into the LF clock domain
29 * * TRIGOVRFLW task or OVRFLW event
30 *
31 * * Note: The COUNTER register is only updated when read with the proper function
32 *
33 * * Note: In this model all RTCs have 4 working CC registers (for simplicity)
34 *
35 * * Note: RTC2 cannot be used (it does not have an assigned interrupt)
36 */
37
38 #define N_RTC 3
39 #define N_CC 4
40
41 #define RTC_COUNTER_MASK 0xFFFFFF /*24 bits*/
42 NRF_RTC_Type NRF_RTC_regs[N_RTC];
43
44 static bool RTC_Running[N_RTC] = {false};
45 static uint32_t RTC_INTEN[N_RTC] = {0};
46
47 bs_time_t Timer_RTC = TIME_NEVER;
48 static bs_time_t cc_timers[N_RTC][N_CC] = {{TIME_NEVER}}; //when each CC will match (in microseconds)
49
50 static bs_time_t RTC_counter_startT[N_RTC] = {TIME_NEVER}; //Time when the counter was "started" (really the time that would correspond to COUNTER = 0)
51 static uint32_t counter[N_RTC] = {0}; //Internal counter value when the counter was stopped
52
53 static bs_time_t first_lf_tick_time = 0;
54
nrf_rtc_init()55 void nrf_rtc_init() {
56 memset(NRF_RTC_regs, 0, sizeof(NRF_RTC_regs));
57 for (int i = 0; i < N_RTC ; i++) {
58 RTC_Running[i] = false;
59 RTC_INTEN[i] = 0;
60 counter[i] = 0;
61 RTC_counter_startT[i] = TIME_NEVER;
62 for (int j = 0 ; j < N_CC ; j++) {
63 cc_timers[i][j] = TIME_NEVER;
64 }
65 }
66 Timer_RTC = TIME_NEVER;
67 }
68
nrf_rtc_clean_up()69 void nrf_rtc_clean_up() {
70
71 }
72
nrf_rtc_notify_first_lf_tick()73 void nrf_rtc_notify_first_lf_tick() {
74 first_lf_tick_time = tm_get_hw_time();
75 bs_trace_raw_time(9, "RTC: First lf tick\n");
76 }
77
78
get_last_lf_tick_time()79 static bs_time_t get_last_lf_tick_time() {
80 bs_time_t now = tm_get_hw_time();
81
82 if (now > TIME_NEVER>>9) {
83 bs_trace_error_time_line("Bummer, the RTC model only supports running for 1142 years\n");
84 /*If you really need this, generalize the calculation to more than 64 bits*/
85 }
86
87 uint64_t lf_ticks = ((now - first_lf_tick_time)<<9) / LF_CLOCK_PERIOD; //floor()
88 bs_time_t last_tick_time = lf_ticks * LF_CLOCK_PERIOD >> 9;
89 last_tick_time += first_lf_tick_time;
90
91 return last_tick_time;
92 }
93
94 /**
95 * Convert a time delta in microseconds to the equivalent count accounting for the PRESCALER
96 * Note that the number is rounded down [floor()]
97 */
time_to_counter(bs_time_t delta,int rtc)98 static uint64_t time_to_counter(bs_time_t delta, int rtc) {
99 uint64_t ticks;
100 //Note: we add 1us, to account for the RTC ticks happening in the floor of the us
101 // as 1us is way smaller than the LF_CLOCK_PERIOD it will not cause an issue rounding the counter value up
102 ticks = ((delta + 1)<< 9) / ((uint64_t)LF_CLOCK_PERIOD * (NRF_RTC_regs[rtc].PRESCALER + 1));
103 return ticks;
104 }
105
106 /**
107 * Convert a counter delta to microseconds accounting for the PRESCALER
108 * (the fractional number microseconds with 9 bit resolution, is stored in frac)
109 */
counter_to_time(uint64_t counter,int rtc,uint16_t * frac)110 static bs_time_t counter_to_time(uint64_t counter, int rtc, uint16_t *frac) {
111 bs_time_t Elapsed;
112 Elapsed = counter * (uint64_t)LF_CLOCK_PERIOD * (NRF_RTC_regs[rtc].PRESCALER + 1);
113 if (frac != NULL){
114 *frac = Elapsed & 0x1FF;
115 }
116 return Elapsed >> 9;
117 }
118
119 /**
120 * Return the time it takes for the COUNTER to do 1 wrap
121 * The whole number of microseconds is stored in us, the fractional number of microseconds
122 * with 9 bits resolution is stored in frac
123 */
time_of_1_counter_wrap(int rtc,bs_time_t * us,uint16_t * frac)124 static void time_of_1_counter_wrap(int rtc, bs_time_t *us, uint16_t *frac) {
125 *us = counter_to_time((uint64_t)RTC_COUNTER_MASK + 1, rtc, frac);
126 }
127
update_master_timer()128 static void update_master_timer() {
129 Timer_RTC = TIME_NEVER;
130 for (int rtc = 0; rtc < N_RTC ; rtc++) {
131 if (RTC_Running[rtc] == false) {
132 continue;
133 }
134 for (int cc = 0 ; cc < N_CC ; cc++) {
135 if (cc_timers[rtc][cc] < Timer_RTC) {
136 Timer_RTC = cc_timers[rtc][cc];
137 }
138 }
139 }
140 nrf_hw_find_next_timer_to_trigger();
141 }
142
143 /**
144 * Save in cc_timers[t][cc] the next time when this RTC will match the
145 * CC[cc] register
146 */
update_cc_timer(int rtc,int cc)147 static void update_cc_timer(int rtc, int cc) {
148 if (RTC_Running[rtc] == true) {
149 uint16_t next_match_frac;
150 bs_time_t next_match_us = RTC_counter_startT[rtc]
151 + counter_to_time(NRF_RTC_regs[rtc].CC[cc], rtc, &next_match_frac);
152
153 bs_time_t now = tm_get_hw_time();
154
155 if (next_match_us <= now) {
156 bs_time_t t_us;
157 uint16_t t_frac;
158
159 time_of_1_counter_wrap(rtc, &t_us, &t_frac);
160
161 do {
162 next_match_us += t_us;
163 next_match_frac += t_frac;
164 if (next_match_frac >= 0x200){
165 next_match_frac -= 0x200;
166 next_match_us +=1;
167 }
168 } while (next_match_us <= now);
169
170 }
171 cc_timers[rtc][cc] = next_match_us;
172 } else {
173 cc_timers[rtc][cc] = TIME_NEVER;
174 }
175 }
176
update_all_cc_timers(int rtc)177 static void update_all_cc_timers(int rtc) {
178 for (int cc = 0 ; cc < N_CC; cc++){
179 update_cc_timer(rtc, cc);
180 }
181 }
182
get_irq_t(int rtc)183 static unsigned int get_irq_t(int rtc)
184 {
185 unsigned int irq_t = NRF5_IRQ_RTC0_IRQn;
186
187 switch (rtc){
188 case 0:
189 irq_t = NRF5_IRQ_RTC0_IRQn;
190 break;
191 case 1:
192 irq_t = NRF5_IRQ_RTC1_IRQn;
193 break;
194 case 2:
195 irq_t = NRF5_IRQ_RTC1_IRQn;
196 bs_trace_error_line_time("There is no IRQ mapped for RTC2\n");
197 break;
198 }
199
200 return irq_t;
201 }
202
get_event(int rtc)203 static ppi_event_types_t get_event(int rtc)
204 {
205 ppi_event_types_t event = RTC0_EVENTS_COMPARE_0;
206 switch (rtc){
207 case 0:
208 event = RTC0_EVENTS_COMPARE_0;
209 break;
210 case 1:
211 event = RTC1_EVENTS_COMPARE_0;
212 break;
213 case 2:
214 event = RTC2_EVENTS_COMPARE_0;
215 break;
216 }
217
218 return event;
219 }
220
nrf_rtc_timer_triggered()221 void nrf_rtc_timer_triggered() {
222 for ( int rtc = 0; rtc < N_RTC-1/*the 3rd rtc does not have an int*/ ; rtc++ ){
223 if ( RTC_Running[rtc] == false ) {
224 continue;
225 }
226 ppi_event_types_t event = get_event(rtc);
227
228 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[rtc];
229
230 uint32_t mask = RTC_EVTEN_COMPARE0_Msk;
231
232 for ( int cc = 0 ; cc < N_CC ; cc++, event++, mask <<=1) {
233 if ( cc_timers[rtc][cc] == Timer_RTC ){ //This CC is matching now
234 update_cc_timer(rtc, cc); //Next time it will match
235
236 bs_trace_raw_time(8, "RTC%i: CC%i matching now\n", rtc, cc);
237
238 if ( ( RTC_regs->EVTEN | RTC_INTEN[rtc] ) & mask ) {
239 RTC_regs->EVENTS_COMPARE[cc] = 1;
240 if ( RTC_regs->EVTEN & mask ){
241 nrf_ppi_event(event);
242 }
243 if ( RTC_INTEN[rtc] & mask ){
244 hw_irq_ctrl_set_irq(get_irq_t(rtc));
245 }
246 }
247 } //if cc_timers[rtc][cc] == Timer_RTC
248 } //for cc
249 } //for rtc
250 update_master_timer();
251 }
252
253 /**
254 * Check if an EVTEN or INTEN has the tick event set
255 */
check_not_supported_func(uint32_t i)256 static void check_not_supported_func(uint32_t i) {
257 if (i & RTC_EVTEN_TICK_Msk) {
258 bs_trace_warning_line_time("RTC: The TICK functionality is not modelled\n");
259 }
260 if (i & RTC_EVTEN_OVRFLW_Msk) {
261 bs_trace_warning_line_time("RTC: The OVERFLOW functionality is not modelled\n");
262 }
263 }
264
265
nrf_rtc_update_COUNTER(int rtc)266 void nrf_rtc_update_COUNTER(int rtc) {
267 if (RTC_Running[rtc] == true) {
268 uint64_t count;
269 count = time_to_counter(tm_get_hw_time() - RTC_counter_startT[rtc], rtc);
270 NRF_RTC_regs[rtc].COUNTER = count & RTC_COUNTER_MASK;
271 } else {
272 NRF_RTC_regs[rtc].COUNTER = counter[rtc] & RTC_COUNTER_MASK;
273 }
274 }
275
276 /**
277 * TASK_START triggered handler
278 */
nrf_rtc_TASKS_START(int rtc)279 void nrf_rtc_TASKS_START(int rtc) {
280 if (RTC_Running[rtc] == true) {
281 return;
282 }
283 bs_trace_raw_time(5, "RTC%i: TASK_START\n", rtc);
284 RTC_Running[rtc] = true;
285 RTC_counter_startT[rtc] = get_last_lf_tick_time()
286 - counter_to_time(counter[rtc], rtc, NULL); //If the counter is not zero at start, is like if the counter was started earlier
287 update_all_cc_timers(rtc);
288 update_master_timer();
289 }
290
291 /**
292 * TASK_STOP triggered handler
293 */
nrf_rtc_TASKS_STOP(int rtc)294 void nrf_rtc_TASKS_STOP(int rtc) {
295 if (RTC_Running[rtc] == false) {
296 return;
297 }
298 bs_trace_raw_time(5, "RTC%i: TASK_STOP\n", rtc);
299 RTC_Running[rtc] = false;
300 counter[rtc] = time_to_counter(tm_get_hw_time() - RTC_counter_startT[rtc], rtc); //we save the value when the counter was stoped in case it is started again without clearing it
301 counter[rtc] &= RTC_COUNTER_MASK;
302 for (int cc = 0 ; cc < N_CC ; cc++){
303 cc_timers[rtc][cc] = TIME_NEVER;
304 }
305 update_master_timer();
306 }
307
308 /**
309 * TASK_CLEAR triggered handler
310 */
nrf_rtc_TASKS_CLEAR(int rtc)311 void nrf_rtc_TASKS_CLEAR(int rtc) {
312 bs_trace_raw_time(5, "RTC%i: TASK_CLEAR\n", rtc);
313 NRF_RTC_regs[rtc].COUNTER = 0;
314 counter[rtc] = 0;
315 RTC_counter_startT[rtc] = get_last_lf_tick_time();
316 update_all_cc_timers(rtc);
317 update_master_timer();
318 }
319
nrf_rtc0_TASKS_START()320 void nrf_rtc0_TASKS_START() { nrf_rtc_TASKS_START(0); }
nrf_rtc0_TASKS_STOP()321 void nrf_rtc0_TASKS_STOP() { nrf_rtc_TASKS_STOP(0); }
nrf_rtc0_TASKS_CLEAR()322 void nrf_rtc0_TASKS_CLEAR() { nrf_rtc_TASKS_CLEAR(0); }
nrf_rtc1_TASKS_START()323 void nrf_rtc1_TASKS_START() { nrf_rtc_TASKS_START(1); }
nrf_rtc1_TASKS_STOP()324 void nrf_rtc1_TASKS_STOP() { nrf_rtc_TASKS_STOP(1); }
nrf_rtc1_TASKS_CLEAR()325 void nrf_rtc1_TASKS_CLEAR() { nrf_rtc_TASKS_CLEAR(1); }
nrf_rtc2_TASKS_START()326 void nrf_rtc2_TASKS_START() { nrf_rtc_TASKS_START(2); }
nrf_rtc2_TASKS_STOP()327 void nrf_rtc2_TASKS_STOP() { nrf_rtc_TASKS_STOP(2); }
nrf_rtc2_TASKS_CLEAR()328 void nrf_rtc2_TASKS_CLEAR() { nrf_rtc_TASKS_CLEAR(2); }
329
nrf_rtc_regw_sideeffect_TASKS_START(int i)330 void nrf_rtc_regw_sideeffect_TASKS_START(int i) {
331 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
332 if ( RTC_regs->TASKS_START ){
333 RTC_regs->TASKS_START = 0;
334 nrf_rtc_TASKS_START(i);
335 }
336 }
337
nrf_rtc_regw_sideeffect_TASKS_STOP(int i)338 void nrf_rtc_regw_sideeffect_TASKS_STOP(int i) {
339 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
340 if ( RTC_regs->TASKS_STOP ){
341 NRF_RTC_regs[i].TASKS_STOP = 0;
342 nrf_rtc_TASKS_STOP(i);
343 }
344 }
345
nrf_rtc_regw_sideeffect_TASKS_CLEAR(int i)346 void nrf_rtc_regw_sideeffect_TASKS_CLEAR(int i) {
347 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
348 if ( RTC_regs->TASKS_CLEAR ){
349 NRF_RTC_regs[i].TASKS_CLEAR = 0;
350 nrf_rtc_TASKS_CLEAR(i);
351 }
352 }
353
nrf_rtc_regw_sideeffect_INTENSET(int i)354 void nrf_rtc_regw_sideeffect_INTENSET(int i) {
355 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
356 if ( RTC_regs->INTENSET ){
357 uint32_t new_interrupts = RTC_regs->INTENSET & ~RTC_INTEN[i];
358 unsigned int irq_t = get_irq_t(i);
359 uint32_t mask = RTC_EVTEN_COMPARE0_Msk;
360
361 RTC_INTEN[i] |= RTC_regs->INTENSET;
362 RTC_regs->INTENSET = RTC_INTEN[i];
363 for ( int cc = 0 ; cc < N_CC ; cc++, mask <<=1) {
364 if (RTC_regs->EVENTS_COMPARE[cc] && (new_interrupts & mask)) {
365 hw_irq_ctrl_set_irq(irq_t);
366 }
367 }
368
369 check_not_supported_func(RTC_INTEN[i]);
370 }
371 }
372
nrf_rtc_regw_sideeffect_INTENCLR(int i)373 void nrf_rtc_regw_sideeffect_INTENCLR(int i) {
374 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
375 if ( RTC_regs->INTENCLR ){
376 RTC_INTEN[i] &= ~RTC_regs->INTENCLR;
377 RTC_regs->INTENSET = RTC_INTEN[i];
378 RTC_regs->INTENCLR = 0;
379 }
380 }
381
nrf_rtc_regw_sideeffect_EVTENSET(int i)382 void nrf_rtc_regw_sideeffect_EVTENSET(int i) {
383 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
384 if ( RTC_regs->EVTENSET ){
385 RTC_regs->EVTEN |= RTC_regs->EVTENSET;
386 RTC_regs->EVTENSET = RTC_regs->EVTEN;
387 check_not_supported_func(RTC_regs->EVTEN);
388 }
389 }
390
nrf_rtc_regw_sideeffect_EVTENCLR(int i)391 void nrf_rtc_regw_sideeffect_EVTENCLR(int i) {
392 NRF_RTC_Type *RTC_regs = &NRF_RTC_regs[i];
393 if ( RTC_regs->EVTENCLR ){
394 RTC_regs->EVTEN &= ~RTC_regs->EVTENCLR;
395 RTC_regs->EVTENSET = RTC_regs->EVTEN;
396 RTC_regs->EVTENCLR = 0;
397 }
398 }
399
nrf_rtc_regw_sideeffects_CC(int rtc,int cc_n)400 void nrf_rtc_regw_sideeffects_CC(int rtc, int cc_n) {
401 if (RTC_Running[rtc] == true) {
402 update_cc_timer(rtc, cc_n);
403 update_master_timer();
404 }
405 }
406
407 /**
408 * Handle any register side effect (by inspecting the registers values)
409 * (deprecated)
410 */
nrf_rtc_regw_sideeffects(int i)411 void nrf_rtc_regw_sideeffects(int i){
412 nrf_rtc_regw_sideeffect_TASKS_START(i);
413
414 nrf_rtc_regw_sideeffect_TASKS_STOP(i);
415
416 nrf_rtc_regw_sideeffect_TASKS_CLEAR(i);
417
418 nrf_rtc_regw_sideeffect_INTENSET(i);
419
420 nrf_rtc_regw_sideeffect_INTENCLR(i);
421
422 nrf_rtc_regw_sideeffect_EVTENSET(i);
423
424 nrf_rtc_regw_sideeffect_EVTENCLR(i);
425 }
426
nrf_rtc0_regw_sideeffects()427 void nrf_rtc0_regw_sideeffects(){ nrf_rtc_regw_sideeffects(0); }
nrf_rtc1_regw_sideeffects()428 void nrf_rtc1_regw_sideeffects(){ nrf_rtc_regw_sideeffects(1); }
nrf_rtc2_regw_sideeffects()429 void nrf_rtc2_regw_sideeffects(){ nrf_rtc_regw_sideeffects(2); }
430