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:
Krzysztof Chruscinski 2021-07-19 08:13:45 +02:00 committed by Carles Cufí
commit 482fae74a8

View file

@ -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) {