rp-hal-boards/rp2040-hal/src/timer.rs

141 lines
3.8 KiB
Rust
Raw Normal View History

2021-08-15 08:10:39 +10:00
//! Timer Peripheral
// See [Chapter 4 Section 6](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details
2021-08-15 08:10:39 +10:00
use embedded_time::duration::Microseconds;
use crate::pac::{RESETS, TIMER};
use crate::resets::SubsystemReset;
2021-08-15 08:10:39 +10:00
/// Timer peripheral
pub struct Timer {
timer: TIMER,
}
// Safety: All access is read-only.
unsafe impl Sync for Timer {}
2021-08-15 08:10:39 +10:00
impl Timer {
/// Create a new [`Timer`]
pub fn new(timer: TIMER, resets: &mut RESETS) -> Self {
timer.reset_bring_up(resets);
2021-08-15 08:10:39 +10:00
Self { timer }
}
/// Get the current counter value.
pub fn get_counter(&self) -> u64 {
let mut hi0 = self.timer.timerawh.read().bits();
loop {
let low = self.timer.timerawl.read().bits();
let hi1 = self.timer.timerawh.read().bits();
if hi0 == hi1 {
break (u64::from(hi0) << 32) | u64::from(low);
}
hi0 = hi1;
}
}
/// Get the value of the least significant word of the counter.
pub fn get_counter_low(&self) -> u32 {
self.timer.timerawl.read().bits()
}
/// Initialized a Count Down instance without starting it.
pub fn count_down(&self) -> CountDown<'_> {
CountDown {
timer: self,
period: Microseconds::new(0),
next_end: None,
}
}
}
/// Delay implementation
pub struct CountDown<'timer> {
timer: &'timer Timer,
period: embedded_time::duration::Microseconds<u64>,
next_end: Option<u64>,
}
impl embedded_hal::timer::CountDown for CountDown<'_> {
type Time = embedded_time::duration::Microseconds<u64>;
fn start<T>(&mut self, count: T)
where
T: Into<Self::Time>,
{
self.period = count.into();
self.next_end = Some(self.timer.get_counter().wrapping_add(self.period.0));
}
fn wait(&mut self) -> nb::Result<(), void::Void> {
if let Some(end) = self.next_end {
let ts = self.timer.get_counter();
if ts >= end {
self.next_end = Some(end.wrapping_add(self.period.0));
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
} else {
panic!("CountDown is not running!");
}
}
}
#[cfg(feature = "eh1_0_alpha")]
impl eh1_0_alpha::timer::nb::CountDown for CountDown<'_> {
type Time = embedded_time::duration::Microseconds<u64>;
type Error = &'static str;
fn start<T>(&mut self, count: T) -> Result<(), Self::Error>
where
T: Into<Self::Time>,
{
self.period = count.into();
self.next_end = Some(self.timer.get_counter().wrapping_add(self.period.0));
Ok(())
}
fn wait(&mut self) -> nb::Result<(), Self::Error> {
if let Some(end) = self.next_end {
let ts = self.timer.get_counter();
if ts >= end {
self.next_end = Some(end.wrapping_add(self.period.0));
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
} else {
panic!("CountDown is not running!");
}
}
}
impl embedded_hal::timer::Periodic for CountDown<'_> {}
#[cfg(feature = "eh1_0_alpha")]
impl eh1_0_alpha::timer::Periodic for CountDown<'_> {}
impl embedded_hal::timer::Cancel for CountDown<'_> {
type Error = &'static str;
fn cancel(&mut self) -> Result<(), Self::Error> {
if self.next_end.is_none() {
Err("CountDown is not running.")
} else {
self.next_end = None;
Ok(())
}
2021-08-15 08:10:39 +10:00
}
}
#[cfg(feature = "eh1_0_alpha")]
impl eh1_0_alpha::timer::nb::Cancel for CountDown<'_> {
fn cancel(&mut self) -> Result<(), Self::Error> {
if self.next_end.is_none() {
Err("CountDown is not running.")
} else {
self.next_end = None;
Ok(())
}
}
}