55
55
bool m_common_rtc_enabled = false;
56
56
uint32_t volatile m_common_rtc_overflows = 0 ;
57
57
58
+ __STATIC_INLINE void rtc_ovf_event_check (void )
59
+ {
60
+ if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW )) {
61
+ nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
62
+ // Don't disable this event. It shall occur periodically.
63
+
64
+ ++ m_common_rtc_overflows ;
65
+ }
66
+ }
67
+
58
68
#if defined(TARGET_MCU_NRF51822 )
59
69
void common_rtc_irq_handler (void )
60
70
#else
61
71
void COMMON_RTC_IRQ_HANDLER (void )
62
72
#endif
63
73
{
64
- if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , US_TICKER_EVENT ))
65
- {
74
+
75
+ rtc_ovf_event_check ();
76
+
77
+ if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , US_TICKER_EVENT )) {
66
78
us_ticker_irq_handler ();
67
79
}
68
80
69
81
#if DEVICE_LOWPOWERTIMER
70
- if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , LP_TICKER_EVENT ))
71
- {
82
+ if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , LP_TICKER_EVENT )) {
72
83
73
84
lp_ticker_irq_handler ();
74
85
}
75
86
#endif
76
87
77
- if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW ))
78
- {
79
- nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
80
- // Don't disable this event. It shall occur periodically.
81
-
82
- ++ m_common_rtc_overflows ;
83
- }
84
88
}
85
89
86
90
// Function for fix errata 20: RTC Register values are invalid
@@ -107,8 +111,7 @@ void RTC1_IRQHandler(void);
107
111
108
112
void common_rtc_init (void )
109
113
{
110
- if (m_common_rtc_enabled )
111
- {
114
+ if (m_common_rtc_enabled ) {
112
115
return ;
113
116
}
114
117
@@ -168,13 +171,37 @@ void common_rtc_init(void)
168
171
m_common_rtc_enabled = true;
169
172
}
170
173
174
+ __STATIC_INLINE void rtc_ovf_event_safe_check (void )
175
+ {
176
+ core_util_critical_section_enter ();
177
+
178
+ rtc_ovf_event_check ();
179
+
180
+ core_util_critical_section_exit ();
181
+ }
182
+
183
+
171
184
uint32_t common_rtc_32bit_ticks_get (void )
172
185
{
173
- uint32_t ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
174
- // The counter used for time measurements is less than 32 bit wide,
175
- // so its value is complemented with the number of registered overflows
176
- // of the counter.
177
- ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS );
186
+ uint32_t ticks ;
187
+ uint32_t prev_overflows ;
188
+
189
+ do {
190
+ prev_overflows = m_common_rtc_overflows ;
191
+
192
+ ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
193
+ // The counter used for time measurements is less than 32 bit wide,
194
+ // so its value is complemented with the number of registered overflows
195
+ // of the counter.
196
+ ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS );
197
+
198
+ // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler)
199
+ // m_common_rtc_overflows might been updated in this call.
200
+ rtc_ovf_event_safe_check ();
201
+
202
+ // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler.
203
+ } while (m_common_rtc_overflows != prev_overflows );
204
+
178
205
return ticks ;
179
206
}
180
207
@@ -200,32 +227,31 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
200
227
uint64_t current_time64 = common_rtc_64bit_us_get ();
201
228
// [add upper 32 bits from the current time to the timestamp value]
202
229
uint64_t timestamp64 = us_timestamp +
203
- (current_time64 & ~(uint64_t )0xFFFFFFFF );
204
-
230
+ (current_time64 & ~(uint64_t )0xFFFFFFFF );
205
231
// [if the original timestamp value happens to be after the 32 bit counter
206
232
// of microsends overflows, correct the upper 32 bits accordingly]
207
- if (us_timestamp < (uint32_t )(current_time64 & 0xFFFFFFFF ))
208
- {
233
+ if (us_timestamp < (uint32_t )(current_time64 & 0xFFFFFFFF )) {
209
234
timestamp64 += ((uint64_t )1 << 32 );
210
235
}
211
236
// [microseconds -> ticks, always round the result up to avoid too early
212
237
// interrupt generation]
213
238
uint32_t compare_value =
214
239
(uint32_t )CEIL_DIV ((timestamp64 ) * RTC_INPUT_FREQ , 1000000 );
215
240
241
+ core_util_critical_section_enter ();
216
242
// The COMPARE event occurs when the value in compare register is N and
217
243
// the counter value changes from N-1 to N. Therefore, the minimal safe
218
244
// difference between the compare value to be set and the current counter
219
245
// value is 2 ticks. This guarantees that the compare trigger is properly
220
246
// setup before the compare condition occurs.
221
247
uint32_t closest_safe_compare = common_rtc_32bit_ticks_get () + 2 ;
222
- if ((int )(compare_value - closest_safe_compare ) <= 0 )
223
- {
248
+ if ((int )(compare_value - closest_safe_compare ) <= 0 ) {
224
249
compare_value = closest_safe_compare ;
225
250
}
226
251
227
252
nrf_rtc_cc_set (COMMON_RTC_INSTANCE , cc_channel , RTC_WRAP (compare_value ));
228
253
nrf_rtc_event_enable (COMMON_RTC_INSTANCE , int_mask );
254
+ core_util_critical_section_exit ();
229
255
}
230
256
//------------------------------------------------------------------------------
231
257
@@ -284,7 +310,7 @@ static uint32_t previous_tick_cc_value = 0;
284
310
*/
285
311
MBED_WEAK uint32_t const os_trv ;
286
312
MBED_WEAK uint32_t const os_clockrate ;
287
- MBED_WEAK void OS_Tick_Handler ()
313
+ MBED_WEAK void OS_Tick_Handler (void )
288
314
{
289
315
}
290
316
@@ -431,14 +457,11 @@ static uint32_t get_next_tick_cc_delta()
431
457
{
432
458
uint32_t delta = 0 ;
433
459
434
- if (os_clockrate != 1000 )
435
- {
460
+ if (os_clockrate != 1000 ) {
436
461
// In RTX, by default SYSTICK is is used.
437
462
// A tick event is generated every os_trv + 1 clock cycles of the system timer.
438
463
delta = os_trv + 1 ;
439
- }
440
- else
441
- {
464
+ } else {
442
465
// If the clockrate is set to 1000us then 1000 tick should happen every second.
443
466
// Unfortunatelly, when clockrate is set to 1000, os_trv is equal to 31.
444
467
// If (os_trv + 1) is used as the delta value between two ticks, 1000 ticks will be
@@ -454,24 +477,19 @@ static uint32_t get_next_tick_cc_delta()
454
477
// Every five ticks (20%, 200 delta in one second), the delta is equal to 32
455
478
// The remaining (32) deltas equal to 32 are distributed using primes numbers.
456
479
static uint32_t counter = 0 ;
457
- if ((counter % 5 ) == 0 || (counter % 31 ) == 0 || (counter % 139 ) == 0 || (counter == 503 ))
458
- {
480
+ if ((counter % 5 ) == 0 || (counter % 31 ) == 0 || (counter % 139 ) == 0 || (counter == 503 )) {
459
481
delta = 32 ;
460
- }
461
- else
462
- {
482
+ } else {
463
483
delta = 33 ;
464
484
}
465
485
++ counter ;
466
- if (counter == 1000 )
467
- {
486
+ if (counter == 1000 ) {
468
487
counter = 0 ;
469
488
}
470
489
}
471
490
return delta ;
472
491
}
473
492
474
-
475
493
static inline void clear_tick_interrupt ()
476
494
{
477
495
nrf_rtc_event_clear (COMMON_RTC_INSTANCE , OS_TICK_EVENT );
@@ -489,27 +507,18 @@ static inline bool is_in_wrapped_range(uint32_t begin, uint32_t end, uint32_t va
489
507
{
490
508
// regular case, begin < end
491
509
// return true if begin <= val < end
492
- if (begin < end )
493
- {
494
- if (begin <= val && val < end )
495
- {
510
+ if (begin < end ) {
511
+ if (begin <= val && val < end ) {
496
512
return true;
497
- }
498
- else
499
- {
513
+ } else {
500
514
return false;
501
515
}
502
- }
503
- else
504
- {
516
+ } else {
505
517
// In this case end < begin because it has wrap around the limits
506
518
// return false if end < val < begin
507
- if (end < val && val < begin )
508
- {
519
+ if (end < val && val < begin ) {
509
520
return false;
510
- }
511
- else
512
- {
521
+ } else {
513
522
return true;
514
523
}
515
524
}
@@ -536,8 +545,7 @@ static void register_next_tick()
536
545
uint32_t current_counter = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
537
546
538
547
// If an overflow occur, set the next tick in COUNTER + delta clock cycles
539
- if (is_in_wrapped_range (previous_tick_cc_value , new_compare_value , current_counter + 1 ) == false)
540
- {
548
+ if (is_in_wrapped_range (previous_tick_cc_value , new_compare_value , current_counter + 1 ) == false) {
541
549
new_compare_value = current_counter + delta ;
542
550
}
543
551
nrf_rtc_cc_set (COMMON_RTC_INSTANCE , OS_TICK_CC_CHANNEL , new_compare_value );
@@ -603,29 +611,20 @@ uint32_t os_tick_val(void)
603
611
uint32_t next_tick_cc_value = nrf_rtc_cc_get (COMMON_RTC_INSTANCE , OS_TICK_CC_CHANNEL );
604
612
605
613
// do not use os_tick_ovf because its counter value can be different
606
- if (is_in_wrapped_range (previous_tick_cc_value , next_tick_cc_value , current_counter ))
607
- {
608
- if (next_tick_cc_value > previous_tick_cc_value )
609
- {
614
+ if (is_in_wrapped_range (previous_tick_cc_value , next_tick_cc_value , current_counter )) {
615
+ if (next_tick_cc_value > previous_tick_cc_value ) {
610
616
return next_tick_cc_value - current_counter ;
611
- }
612
- else if (current_counter <= next_tick_cc_value )
613
- {
617
+ } else if (current_counter <= next_tick_cc_value ) {
614
618
return next_tick_cc_value - current_counter ;
615
- }
616
- else
617
- {
619
+ } else {
618
620
return next_tick_cc_value + (MAX_RTC_COUNTER_VAL - current_counter );
619
621
}
620
- }
621
- else
622
- {
622
+ } else {
623
623
// use (os_trv + 1) has the base step, can be totally inacurate ...
624
624
uint32_t clock_cycles_by_tick = os_trv + 1 ;
625
625
626
626
// if current counter has wrap arround, add the limit to it.
627
- if (current_counter < next_tick_cc_value )
628
- {
627
+ if (current_counter < next_tick_cc_value ) {
629
628
current_counter = current_counter + MAX_RTC_COUNTER_VAL ;
630
629
}
631
630
0 commit comments