723: Fix monotonics race r=AfoHT a=korken89



Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
This commit is contained in:
bors[bot] 2023-04-05 18:22:41 +00:00 committed by GitHub
commit 539d4b1674
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 4 deletions

View file

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

View file

@ -182,6 +182,12 @@ macro_rules! make_timer {
pub async fn delay_until(instant: <Self as Monotonic>::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);
}