mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
timer: Mark Timer & Alarm* Send and Sync (#451)
This commit is contained in:
parent
e681b67d9c
commit
42fc266e67
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue