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
55
- #if defined(TARGET_MCU_NRF51822 )
56
- void common_rtc_irq_handler (void )
57
- #else
58
- void COMMON_RTC_IRQ_HANDLER (void )
59
- #endif
56
+ __STATIC_INLINE void rtc_ovf_event_check (void )
60
57
{
61
-
62
58
if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW )) {
63
59
nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
64
60
// Don't disable this event. It shall occur periodically.
65
61
66
62
++ m_common_rtc_overflows ;
67
63
}
64
+ }
65
+
66
+ #if defined(TARGET_MCU_NRF51822 )
67
+ void common_rtc_irq_handler (void )
68
+ #else
69
+ void COMMON_RTC_IRQ_HANDLER (void )
70
+ #endif
71
+ {
72
+
73
+ rtc_ovf_event_check ();
68
74
69
75
if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , US_TICKER_EVENT )) {
70
76
us_ticker_irq_handler ();
@@ -144,13 +150,37 @@ void common_rtc_init(void)
144
150
m_common_rtc_enabled = true;
145
151
}
146
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
+
147
163
uint32_t common_rtc_32bit_ticks_get (void )
148
164
{
149
- uint32_t ticks = nrf_rtc_counter_get (COMMON_RTC_INSTANCE );
150
- // The counter used for time measurements is less than 32 bit wide,
151
- // so its value is complemented with the number of registered overflows
152
- // of the counter.
153
- 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
+
154
184
return ticks ;
155
185
}
156
186
@@ -161,7 +191,7 @@ uint64_t common_rtc_64bit_us_get(void)
161
191
return ROUNDED_DIV (((uint64_t )ticks ) * 1000000 , RTC_INPUT_FREQ );
162
192
}
163
193
164
- __STATIC_INLINE void internal_common_rtc_set_interrupt (uint32_t us_timestamp , uint32_t cc_channel ,
194
+ void common_rtc_set_interrupt (uint32_t us_timestamp , uint32_t cc_channel ,
165
195
uint32_t int_mask )
166
196
{
167
197
// The internal counter is clocked with a frequency that cannot be easily
@@ -187,6 +217,8 @@ __STATIC_INLINE void internal_common_rtc_set_interrupt(uint32_t us_timestamp, ui
187
217
uint32_t compare_value =
188
218
(uint32_t )CEIL_DIV ((timestamp64 ) * RTC_INPUT_FREQ , 1000000 );
189
219
220
+
221
+ core_util_critical_section_enter ();
190
222
// The COMPARE event occurs when the value in compare register is N and
191
223
// the counter value changes from N-1 to N. Therefore, the minimal safe
192
224
// difference between the compare value to be set and the current counter
@@ -199,35 +231,8 @@ __STATIC_INLINE void internal_common_rtc_set_interrupt(uint32_t us_timestamp, ui
199
231
200
232
nrf_rtc_cc_set (COMMON_RTC_INSTANCE , cc_channel , RTC_WRAP (compare_value ));
201
233
nrf_rtc_event_enable (COMMON_RTC_INSTANCE , int_mask );
202
- }
203
234
204
- void common_rtc_set_interrupt (uint32_t us_timestamp , uint32_t cc_channel ,
205
- uint32_t int_mask )
206
- {
207
- uint32_t prev_overflows ;
208
-
209
- while (1 )
210
- {
211
- prev_overflows = m_common_rtc_overflows ;
212
-
213
- internal_common_rtc_set_interrupt (us_timestamp , cc_channel , int_mask );
214
-
215
- // check in case of preemption by RTC OVF event (apply if call was from a low priority level)
216
- if (prev_overflows != m_common_rtc_overflows )
217
- {
218
- continue ;
219
- } // check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler)
220
- else if (nrf_rtc_event_pending (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW ))
221
- {
222
- nrf_rtc_event_clear (COMMON_RTC_INSTANCE , NRF_RTC_EVENT_OVERFLOW );
223
- // Don't disable this event. It shall occur periodically.
224
-
225
- ++ m_common_rtc_overflows ;
226
- continue ;
227
- }
228
-
229
- break ;
230
- }
235
+ core_util_critical_section_exit ();
231
236
}
232
237
//------------------------------------------------------------------------------
233
238
0 commit comments