diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index f28ad1da..ae8d0dbc 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs @@ -2,6 +2,8 @@ use core::cell::Cell; use core::ops::Deref; use core::sync::atomic::{AtomicU32, Ordering}; +use embassy::time::Clock; + use crate::interrupt; use crate::interrupt::{CriticalSection, Mutex}; use crate::pac::{rtc0, Interrupt, RTC0, RTC1}; @@ -100,12 +102,6 @@ impl RTC { interrupt::enable(T::INTERRUPT); } - pub fn now(&self) -> u64 { - let counter = self.rtc.counter.read().bits(); - let period = self.period.load(Ordering::Relaxed); - calc_now(period, counter) - } - fn on_interrupt(&self) { if self.rtc.events_ovrflw.read().bits() == 1 { self.rtc.events_ovrflw.write(|w| w); @@ -203,6 +199,14 @@ impl RTC { } } +impl embassy::time::Clock for RTC { + fn now(&self) -> u64 { + let counter = self.rtc.counter.read().bits(); + let period = self.period.load(Ordering::Relaxed); + calc_now(period, counter) + } +} + pub struct Alarm { n: usize, rtc: &'static RTC, diff --git a/embassy/src/time.rs b/embassy/src/time.rs index eba2e6eb..29453bc0 100644 --- a/embassy/src/time.rs +++ b/embassy/src/time.rs @@ -7,21 +7,17 @@ use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; use core::task::{Context, Poll}; +use crate::util::*; use fi::LocalTimer; use futures_intrusive::timer as fi; +static mut CLOCK: Option<&'static dyn Clock> = None; -static mut CLOCK: fn() -> u64 = clock_not_set; - -fn clock_not_set() -> u64 { - panic!("No clock set. You must call embassy::time::set_clock() before trying to use the clock") -} - -pub unsafe fn set_clock(clock: fn() -> u64) { - CLOCK = clock; +pub unsafe fn set_clock(clock: &'static dyn Clock) { + CLOCK = Some(clock); } fn now() -> u64 { - unsafe { CLOCK() } + unsafe { CLOCK.dexpect(defmt::intern!("No clock set")).now() } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -270,6 +266,19 @@ impl Future for Timer { unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }.poll(cx) } } +/// Monotonic clock +pub trait Clock { + /// Return the current timestamp in ticks. + /// This is guaranteed to be monotonic, i.e. a call to now() will always return + /// a greater or equal value than earler calls. + fn now(&self) -> u64; +} + +impl Clock for &T { + fn now(&self) -> u64 { + T::now(self) + } +} /// Trait to register a callback at a given timestamp. pub trait Alarm { @@ -289,3 +298,15 @@ pub trait Alarm { /// If no alarm was set, this is a noop. fn clear(&self); } + +impl Alarm for &T { + fn set_callback(&self, callback: fn()) { + T::set_callback(self, callback); + } + fn set(&self, timestamp: u64) { + T::set(self, timestamp); + } + fn clear(&self) { + T::clear(self) + } +} diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs index 3a0f11e6..601a9b4a 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs @@ -11,7 +11,7 @@ pub use waker_store::*; mod drop_bomb; pub use drop_bomb::*; -use defmt::{warn, error}; +use defmt::{debug, error, info, intern, trace, warn}; pub trait Dewrap { /// dewrap = defmt unwrap diff --git a/examples/src/bin/rtc_async.rs b/examples/src/bin/rtc_async.rs index 3bffabf0..a4149ef1 100644 --- a/examples/src/bin/rtc_async.rs +++ b/examples/src/bin/rtc_async.rs @@ -9,7 +9,7 @@ use example_common::*; use core::mem::MaybeUninit; use cortex_m_rt::entry; use embassy::executor::{task, Executor, WfeModel}; -use embassy::time::{Duration, Instant, Timer}; +use embassy::time::{Clock, Duration, Timer}; use embassy_nrf::pac; use embassy_nrf::rtc; use nrf52840_hal::clocks; @@ -51,7 +51,7 @@ fn main() -> ! { }; rtc.start(); - unsafe { embassy::time::set_clock(|| RTC.as_ptr().as_ref().unwrap().now()) }; + unsafe { embassy::time::set_clock(rtc) }; let executor: &'static _ = unsafe { let ptr = EXECUTOR.as_mut_ptr(); diff --git a/examples/src/bin/rtc_raw.rs b/examples/src/bin/rtc_raw.rs index 8311c1bc..4453ecae 100644 --- a/examples/src/bin/rtc_raw.rs +++ b/examples/src/bin/rtc_raw.rs @@ -8,7 +8,7 @@ use example_common::*; use core::mem::MaybeUninit; use cortex_m_rt::entry; -use embassy::time::Alarm; +use embassy::time::{Alarm, Clock}; use embassy_nrf::rtc; use nrf52840_hal::clocks;