timer: Mark Timer & Alarm* Send and Sync (#451)

This commit is contained in:
Wilfried Chauveau 2022-09-14 21:06:08 +01:00 committed by GitHub
parent e681b67d9c
commit 42fc266e67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -14,10 +14,26 @@ use crate::atomic_register_access::{write_bitmask_clear, write_bitmask_set};
use crate::pac::{RESETS, TIMER}; use crate::pac::{RESETS, TIMER};
use crate::resets::SubsystemReset; use crate::resets::SubsystemReset;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::sync::atomic::{AtomicU8, Ordering};
/// Instant type used by the Timer & Alarm methods. /// Instant type used by the Timer & Alarm methods.
pub type Instant = TimerInstantU64<1_000_000>; pub type Instant = TimerInstantU64<1_000_000>;
static ALARMS: AtomicU8 = AtomicU8::new(0x0F);
fn take_alarm(mask: u8) -> bool {
critical_section::with(|_| {
let alarms = ALARMS.load(Ordering::Relaxed);
ALARMS.store(alarms & !mask, Ordering::Relaxed);
(alarms & mask) != 0
})
}
fn release_alarm(mask: u8) {
critical_section::with(|_| {
let alarms = ALARMS.load(Ordering::Relaxed);
ALARMS.store(alarms | mask, Ordering::Relaxed);
});
}
fn get_counter(timer: &crate::pac::timer::RegisterBlock) -> Instant { fn get_counter(timer: &crate::pac::timer::RegisterBlock) -> Instant {
let mut hi0 = timer.timerawh.read().bits(); let mut hi0 = timer.timerawh.read().bits();
let timestamp = loop { let timestamp = loop {
@ -33,7 +49,6 @@ fn get_counter(timer: &crate::pac::timer::RegisterBlock) -> Instant {
/// Timer peripheral /// Timer peripheral
pub struct Timer { pub struct Timer {
timer: TIMER, timer: TIMER,
alarms: [bool; 4],
} }
impl Timer { impl Timer {
@ -41,10 +56,7 @@ impl Timer {
pub fn new(timer: TIMER, resets: &mut RESETS) -> Self { pub fn new(timer: TIMER, resets: &mut RESETS) -> Self {
timer.reset_bring_down(resets); timer.reset_bring_down(resets);
timer.reset_bring_up(resets); timer.reset_bring_up(resets);
Self { Self { timer }
timer,
alarms: [true; 4],
}
} }
/// Get the current counter value. /// Get the current counter value.
@ -65,48 +77,30 @@ impl Timer {
next_end: None, next_end: None,
} }
} }
/// Retrieve a reference to alarm 0. Will only return a value the first time this is called /// Retrieve a reference to alarm 0. Will only return a value the first time this is called
pub fn alarm_0(&mut self) -> Option<Alarm0> { pub fn alarm_0(&mut self) -> Option<Alarm0> {
if self.alarms[0] { take_alarm(1 << 0).then_some(Alarm0(PhantomData))
self.alarms[0] = false;
Some(Alarm0(PhantomData))
} else {
None
}
} }
/// Retrieve a reference to alarm 1. Will only return a value the first time this is called /// Retrieve a reference to alarm 1. Will only return a value the first time this is called
pub fn alarm_1(&mut self) -> Option<Alarm1> { pub fn alarm_1(&mut self) -> Option<Alarm1> {
if self.alarms[1] { take_alarm(1 << 1).then_some(Alarm1(PhantomData))
self.alarms[1] = false;
Some(Alarm1(PhantomData))
} else {
None
}
} }
/// Retrieve a reference to alarm 2. Will only return a value the first time this is called /// Retrieve a reference to alarm 2. Will only return a value the first time this is called
pub fn alarm_2(&mut self) -> Option<Alarm2> { pub fn alarm_2(&mut self) -> Option<Alarm2> {
if self.alarms[2] { take_alarm(1 << 2).then_some(Alarm2(PhantomData))
self.alarms[2] = false;
Some(Alarm2(PhantomData))
} else {
None
}
} }
/// Retrieve a reference to alarm 3. Will only return a value the first time this is called /// Retrieve a reference to alarm 3. Will only return a value the first time this is called
pub fn alarm_3(&mut self) -> Option<Alarm3> { pub fn alarm_3(&mut self) -> Option<Alarm3> {
if self.alarms[3] { take_alarm(1 << 3).then_some(Alarm3(PhantomData))
self.alarms[3] = false;
Some(Alarm3(PhantomData))
} else {
None
}
} }
} }
// safety: all write operations are synchronised and all reads are atomic
unsafe impl Sync for Timer {}
/// Implementation of the embedded_hal::Timer traits using rp2040_hal::timer counter /// Implementation of the embedded_hal::Timer traits using rp2040_hal::timer counter
/// ///
/// ## Usage /// ## Usage
@ -340,6 +334,13 @@ macro_rules! impl_alarm {
(bits & $armed_bit_mask) == 0 (bits & $armed_bit_mask) == 0
} }
} }
impl Drop for $name {
fn drop(&mut self) {
self.disable_interrupt();
release_alarm($armed_bit_mask)
}
}
}; };
} }