42
42
#include "nrf_drv_common.h"
43
43
#include "nrf_drv_config.h"
44
44
#include "lp_ticker_api.h"
45
+ #include "mbed_critical.h"
45
46
46
47
47
48
//------------------------------------------------------------------------------
52
53
bool m_common_rtc_enabled = false;
53
54
uint32_t volatile m_common_rtc_overflows = 0 ;
54
55
56
+ __STATIC_INLINE void rtc_ovf_event_check (void )
57
+ {
58
+ if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW )) {
59
+ nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
60
+ // Don't disable this event. It shall occur periodically.
61
+
62
+ ++ m_common_rtc_overflows ;
63
+ }
64
+ }
65
+
55
66
#if defined(TARGET_MCU_NRF51822 )
56
67
void common_rtc_irq_handler (void )
57
68
#else
58
69
void COMMON_RTC_IRQ_HANDLER (void )
59
70
#endif
60
71
{
72
+
73
+ rtc_ovf_event_check ();
74
+
61
75
if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , US_TICKER_EVENT )) {
62
76
us_ticker_irq_handler ();
63
77
}
@@ -69,12 +83,6 @@ void COMMON_RTC_IRQ_HANDLER(void)
69
83
}
70
84
#endif
71
85
72
- if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW )) {
73
- nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
74
- // Don't disable this event. It shall occur periodically.
75
-
76
- ++ m_common_rtc_overflows ;
77
- }
78
86
}
79
87
80
88
#if (defined (__ICCARM__ )) && defined(TARGET_MCU_NRF51822 )//IAR
@@ -142,13 +150,37 @@ void common_rtc_init(void)
142
150
m_common_rtc_enabled = true;
143
151
}
144
152
153
+ __STATIC_INLINE void rtc_ovf_event_safe_check (void )
154
+ {
155
+ core_util_critical_section_enter ();
156
+
157
+ rtc_ovf_event_check ();
158
+
159
+ core_util_critical_section_exit ();
160
+ }
161
+
162
+
145
163
uint32_t common_rtc_32bit_ticks_get (void )
146
164
{
147
- uint32_t ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
148
- // The counter used for time measurements is less than 32 bit wide,
149
- // so its value is complemented with the number of registered overflows
150
- // of the counter.
151
- ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS );
165
+ uint32_t ticks ;
166
+ uint32_t prev_overflows ;
167
+
168
+ do {
169
+ prev_overflows = m_common_rtc_overflows ;
170
+
171
+ ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
172
+ // The counter used for time measurements is less than 32 bit wide,
173
+ // so its value is complemented with the number of registered overflows
174
+ // of the counter.
175
+ ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS );
176
+
177
+ // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler)
178
+ // m_common_rtc_overflows might been updated in this call.
179
+ rtc_ovf_event_safe_check ();
180
+
181
+ // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler.
182
+ } while (m_common_rtc_overflows != prev_overflows );
183
+
152
184
return ticks ;
153
185
}
154
186
@@ -185,6 +217,8 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
185
217
uint32_t compare_value =
186
218
(uint32_t )CEIL_DIV ((timestamp64 ) * RTC_INPUT_FREQ , 1000000 );
187
219
220
+
221
+ core_util_critical_section_enter ();
188
222
// The COMPARE event occurs when the value in compare register is N and
189
223
// the counter value changes from N-1 to N. Therefore, the minimal safe
190
224
// difference between the compare value to be set and the current counter
@@ -197,6 +231,8 @@ void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
197
231
198
232
nrf_rtc_cc_set (COMMON_RTC_INSTANCE , cc_channel , RTC_WRAP (compare_value ));
199
233
nrf_rtc_event_enable (COMMON_RTC_INSTANCE , int_mask );
234
+
235
+ core_util_critical_section_exit ();
200
236
}
201
237
//------------------------------------------------------------------------------
202
238
0 commit comments