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
@@ -168,13 +172,37 @@ void common_rtc_init(void)
168
172
m_common_rtc_enabled = true;
169
173
}
170
174
175
+ __STATIC_INLINE void rtc_ovf_event_safe_check (void )
176
+ {
177
+ core_util_critical_section_enter ();
178
+
179
+ rtc_ovf_event_check ();
180
+
181
+ core_util_critical_section_exit ();
182
+ }
183
+
184
+
171
185
uint32_t common_rtc_32bit_ticks_get (void )
172
186
{
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 );
187
+ uint32_t ticks ;
188
+ uint32_t prev_overflows ;
189
+
190
+ do {
191
+ prev_overflows = m_common_rtc_overflows ;
192
+
193
+ ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
194
+ // The counter used for time measurements is less than 32 bit wide,
195
+ // so its value is complemented with the number of registered overflows
196
+ // of the counter.
197
+ ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS );
198
+
199
+ // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler)
200
+ // m_common_rtc_overflows might been updated in this call.
201
+ rtc_ovf_event_safe_check ();
202
+
203
+ // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler.
204
+ } while (m_common_rtc_overflows != prev_overflows );
205
+
178
206
return ticks ;
179
207
}
180
208
@@ -213,6 +241,7 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
213
241
uint32_t compare_value =
214
242
(uint32_t )CEIL_DIV ((timestamp64 ) * RTC_INPUT_FREQ , 1000000 );
215
243
244
+ core_util_critical_section_enter ();
216
245
// The COMPARE event occurs when the value in compare register is N and
217
246
// the counter value changes from N-1 to N. Therefore, the minimal safe
218
247
// difference between the compare value to be set and the current counter
@@ -226,6 +255,7 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
226
255
227
256
nrf_rtc_cc_set (COMMON_RTC_INSTANCE , cc_channel , RTC_WRAP (compare_value ));
228
257
nrf_rtc_event_enable (COMMON_RTC_INSTANCE , int_mask );
258
+ core_util_critical_section_exit ();
229
259
}
230
260
//------------------------------------------------------------------------------
231
261
0 commit comments