From ced8aa4f9c4033a5b87765ae50758a11903de5d3 Mon Sep 17 00:00:00 2001 From: Peter Taylor Date: Tue, 30 Jun 2020 17:38:57 -0600 Subject: [PATCH] feat(Clock): Allow `Clock` impls to be stateful --- CHANGELOG.md | 1 + examples/nrf52_dk/main.rs | 64 ++++++++++++++++++--------------------- src/clock.rs | 8 ++--- src/instant.rs | 21 +++++++------ src/lib.rs | 29 ++++++++++-------- 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2e4dc4..f7906b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Changed +- Add `&mut self` to `Clock` functions (make stateful, or at least allow stateful implementations) - All time-type inner types from signed to unsigned - `Instant::duration_since()` return type to `Result` - Refactor `examples/nrf52_dk` diff --git a/examples/nrf52_dk/main.rs b/examples/nrf52_dk/main.rs index a47af02..cf6fbee 100644 --- a/examples/nrf52_dk/main.rs +++ b/examples/nrf52_dk/main.rs @@ -3,10 +3,8 @@ extern crate panic_rtt; -use cortex_m::mutex::CriticalSectionMutex as Mutex; use cortex_m_rt::entry; -use embedded_time::{self as time, traits::*, Clock, Instant, Period}; -use mutex_trait::Mutex as _; +use embedded_time::{self as time, traits::*}; pub mod nrf52 { pub use nrf52832_hal::{ @@ -14,47 +12,42 @@ pub mod nrf52 { prelude::*, target::{self as pac, Peripherals}, }; +} - pub struct Clock64 { - low: pac::TIMER0, - high: pac::TIMER1, - capture_task: pac::EGU0, - } - - impl Clock64 { - pub fn take(low: pac::TIMER0, high: pac::TIMER1, capture_task: pac::EGU0) -> Self { - Self { - low, - high, - capture_task, - } - } +pub struct SysClock { + low: nrf52::pac::TIMER0, + high: nrf52::pac::TIMER1, + capture_task: nrf52::pac::EGU0, +} - pub(crate) fn read(&mut self) -> u64 { - self.capture_task.tasks_trigger[0].write(|write| unsafe { write.bits(1) }); - self.low.cc[0].read().bits() as u64 | ((self.high.cc[0].read().bits() as u64) << 32) +impl SysClock { + pub fn take( + low: nrf52::pac::TIMER0, + high: nrf52::pac::TIMER1, + capture_task: nrf52::pac::EGU0, + ) -> Self { + Self { + low, + high, + capture_task, } } } -pub struct SysClock; - impl time::Clock for SysClock { type Rep = u64; - const PERIOD: Period = ::new(1, 16_000_000); + const PERIOD: time::Period = ::new(1, 16_000_000); - fn now() -> Instant { - let ticks = (&CLOCK64).lock(|clock| match clock { - Some(clock) => clock.read(), - None => 0, - }); + fn now(&mut self) -> time::Instant { + self.capture_task.tasks_trigger[0].write(|write| unsafe { write.bits(1) }); - Instant::new(ticks as Self::Rep) + let ticks = + self.low.cc[0].read().bits() as u64 | ((self.high.cc[0].read().bits() as u64) << 32); + + time::Instant::new(ticks as Self::Rep) } } -static CLOCK64: Mutex> = Mutex::new(None); - #[entry] fn main() -> ! { let device = nrf52::pac::Peripherals::take().unwrap(); @@ -106,8 +99,7 @@ fn main() -> ! { // This moves these peripherals to prevent conflicting usage, however not the entire EGU0 is // used. A ref to EGU0 could be sent instead, although that provides no protection for the // fields that are being used by Clock64. - let clock64 = nrf52::Clock64::take(device.TIMER0, device.TIMER1, device.EGU0); - (&CLOCK64).lock(|ticks| *ticks = Some(clock64)); + let mut clock = SysClock::take(device.TIMER0, device.TIMER1, device.EGU0); let port0 = nrf52::gpio::p0::Parts::new(device.P0); @@ -136,6 +128,7 @@ fn main() -> ! { &mut led2.degrade(), &mut led3.degrade(), &mut led4.degrade(), + &mut clock, ) .unwrap(); @@ -147,6 +140,7 @@ fn run( led2: &mut Led, led3: &mut Led, led4: &mut Led, + clock: &mut SysClock, ) -> Result<(), ::Error> where Led: nrf52::OutputPin, @@ -156,12 +150,12 @@ where led2.set_high()?; led3.set_high()?; led4.set_low()?; - SysClock::delay(250_u32.milliseconds()); + clock.delay(250_u32.milliseconds()); led1.set_high()?; led2.set_low()?; led3.set_low()?; led4.set_high()?; - SysClock::delay(250_u32.milliseconds()); + clock.delay(250_u32.milliseconds()); } } diff --git a/src/clock.rs b/src/clock.rs index bcb7e85..9a14faf 100644 --- a/src/clock.rs +++ b/src/clock.rs @@ -10,15 +10,15 @@ pub trait Clock: Sized { const PERIOD: Period; /// Get the current Instant - fn now() -> Instant; + fn now(&mut self) -> Instant; /// Blocking delay - fn delay(dur: Dur) + fn delay(&mut self, dur: Dur) where Self::Rep: TryFrom, { - let start = Self::now(); + let start = self.now(); let end = start + dur; - while Self::now() < end {} + while self.now() < end {} } } diff --git a/src/instant.rs b/src/instant.rs index b684711..b56a9a5 100644 --- a/src/instant.rs +++ b/src/instant.rs @@ -38,7 +38,7 @@ impl Instant { /// type Rep = u32; /// const PERIOD: Period = ::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// assert_eq!(Instant::::new(5).duration_since::>(&Instant::::new(3)), @@ -74,7 +74,7 @@ impl Instant { /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// assert_eq!(Instant::::new(5).duration_until::>(&Instant::::new(7)), @@ -99,6 +99,7 @@ impl Instant { pub fn duration_since_epoch(&self) -> Result where Dur::Rep: TryFrom, + Clock::Rep: TryFrom, { Self::duration_since::( &self, @@ -137,7 +138,7 @@ impl PartialOrd for Instant { /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// assert!(Instant::::new(5) > Instant::::new(3)); @@ -177,7 +178,7 @@ where /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// Instant::::new(1) + Seconds(u32::MAX); @@ -193,7 +194,7 @@ where /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// let _ = Instant::::new(0) + Milliseconds(i32::MAX as u32 + 1); @@ -210,7 +211,7 @@ where /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// assert_eq!(Instant::::new(1) + Seconds(3_u32), Instant::::new(3_001)); @@ -250,7 +251,7 @@ where /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// Instant::::new(1) - Seconds(u32::MAX); @@ -266,7 +267,7 @@ where /// type Rep = u32; /// const PERIOD: Period = ::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// let _ = Instant::::new(u32::MAX) - Milliseconds(i32::MAX as u32 + 1); @@ -283,7 +284,7 @@ where /// type Rep = u32; /// const PERIOD: Period =::new(1, 1_000); /// // ... - /// # fn now() -> Instant {unimplemented!()} + /// # fn now(&mut self) -> Instant {unimplemented!()} /// } /// /// assert_eq!(Instant::::new(800) - Milliseconds(700_u32), Instant::::new(100)); @@ -314,7 +315,7 @@ mod tests { type Rep = u32; const PERIOD: Period = ::new(1, 1_000); - fn now() -> Instant { + fn now(&mut self) -> Instant { unimplemented!() } } diff --git a/src/lib.rs b/src/lib.rs index 81bcc89..54000a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,15 +46,16 @@ //! type Rep = u64; //! const PERIOD: Period = ::new(1, 16_000_000); //! -//! fn now() -> Instant { +//! fn now(&mut self) -> Instant { //! // ... //! # unimplemented!() //! } //! } //! -//! let instant1 = SomeClock::now(); +//! let mut clock = SomeClock; +//! let instant1 = clock.now(); //! // ... -//! let instant2 = SomeClock::now(); +//! let instant2 = clock.now(); //! assert!(instant1 < instant2); // instant1 is *before* instant2 //! //! // duration is the difference between the instances @@ -121,7 +122,7 @@ mod tests { type Rep = u64; const PERIOD: time::Period = ::new(1, 64_000_000); - fn now() -> time::Instant { + fn now(&mut self) -> time::Instant { time::Instant::new(128_000_000) } } @@ -133,25 +134,29 @@ mod tests { type Rep = u32; const PERIOD: time::Period = ::new(1, 16_000_000); - fn now() -> time::Instant { + fn now(&mut self) -> time::Instant { time::Instant::new(32_000_000) } } - fn get_time() + fn get_time(clock: &mut Clock) where - u32: TryFrom, + u32: TryFrom, + Clock::Rep: TryFrom, { - assert_eq!(M::now().duration_since_epoch(), Ok(Seconds(2_u32))); + assert_eq!(clock.now().duration_since_epoch(), Ok(Seconds(2_u32))); } #[test] fn common_types() { - let then = MockClock32::now(); - let now = MockClock32::now(); + let then = MockClock32.now(); + let now = MockClock32.now(); - get_time::(); - get_time::(); + let mut clock64 = MockClock64 {}; + let mut clock32 = MockClock32 {}; + + get_time(&mut clock64); + get_time(&mut clock32); let then = then - Seconds(1_u32); assert_ne!(then, now);