timer::global: wrap us in Microseconds, impl embedded_hal blocking delay traits

tcp-recv-fnmut
Astro 2020-07-22 23:41:15 +02:00
parent 7f45d10af3
commit f36b1a610e
5 changed files with 73 additions and 16 deletions

View File

@ -10,7 +10,7 @@ mod regs;
pub struct DevC { pub struct DevC {
regs: &'static mut regs::RegisterBlock, regs: &'static mut regs::RegisterBlock,
enabled: bool, enabled: bool,
count_down: super::timer::global::CountDown, count_down: super::timer::global::CountDown<Milliseconds>,
timeout_ms: Milliseconds, timeout_ms: Milliseconds,
} }

View File

@ -19,7 +19,7 @@ impl log::Log for Logger {
if self.enabled(record.metadata()) { if self.enabled(record.metadata()) {
let timestamp = unsafe { let timestamp = unsafe {
GlobalTimer::get() GlobalTimer::get()
}.get_us(); }.get_us().0;
let seconds = timestamp / 1_000_000; let seconds = timestamp / 1_000_000;
let micros = timestamp % 1_000_000; let micros = timestamp % 1_000_000;

View File

@ -14,7 +14,7 @@ use nb;
/// Basic SDIO Struct with common low-level functions. /// Basic SDIO Struct with common low-level functions.
pub struct SDIO { pub struct SDIO {
regs: &'static mut regs::RegisterBlock, regs: &'static mut regs::RegisterBlock,
count_down: super::timer::global::CountDown, count_down: super::timer::global::CountDown<Milliseconds>,
input_clk_hz: u32, input_clk_hz: u32,
card_type: CardType, card_type: CardType,
card_detect: bool, card_detect: bool,

View File

@ -8,3 +8,18 @@ impl core::ops::Add for Milliseconds {
Milliseconds(self.0 + rhs.0) Milliseconds(self.0 + rhs.0)
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Microseconds(pub u64);
impl core::ops::Add for Microseconds {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Microseconds(self.0 + rhs.0)
}
}
pub trait TimeSource<U> {
fn now(&self) -> U;
}

View File

@ -1,9 +1,10 @@
use core::ops::Add;
use void::Void; use void::Void;
use libregister::{RegisterR, RegisterW}; use libregister::{RegisterR, RegisterW};
use crate::{ use crate::{
clocks::Clocks, clocks::Clocks,
mpcore, mpcore,
time::Milliseconds, time::{Milliseconds, Microseconds, TimeSource},
}; };
/// "uptime" /// "uptime"
@ -79,41 +80,82 @@ impl GlobalTimer {
} }
/// read with high precision /// read with high precision
pub fn get_us(&self) -> u64 { pub fn get_us(&self) -> Microseconds {
let prescaler = self.regs.global_timer_control.read().prescaler() as u64; let prescaler = self.regs.global_timer_control.read().prescaler() as u64;
let clocks = Clocks::get(); let clocks = Clocks::get();
1_000_000 * self.get_counter() * (prescaler + 1) / clocks.cpu_3x2x() as u64 Microseconds(1_000_000 * self.get_counter() * (prescaler + 1) / clocks.cpu_3x2x() as u64)
} }
/// return a handle that has implements /// return a handle that has implements
/// `embedded_hal::timer::CountDown` /// `embedded_hal::timer::CountDown`
pub fn countdown(&self) -> CountDown { pub fn countdown<U>(&self) -> CountDown<U>
where
Self: TimeSource<U>,
{
CountDown { CountDown {
timer: self.clone(), timer: self.clone(),
timeout: Milliseconds(0), timeout: self.now(),
} }
} }
} }
#[derive(Clone)] impl TimeSource<Milliseconds> for GlobalTimer {
pub struct CountDown { fn now(&self) -> Milliseconds {
timer: GlobalTimer, self.get_time()
timeout: Milliseconds, }
} }
impl embedded_hal::timer::CountDown for CountDown { impl TimeSource<Microseconds> for GlobalTimer {
type Time = Milliseconds; fn now(&self) -> Microseconds {
self.get_us()
}
}
#[derive(Clone)]
pub struct CountDown<U> {
timer: GlobalTimer,
timeout: U,
}
/// embedded-hal async API
impl<U: Add<Output=U> + PartialOrd> embedded_hal::timer::CountDown for CountDown<U>
where
GlobalTimer: TimeSource<U>,
{
type Time = U;
fn start<T: Into<Self::Time>>(&mut self, count: T) { fn start<T: Into<Self::Time>>(&mut self, count: T) {
self.timeout = self.timer.get_time() + count.into(); self.timeout = self.timer.now() + count.into();
} }
fn wait(&mut self) -> nb::Result<(), Void> { fn wait(&mut self) -> nb::Result<(), Void> {
if self.timer.get_time() <= self.timeout { if self.timer.now() <= self.timeout {
Err(nb::Error::WouldBlock) Err(nb::Error::WouldBlock)
} else { } else {
Ok(()) Ok(())
} }
} }
} }
/// embedded-hal sync API
impl embedded_hal::blocking::delay::DelayMs<u64> for GlobalTimer {
fn delay_ms(&mut self, ms: u64) {
use embedded_hal::timer::CountDown;
let mut countdown = self.countdown::<Milliseconds>();
countdown.start(Milliseconds(ms));
nb::block!(countdown.wait()).unwrap();
}
}
/// embedded-hal sync API
impl embedded_hal::blocking::delay::DelayUs<u64> for GlobalTimer {
fn delay_us(&mut self, us: u64) {
use embedded_hal::timer::CountDown;
let mut countdown = self.countdown::<Microseconds>();
countdown.start(Microseconds(us));
nb::block!(countdown.wait()).unwrap();
}
}