Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016-2021 Nordic Semiconductor ASA
3 : : * Copyright (c) 2018 Intel Corporation
4 : : *
5 : : * SPDX-License-Identifier: Apache-2.0
6 : : */
7 : :
8 : : #include <device.h>
9 : : #include <soc.h>
10 : : #include <drivers/clock_control.h>
11 : : #include <drivers/clock_control/nrf_clock_control.h>
12 : : #include <drivers/timer/system_timer.h>
13 : : #include <drivers/timer/nrf_rtc_timer.h>
14 : : #include <sys_clock.h>
15 : : #include <hal/nrf_rtc.h>
16 : :
17 : : #define EXT_CHAN_COUNT CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT
18 : : #define CHAN_COUNT (EXT_CHAN_COUNT + 1)
19 : :
20 : : #define RTC NRF_RTC1
21 : : #define RTC_IRQn NRFX_IRQ_NUMBER_GET(RTC)
22 : : #define RTC_LABEL rtc1
23 : : #define RTC_CH_COUNT RTC1_CC_NUM
24 : :
25 : : BUILD_ASSERT(CHAN_COUNT <= RTC_CH_COUNT, "Not enough compare channels");
26 : :
27 : : #define COUNTER_BIT_WIDTH 24U
28 : : #define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)
29 : : #define COUNTER_MAX (COUNTER_SPAN - 1U)
30 : : #define COUNTER_HALF_SPAN (COUNTER_SPAN / 2U)
31 : : #define CYC_PER_TICK (sys_clock_hw_cycles_per_sec() \
32 : : / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
33 : : #define MAX_TICKS ((COUNTER_HALF_SPAN - CYC_PER_TICK) / CYC_PER_TICK)
34 : : #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)
35 : :
36 : : #define OVERFLOW_RISK_RANGE_END (COUNTER_SPAN / 16)
37 : : #define ANCHOR_RANGE_START (COUNTER_SPAN / 8)
38 : : #define ANCHOR_RANGE_END (7 * COUNTER_SPAN / 8)
39 : : #define TARGET_TIME_INVALID (UINT64_MAX)
40 : :
41 : : static volatile uint32_t overflow_cnt;
42 : : static volatile uint64_t anchor;
43 : : static uint64_t last_count;
44 : :
45 : : struct z_nrf_rtc_timer_chan_data {
46 : : z_nrf_rtc_timer_compare_handler_t callback;
47 : : void *user_context;
48 : : volatile uint64_t target_time;
49 : : };
50 : :
51 : : static struct z_nrf_rtc_timer_chan_data cc_data[CHAN_COUNT];
52 : : static atomic_t int_mask;
53 : : static atomic_t alloc_mask;
54 : : static atomic_t force_isr_mask;
55 : :
56 : 3 : static uint32_t counter_sub(uint32_t a, uint32_t b)
57 : : {
58 : 3 : return (a - b) & COUNTER_MAX;
59 : : }
60 : :
61 : 2 : static void set_comparator(int32_t chan, uint32_t cyc)
62 : : {
63 : 2 : nrf_rtc_cc_set(RTC, chan, cyc & COUNTER_MAX);
64 : 2 : }
65 : :
66 : 1 : static uint32_t get_comparator(int32_t chan)
67 : : {
68 : 1 : return nrf_rtc_cc_get(RTC, chan);
69 : : }
70 : :
71 : 1 : static void event_clear(int32_t chan)
72 : : {
73 : 1 : nrf_rtc_event_clear(RTC, RTC_CHANNEL_EVENT_ADDR(chan));
74 : 1 : }
75 : :
76 : 1 : static void event_enable(int32_t chan)
77 : : {
78 : 1 : nrf_rtc_event_enable(RTC, RTC_CHANNEL_INT_MASK(chan));
79 : 1 : }
80 : :
81 : 0 : static void event_disable(int32_t chan)
82 : : {
83 : 0 : nrf_rtc_event_disable(RTC, RTC_CHANNEL_INT_MASK(chan));
84 : 0 : }
85 : :
86 : 53 : static uint32_t counter(void)
87 : : {
88 : 53 : return nrf_rtc_counter_get(RTC);
89 : : }
90 : :
91 : 1 : static uint32_t absolute_time_to_cc(uint64_t absolute_time)
92 : : {
93 : : /* 24 least significant bits represent target CC value */
94 : 1 : return absolute_time & COUNTER_MAX;
95 : : }
96 : :
97 : 0 : static uint32_t full_int_lock(void)
98 : : {
99 : : uint32_t mcu_critical_state;
100 : :
101 : : if (IS_ENABLED(CONFIG_NRF_RTC_TIMER_LOCK_ZERO_LATENCY_IRQS)) {
102 : : mcu_critical_state = __get_PRIMASK();
103 : : __disable_irq();
104 : : } else {
105 : 0 : mcu_critical_state = irq_lock();
106 : : }
107 : :
108 : 0 : return mcu_critical_state;
109 : : }
110 : :
111 : 0 : static void full_int_unlock(uint32_t mcu_critical_state)
112 : : {
113 : : if (IS_ENABLED(CONFIG_NRF_RTC_TIMER_LOCK_ZERO_LATENCY_IRQS)) {
114 : : __set_PRIMASK(mcu_critical_state);
115 : : } else {
116 : 0 : irq_unlock(mcu_critical_state);
117 : : }
118 : 0 : }
119 : :
120 : 0 : uint32_t z_nrf_rtc_timer_compare_evt_address_get(int32_t chan)
121 : : {
122 [ # # ]: 0 : __ASSERT_NO_MSG(chan < CHAN_COUNT);
123 : 0 : return nrf_rtc_event_address_get(RTC, nrf_rtc_compare_event_get(chan));
124 : : }
125 : :
126 : 0 : uint32_t z_nrf_rtc_timer_capture_task_address_get(int32_t chan)
127 : : {
128 : : #if defined(RTC_TASKS_CAPTURE_TASKS_CAPTURE_Msk)
129 [ # # ]: 0 : __ASSERT_NO_MSG(chan < CHAN_COUNT);
130 [ # # ]: 0 : if (chan == 0) {
131 : 0 : return 0;
132 : : }
133 : :
134 : 0 : nrf_rtc_task_t task = offsetof(NRF_RTC_Type, TASKS_CAPTURE[chan]);
135 : :
136 : 0 : return nrf_rtc_task_address_get(RTC, task);
137 : : #else
138 : : ARG_UNUSED(chan);
139 : : return 0;
140 : : #endif
141 : : }
142 : :
143 : 1 : static bool compare_int_lock(int32_t chan)
144 : : {
145 : 1 : atomic_val_t prev = atomic_and(&int_mask, ~BIT(chan));
146 : :
147 : 1 : nrf_rtc_int_disable(RTC, RTC_CHANNEL_INT_MASK(chan));
148 : :
149 : : __DMB();
150 : : __ISB();
151 : :
152 : 1 : return prev & BIT(chan);
153 : : }
154 : :
155 : :
156 : 0 : bool z_nrf_rtc_timer_compare_int_lock(int32_t chan)
157 : : {
158 [ # # # # ]: 0 : __ASSERT_NO_MSG(chan && chan < CHAN_COUNT);
159 : :
160 : 0 : return compare_int_lock(chan);
161 : : }
162 : :
163 : 1 : static void compare_int_unlock(int32_t chan, bool key)
164 : : {
165 [ + - ]: 1 : if (key) {
166 : 1 : atomic_or(&int_mask, BIT(chan));
167 : 1 : nrf_rtc_int_enable(RTC, RTC_CHANNEL_INT_MASK(chan));
168 [ - + ]: 1 : if (atomic_get(&force_isr_mask) & BIT(chan)) {
169 : 0 : NVIC_SetPendingIRQ(RTC_IRQn);
170 : : }
171 : : }
172 : 1 : }
173 : :
174 : 0 : void z_nrf_rtc_timer_compare_int_unlock(int32_t chan, bool key)
175 : : {
176 [ # # # # ]: 0 : __ASSERT_NO_MSG(chan && chan < CHAN_COUNT);
177 : :
178 : 0 : compare_int_unlock(chan, key);
179 : 0 : }
180 : :
181 : 0 : uint32_t z_nrf_rtc_timer_compare_read(int32_t chan)
182 : : {
183 [ # # ]: 0 : __ASSERT_NO_MSG(chan < CHAN_COUNT);
184 : :
185 : 0 : return nrf_rtc_cc_get(RTC, chan);
186 : : }
187 : :
188 : 0 : uint64_t z_nrf_rtc_timer_get_ticks(k_timeout_t t)
189 : : {
190 : : uint64_t curr_time;
191 : : int64_t curr_tick;
192 : : int64_t result;
193 : : int64_t abs_ticks;
194 : :
195 : : do {
196 : 0 : curr_time = z_nrf_rtc_timer_read();
197 : 0 : curr_tick = sys_clock_tick_get();
198 [ # # ]: 0 : } while (curr_time != z_nrf_rtc_timer_read());
199 : :
200 : 0 : abs_ticks = Z_TICK_ABS(t.ticks);
201 [ # # ]: 0 : if (abs_ticks < 0) {
202 : : /* relative timeout */
203 : 0 : return (t.ticks > COUNTER_SPAN) ?
204 [ # # ]: 0 : -EINVAL : (curr_time + t.ticks);
205 : : }
206 : :
207 : : /* absolute timeout */
208 : 0 : result = abs_ticks - curr_tick;
209 : :
210 [ # # ]: 0 : if (result > COUNTER_SPAN) {
211 : 0 : return -EINVAL;
212 : : }
213 : :
214 : 0 : return curr_time + result;
215 : : }
216 : :
217 : : /** @brief Function safely sets absolute alarm.
218 : : *
219 : : * It assumes that provided value is less than COUNTER_HALF_SPAN from now.
220 : : * It detects late setting and also handle +1 cycle case.
221 : : *
222 : : * @param[in] chan A channel for which a new CC value is to be set.
223 : : *
224 : : * @param[in] abs_val An absolute value of CC register to be set.
225 : : *
226 : : * @returns CC value that was actually set. It is equal to @p abs_val or
227 : : * shifted ahead if @p abs_val was too near in the future (+1 case).
228 : : */
229 : 1 : static uint32_t set_absolute_alarm(int32_t chan, uint32_t abs_val)
230 : : {
231 : : uint32_t now;
232 : : uint32_t now2;
233 : 1 : uint32_t cc_val = abs_val & COUNTER_MAX;
234 : 1 : uint32_t prev_cc = get_comparator(chan);
235 : :
236 : : do {
237 : 1 : now = counter();
238 : :
239 : : /* Handle case when previous event may generate an event.
240 : : * It is handled by setting CC to now (far in the future),
241 : : * in case previous event was set for next tick wait for half
242 : : * LF tick and clear event that may have been generated.
243 : : */
244 : 1 : set_comparator(chan, now);
245 [ - + ]: 1 : if (counter_sub(prev_cc, now) == 1) {
246 : : /* It should wait for half of RTC tick 15.26us. As
247 : : * busy wait runs from different clock source thus
248 : : * wait longer to cover for discrepancy.
249 : : */
250 : 0 : k_busy_wait(19);
251 : : }
252 : :
253 : : /* If requested cc_val is in the past or next tick, set to 2
254 : : * ticks from now. RTC may not generate event if CC is set for
255 : : * 1 tick from now.
256 : : */
257 [ - + ]: 1 : if (counter_sub(cc_val, now + 2) > COUNTER_HALF_SPAN) {
258 : 0 : cc_val = now + 2;
259 : : }
260 : :
261 : 1 : event_clear(chan);
262 : 1 : event_enable(chan);
263 : 1 : set_comparator(chan, cc_val);
264 : 1 : now2 = counter();
265 : 1 : prev_cc = cc_val;
266 : : /* Rerun the algorithm if counter progressed during execution
267 : : * and cc_val is in the past or one tick from now. In such
268 : : * scenario, it is possible that event will not be generated.
269 : : * Rerunning the algorithm will delay the alarm but ensure that
270 : : * event will be generated at the moment indicated by value in
271 : : * CC register.
272 : : */
273 [ # # ]: 0 : } while ((now2 != now) &&
274 [ - + ]: 1 : (counter_sub(cc_val, now2 + 2) > COUNTER_HALF_SPAN));
275 : :
276 : 1 : return cc_val;
277 : : }
278 : :
279 : 1 : static int compare_set_nolocks(int32_t chan, uint64_t target_time,
280 : : z_nrf_rtc_timer_compare_handler_t handler,
281 : : void *user_data)
282 : : {
283 : 1 : int ret = 0;
284 : 1 : uint32_t cc_value = absolute_time_to_cc(target_time);
285 : 1 : uint64_t curr_time = z_nrf_rtc_timer_read();
286 : :
287 [ + - ]: 1 : if (curr_time < target_time) {
288 [ - + ]: 1 : if (target_time - curr_time > COUNTER_SPAN) {
289 : : /* Target time is too distant. */
290 : 0 : return -EINVAL;
291 : : }
292 : :
293 [ + - ]: 1 : if (target_time != cc_data[chan].target_time) {
294 : : /* Target time is valid and is different than currently set.
295 : : * Set CC value.
296 : : */
297 : 1 : uint32_t cc_set = set_absolute_alarm(chan, cc_value);
298 : :
299 : 1 : target_time += counter_sub(cc_set, cc_value);
300 : : }
301 : : } else {
302 : : /* Force ISR handling when exiting from critical section. */
303 : 0 : atomic_or(&force_isr_mask, BIT(chan));
304 : : }
305 : :
306 : 1 : cc_data[chan].target_time = target_time;
307 : 1 : cc_data[chan].callback = handler;
308 : 1 : cc_data[chan].user_context = user_data;
309 : :
310 : 1 : return ret;
311 : : }
312 : :
313 : 1 : static int compare_set(int32_t chan, uint64_t target_time,
314 : : z_nrf_rtc_timer_compare_handler_t handler,
315 : : void *user_data)
316 : : {
317 : : bool key;
318 : :
319 : 1 : key = compare_int_lock(chan);
320 : :
321 : 1 : int ret = compare_set_nolocks(chan, target_time, handler, user_data);
322 : :
323 : 1 : compare_int_unlock(chan, key);
324 : :
325 : 1 : return ret;
326 : : }
327 : :
328 : 0 : int z_nrf_rtc_timer_set(int32_t chan, uint64_t target_time,
329 : : z_nrf_rtc_timer_compare_handler_t handler,
330 : : void *user_data)
331 : : {
332 [ # # # # ]: 0 : __ASSERT_NO_MSG(chan && chan < CHAN_COUNT);
333 : :
334 : 0 : return compare_set(chan, target_time, handler, user_data);
335 : : }
336 : :
337 : 0 : void z_nrf_rtc_timer_abort(int32_t chan)
338 : : {
339 [ # # # # ]: 0 : __ASSERT_NO_MSG(chan && chan < CHAN_COUNT);
340 : :
341 : 0 : bool key = compare_int_lock(chan);
342 : :
343 : 0 : cc_data[chan].target_time = TARGET_TIME_INVALID;
344 : 0 : event_clear(chan);
345 : 0 : event_disable(chan);
346 : 0 : (void)atomic_and(&force_isr_mask, ~BIT(chan));
347 : :
348 : 0 : compare_int_unlock(chan, key);
349 : 0 : }
350 : :
351 : 51 : uint64_t z_nrf_rtc_timer_read(void)
352 : : {
353 : 51 : uint64_t val = ((uint64_t)overflow_cnt) << COUNTER_BIT_WIDTH;
354 : :
355 : : __DMB();
356 : :
357 : 51 : uint32_t cntr = counter();
358 : :
359 : 51 : val += cntr;
360 : :
361 [ + - ]: 51 : if (cntr < OVERFLOW_RISK_RANGE_END) {
362 : : /* `overflow_cnt` can have incorrect value due to still unhandled overflow or
363 : : * due to possibility that this code preempted overflow interrupt before final write
364 : : * of `overflow_cnt`. Update of `anchor` occurs far in time from this moment, so
365 : : * `anchor` is considered valid and stable. Because of this timing there is no risk
366 : : * of incorrect `anchor` value caused by non-atomic read of 64-bit `anchor`.
367 : : */
368 [ - + ]: 51 : if (val < anchor) {
369 : : /* Unhandled overflow, detected, let's add correction */
370 : 0 : val += COUNTER_SPAN;
371 : : }
372 : : } else {
373 : : /* `overflow_cnt` is considered valid and stable in this range, no need to
374 : : * check validity using `anchor`
375 : : */
376 : : }
377 : :
378 : 51 : return val;
379 : : }
380 : :
381 : 0 : static inline bool in_anchor_range(uint32_t cc_value)
382 : : {
383 [ # # # # ]: 0 : return (cc_value >= ANCHOR_RANGE_START) && (cc_value < ANCHOR_RANGE_END);
384 : : }
385 : :
386 : 0 : static inline bool anchor_update(uint32_t cc_value)
387 : : {
388 : : /* Update anchor when far from overflow */
389 [ # # ]: 0 : if (in_anchor_range(cc_value)) {
390 : : /* In this range `overflow_cnt` is considered valid and stable.
391 : : * Write of 64-bit `anchor` is non atomic. However it happens
392 : : * far in time from the moment the `anchor` is read in
393 : : * `z_nrf_rtc_timer_read`.
394 : : */
395 : 0 : anchor = (((uint64_t)overflow_cnt) << COUNTER_BIT_WIDTH) + cc_value;
396 : 0 : return true;
397 : : }
398 : :
399 : 0 : return false;
400 : : }
401 : :
402 : 0 : static void sys_clock_timeout_handler(int32_t chan,
403 : : uint64_t expire_time,
404 : : void *user_data)
405 : : {
406 : 0 : uint32_t cc_value = absolute_time_to_cc(expire_time);
407 : 0 : uint64_t dticks = (expire_time - last_count) / CYC_PER_TICK;
408 : :
409 : 0 : last_count += dticks * CYC_PER_TICK;
410 : :
411 : 0 : bool anchor_updated = anchor_update(cc_value);
412 : :
413 : : if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
414 : : /* protection is not needed because we are in the RTC interrupt
415 : : * so it won't get preempted by the interrupt.
416 : : */
417 : : compare_set(chan, last_count + CYC_PER_TICK,
418 : : sys_clock_timeout_handler, NULL);
419 : : }
420 : :
421 : 0 : sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ?
422 : : (int32_t)dticks : (dticks > 0));
423 : :
424 [ # # ]: 0 : if (cc_value == get_comparator(chan)) {
425 : : /* New value was not set. Set something that can update anchor.
426 : : * If anchor was updated we can enable same CC value to trigger
427 : : * interrupt after full cycle. Else set event in anchor update
428 : : * range. Since anchor was not updated we know that it's very
429 : : * far from mid point so setting is done without any protection.
430 : : */
431 [ # # ]: 0 : if (!anchor_updated) {
432 : 0 : set_comparator(chan, COUNTER_HALF_SPAN);
433 : : }
434 : 0 : event_enable(chan);
435 : : }
436 : 0 : }
437 : :
438 : 0 : static bool channel_processing_check_and_clear(int32_t chan)
439 : : {
440 : 0 : bool result = false;
441 : :
442 : 0 : uint32_t mcu_critical_state = full_int_lock();
443 : :
444 [ # # ]: 0 : if (nrf_rtc_int_enable_check(RTC, RTC_CHANNEL_INT_MASK(chan))) {
445 : : /* The processing of channel can be caused by CC match
446 : : * or be forced.
447 : : */
448 [ # # # # ]: 0 : result = atomic_and(&force_isr_mask, ~BIT(chan)) ||
449 : 0 : nrf_rtc_event_check(RTC, RTC_CHANNEL_EVENT_ADDR(chan));
450 : :
451 [ # # ]: 0 : if (result) {
452 : 0 : event_clear(chan);
453 : : }
454 : : }
455 : :
456 : 0 : full_int_unlock(mcu_critical_state);
457 : :
458 : 0 : return result;
459 : : }
460 : :
461 : 0 : static void process_channel(int32_t chan)
462 : : {
463 [ # # ]: 0 : if (channel_processing_check_and_clear(chan)) {
464 : : void *user_context;
465 : : uint32_t mcu_critical_state;
466 : : uint64_t curr_time;
467 : : uint64_t expire_time;
468 : 0 : z_nrf_rtc_timer_compare_handler_t handler = NULL;
469 : :
470 : 0 : curr_time = z_nrf_rtc_timer_read();
471 : :
472 : : /* This critical section is used to provide atomic access to
473 : : * cc_data structure and prevent higher priority contexts
474 : : * (including ZLIs) from overwriting it.
475 : : */
476 : 0 : mcu_critical_state = full_int_lock();
477 : :
478 : : /* If target_time is in the past or is equal to current time
479 : : * value, execute the handler.
480 : : */
481 : 0 : expire_time = cc_data[chan].target_time;
482 [ # # ]: 0 : if (curr_time >= expire_time) {
483 : 0 : handler = cc_data[chan].callback;
484 : 0 : user_context = cc_data[chan].user_context;
485 : 0 : cc_data[chan].callback = NULL;
486 : 0 : cc_data[chan].target_time = TARGET_TIME_INVALID;
487 : 0 : event_disable(chan);
488 : : }
489 : :
490 : 0 : full_int_unlock(mcu_critical_state);
491 : :
492 [ # # ]: 0 : if (handler) {
493 : 0 : handler(chan, expire_time, user_context);
494 : : }
495 : : }
496 : 0 : }
497 : :
498 : : /* Note: this function has public linkage, and MUST have this
499 : : * particular name. The platform architecture itself doesn't care,
500 : : * but there is a test (tests/arch/arm_irq_vector_table) that needs
501 : : * to find it to it can set it in a custom vector table. Should
502 : : * probably better abstract that at some point (e.g. query and reset
503 : : * it by pointer at runtime, maybe?) so we don't have this leaky
504 : : * symbol.
505 : : */
506 : 0 : void rtc_nrf_isr(const void *arg)
507 : : {
508 : : ARG_UNUSED(arg);
509 : :
510 [ # # # # ]: 0 : if (nrf_rtc_int_enable_check(RTC, NRF_RTC_INT_OVERFLOW_MASK) &&
511 : 0 : nrf_rtc_event_check(RTC, NRF_RTC_EVENT_OVERFLOW)) {
512 : 0 : nrf_rtc_event_clear(RTC, NRF_RTC_EVENT_OVERFLOW);
513 : 0 : overflow_cnt++;
514 : : }
515 : :
516 [ # # ]: 0 : for (int32_t chan = 0; chan < CHAN_COUNT; chan++) {
517 : 0 : process_channel(chan);
518 : : }
519 : 0 : }
520 : :
521 : 0 : int32_t z_nrf_rtc_timer_chan_alloc(void)
522 : : {
523 : : int32_t chan;
524 : : atomic_val_t prev;
525 : : do {
526 [ # # ]: 0 : chan = alloc_mask ? 31 - __builtin_clz(alloc_mask) : -1;
527 [ # # ]: 0 : if (chan < 0) {
528 : 0 : return -ENOMEM;
529 : : }
530 : 0 : prev = atomic_and(&alloc_mask, ~BIT(chan));
531 [ # # ]: 0 : } while (!(prev & BIT(chan)));
532 : :
533 : 0 : return chan;
534 : : }
535 : :
536 : 0 : void z_nrf_rtc_timer_chan_free(int32_t chan)
537 : : {
538 [ # # # # ]: 0 : __ASSERT_NO_MSG(chan && chan < CHAN_COUNT);
539 : :
540 : 0 : atomic_or(&alloc_mask, BIT(chan));
541 : 0 : }
542 : :
543 : :
544 : 0 : void sys_clock_set_timeout(int32_t ticks, bool idle)
545 : : {
546 : : ARG_UNUSED(idle);
547 : : uint32_t cyc;
548 : :
549 : : if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
550 : : return;
551 : : }
552 : :
553 [ # # ]: 0 : ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
554 [ # # # # ]: 0 : ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS);
555 : :
556 : 0 : uint32_t unannounced = z_nrf_rtc_timer_read() - last_count;
557 : :
558 : : /* If we haven't announced for more than half the 24-bit wrap
559 : : * duration, then force an announce to avoid loss of a wrap
560 : : * event. This can happen if new timeouts keep being set
561 : : * before the existing one triggers the interrupt.
562 : : */
563 [ # # ]: 0 : if (unannounced >= COUNTER_HALF_SPAN) {
564 : 0 : ticks = 0;
565 : : }
566 : :
567 : : /* Get the cycles from last_count to the tick boundary after
568 : : * the requested ticks have passed starting now.
569 : : */
570 : 0 : cyc = ticks * CYC_PER_TICK + 1 + unannounced;
571 : 0 : cyc += (CYC_PER_TICK - 1);
572 : 0 : cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK;
573 : :
574 : : /* Due to elapsed time the calculation above might produce a
575 : : * duration that laps the counter. Don't let it.
576 : : */
577 [ # # ]: 0 : if (cyc > MAX_CYCLES) {
578 : 0 : cyc = MAX_CYCLES;
579 : : }
580 : :
581 : 0 : uint64_t target_time = cyc + last_count;
582 : :
583 : 0 : compare_set(0, target_time, sys_clock_timeout_handler, NULL);
584 : : }
585 : :
586 : 48 : uint32_t sys_clock_elapsed(void)
587 : : {
588 : : if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
589 : : return 0;
590 : : }
591 : :
592 : 48 : return (z_nrf_rtc_timer_read() - last_count) / CYC_PER_TICK;
593 : : }
594 : :
595 : 2 : uint32_t sys_clock_cycle_get_32(void)
596 : : {
597 : 2 : return (uint32_t)z_nrf_rtc_timer_read();
598 : : }
599 : :
600 : 1 : static int sys_clock_driver_init(const struct device *dev)
601 : : {
602 : : ARG_UNUSED(dev);
603 : : static const enum nrf_lfclk_start_mode mode =
604 : : IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) ?
605 : : CLOCK_CONTROL_NRF_LF_START_NOWAIT :
606 : : (IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY) ?
607 : : CLOCK_CONTROL_NRF_LF_START_AVAILABLE :
608 : : CLOCK_CONTROL_NRF_LF_START_STABLE);
609 : :
610 : : /* TODO: replace with counter driver to access RTC */
611 : 1 : nrf_rtc_prescaler_set(RTC, 0);
612 [ + + ]: 2 : for (int32_t chan = 0; chan < CHAN_COUNT; chan++) {
613 : 1 : cc_data[chan].target_time = TARGET_TIME_INVALID;
614 : 1 : nrf_rtc_int_enable(RTC, RTC_CHANNEL_INT_MASK(chan));
615 : : }
616 : :
617 : 1 : nrf_rtc_int_enable(RTC, NRF_RTC_INT_OVERFLOW_MASK);
618 : :
619 : 1 : NVIC_ClearPendingIRQ(RTC_IRQn);
620 : :
621 : 1 : IRQ_CONNECT(RTC_IRQn, DT_IRQ(DT_NODELABEL(RTC_LABEL), priority),
622 : : rtc_nrf_isr, 0, 0);
623 : 1 : irq_enable(RTC_IRQn);
624 : :
625 : 1 : nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_CLEAR);
626 : 1 : nrf_rtc_task_trigger(RTC, NRF_RTC_TASK_START);
627 : :
628 : 1 : int_mask = BIT_MASK(CHAN_COUNT);
629 : : if (CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT) {
630 : : alloc_mask = BIT_MASK(EXT_CHAN_COUNT) << 1;
631 : : }
632 : :
633 : 1 : uint32_t initial_timeout = IS_ENABLED(CONFIG_TICKLESS_KERNEL) ?
634 : : (COUNTER_HALF_SPAN - 1) :
635 : : (counter() + CYC_PER_TICK);
636 : :
637 : 1 : compare_set(0, initial_timeout, sys_clock_timeout_handler, NULL);
638 : :
639 : 1 : z_nrf_clock_control_lf_on(mode);
640 : :
641 : 1 : return 0;
642 : : }
643 : :
644 : : SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2,
645 : : CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
|