diff --git a/rtic-monotonics/src/nrf/rtc.rs b/rtic-monotonics/src/nrf/rtc.rs index 03610c015b..2e23389f19 100644 --- a/rtic-monotonics/src/nrf/rtc.rs +++ b/rtic-monotonics/src/nrf/rtc.rs @@ -189,13 +189,18 @@ macro_rules! make_rtc { // and the flag here. critical_section::with(|_| { let rtc = unsafe { &*$rtc::PTR }; - let cnt = rtc.counter.read().bits() as u64; + let cnt = rtc.counter.read().bits(); + // OVERFLOW HAPPENS HERE race needs to be handled let ovf = if Self::is_overflow() { $overflow.load(Ordering::Relaxed) + 1 } else { $overflow.load(Ordering::Relaxed) } as u64; + // Check and fix if above race happened + let new_cnt = rtc.counter.read().bits(); + let cnt = if new_cnt >= cnt { cnt } else { new_cnt } as u64; + Self::Instant::from_ticks((ovf << 24) | cnt) }) } diff --git a/rtic-monotonics/src/nrf/timer.rs b/rtic-monotonics/src/nrf/timer.rs index db5316f237..5e8fe932b4 100644 --- a/rtic-monotonics/src/nrf/timer.rs +++ b/rtic-monotonics/src/nrf/timer.rs @@ -182,6 +182,12 @@ macro_rules! make_timer { pub async fn delay_until(instant: ::Instant) { $tq.delay_until(instant).await; } + + #[inline(always)] + fn is_overflow() -> bool { + let timer = unsafe { &*$timer::PTR }; + timer.events_compare[1].read().bits() & 1 != 0 + } } #[cfg(feature = "embedded-hal-async")] @@ -213,17 +219,22 @@ macro_rules! make_timer { critical_section::with(|_| { let timer = unsafe { &*$timer::PTR }; timer.tasks_capture[2].write(|w| unsafe { w.bits(1) }); + let cnt = timer.cc[2].read().bits(); - let unhandled_overflow = if timer.events_compare[1].read().bits() & 1 != 0 { + let unhandled_overflow = if Self::is_overflow() { // The overflow has not been handled yet, so add an extra to the read overflow. 1 } else { 0 }; + timer.tasks_capture[2].write(|w| unsafe { w.bits(1) }); + let new_cnt = timer.cc[2].read().bits(); + let cnt = if new_cnt >= cnt { cnt } else { new_cnt } as u64; + Self::Instant::from_ticks( (unhandled_overflow + $overflow.load(Ordering::Relaxed) as u64) << 32 - | timer.cc[2].read().bits() as u64, + | cnt as u64, ) }) } @@ -232,7 +243,7 @@ macro_rules! make_timer { let timer = unsafe { &*$timer::PTR }; // If there is a compare match on channel 1, it is an overflow - if timer.events_compare[1].read().bits() & 1 != 0 { + if Self::is_overflow() { timer.events_compare[1].write(|w| w); $overflow.fetch_add(1, Ordering::SeqCst); }