drivers: timer: nrf_rtc_timer: Fix race condition
RTC interrupt was reading CC value and passing it to the handler. However, higher priority interrupt could preempt RTC interrupt and set new CC value. In that case CC value read in the RTC interrupt context was not the one that triggered the interrupt. Added fallback to COUNTER value if that case is detected. Using COUNTER is not as precise as CC because it returns time when event was handled and not when event occured but it is the only option since CC value is overwritten. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
8cbef2da24
commit
482fae74a8
1 changed files with 12 additions and 0 deletions
|
@ -262,11 +262,23 @@ void rtc_nrf_isr(const void *arg)
|
|||
if (nrf_rtc_int_enable_check(RTC, RTC_CHANNEL_INT_MASK(chan)) &&
|
||||
nrf_rtc_event_check(RTC, RTC_CHANNEL_EVENT_ADDR(chan))) {
|
||||
uint32_t cc_val;
|
||||
uint32_t now;
|
||||
z_nrf_rtc_timer_compare_handler_t handler;
|
||||
|
||||
event_clear(chan);
|
||||
event_disable(chan);
|
||||
cc_val = get_comparator(chan);
|
||||
now = counter();
|
||||
|
||||
/* Higher priority interrupt may already changed cc_val
|
||||
* which now points to the future. In that case return
|
||||
* current counter value. It is less precise than
|
||||
* returning exact CC value but this one is already lost.
|
||||
*/
|
||||
if (counter_sub(now, cc_val) > COUNTER_HALF_SPAN) {
|
||||
cc_val = now;
|
||||
}
|
||||
|
||||
handler = cc_data[chan].callback;
|
||||
cc_data[chan].callback = NULL;
|
||||
if (handler) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue