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

This commit is contained in:
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 {
regs: &'static mut regs::RegisterBlock,
enabled: bool,
count_down: super::timer::global::CountDown,
count_down: super::timer::global::CountDown<Milliseconds>,
timeout_ms: Milliseconds,
}

View File

@ -19,7 +19,7 @@ impl log::Log for Logger {
if self.enabled(record.metadata()) {
let timestamp = unsafe {
GlobalTimer::get()
}.get_us();
}.get_us().0;
let seconds = 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.
pub struct SDIO {
regs: &'static mut regs::RegisterBlock,
count_down: super::timer::global::CountDown,
count_down: super::timer::global::CountDown<Milliseconds>,
input_clk_hz: u32,
card_type: CardType,
card_detect: bool,

View File

@ -8,3 +8,18 @@ impl core::ops::Add for Milliseconds {
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 libregister::{RegisterR, RegisterW};
use crate::{
clocks::Clocks,
mpcore,
time::Milliseconds,
time::{Milliseconds, Microseconds, TimeSource},
};
/// "uptime"
@ -79,41 +80,82 @@ impl GlobalTimer {
}
/// 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 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
/// `embedded_hal::timer::CountDown`
pub fn countdown(&self) -> CountDown {
pub fn countdown<U>(&self) -> CountDown<U>
where
Self: TimeSource<U>,
{
CountDown {
timer: self.clone(),
timeout: Milliseconds(0),
timeout: self.now(),
}
}
}
#[derive(Clone)]
pub struct CountDown {
timer: GlobalTimer,
timeout: Milliseconds,
impl TimeSource<Milliseconds> for GlobalTimer {
fn now(&self) -> Milliseconds {
self.get_time()
}
}
impl embedded_hal::timer::CountDown for CountDown {
type Time = Milliseconds;
impl TimeSource<Microseconds> for GlobalTimer {
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) {
self.timeout = self.timer.get_time() + count.into();
self.timeout = self.timer.now() + count.into();
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.timer.get_time() <= self.timeout {
if self.timer.now() <= self.timeout {
Err(nb::Error::WouldBlock)
} else {
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();
}
}