5555bool m_common_rtc_enabled = false;
5656uint32_t volatile m_common_rtc_overflows = 0 ;
5757
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+
5868#if defined(TARGET_MCU_NRF51822 )
5969void common_rtc_irq_handler (void )
6070#else
6171void COMMON_RTC_IRQ_HANDLER (void )
6272#endif
6373{
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 )) {
6678 us_ticker_irq_handler ();
6779 }
6880
6981#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 )) {
7283
7384 lp_ticker_irq_handler ();
7485 }
7586#endif
7687
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- }
8488}
8589
8690// Function for fix errata 20: RTC Register values are invalid
@@ -168,13 +172,37 @@ void common_rtc_init(void)
168172 m_common_rtc_enabled = true;
169173}
170174
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+
171185uint32_t common_rtc_32bit_ticks_get (void )
172186{
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+
178206 return ticks ;
179207}
180208
@@ -213,6 +241,7 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
213241 uint32_t compare_value =
214242 (uint32_t )CEIL_DIV ((timestamp64 ) * RTC_INPUT_FREQ , 1000000 );
215243
244+ core_util_critical_section_enter ();
216245 // The COMPARE event occurs when the value in compare register is N and
217246 // the counter value changes from N-1 to N. Therefore, the minimal safe
218247 // 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,
226255
227256 nrf_rtc_cc_set (COMMON_RTC_INSTANCE , cc_channel , RTC_WRAP (compare_value ));
228257 nrf_rtc_event_enable (COMMON_RTC_INSTANCE , int_mask );
258+ core_util_critical_section_exit ();
229259}
230260//------------------------------------------------------------------------------
231261
0 commit comments