diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index 95ee1a06..55869c6e 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs @@ -1,8 +1,8 @@ use core::cell::Cell; use core::ops::Deref; use core::sync::atomic::{AtomicU32, Ordering}; - use defmt::trace; +use embassy::clock::Monotonic; use crate::interrupt; use crate::interrupt::Mutex; @@ -121,12 +121,6 @@ impl RTC { }) } - pub fn now(&self) -> u64 { - let counter = self.rtc.counter.read().bits(); - let period = self.period.load(Ordering::Relaxed); - calc_now(period, counter) - } - fn trigger_alarm(&self) { self.rtc.intenclr.write(|w| w.compare1().clear()); interrupt::free(|cs| { @@ -139,19 +133,19 @@ impl RTC { }); } - fn do_set_alarm(&self, at: u64, f: Option) { + fn do_set_alarm(&self, timestamp: u64, callback: Option) { interrupt::free(|cs| { - self.alarm.borrow(cs).set((at, f)); + self.alarm.borrow(cs).set((timestamp, callback)); let t = self.now(); - if at <= t { + if timestamp <= t { self.trigger_alarm(); return; } - let diff = at - t; + let diff = timestamp - t; if diff < 0xc00000 { - self.rtc.cc[1].write(|w| unsafe { w.bits(at as u32 & 0xFFFFFF) }); + self.rtc.cc[1].write(|w| unsafe { w.bits(timestamp as u32 & 0xFFFFFF) }); self.rtc.intenset.write(|w| w.compare1().set()); // We may have been preempted for arbitrary time between checking if `at` is in the past @@ -159,7 +153,7 @@ impl RTC { // So, we check again just in case. let t = self.now(); - if at <= t { + if timestamp <= t { self.trigger_alarm(); return; } @@ -168,12 +162,20 @@ impl RTC { } }) } +} - pub fn set_alarm(&self, at: u64, f: fn()) { - self.do_set_alarm(at, Some(f)); +impl Monotonic 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 fn clear_alarm(&self) { + fn set_alarm(&self, timestamp: u64, callback: fn()) { + self.do_set_alarm(timestamp, Some(callback)); + } + + fn clear_alarm(&self) { self.do_set_alarm(u64::MAX, None); } } diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index f621015a..5826e8ba 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml @@ -12,3 +12,4 @@ defmt = "0.1.0" cortex-m = "0.6.3" futures = { version = "0.3.5", default-features = false, features = [ "async-await" ] } pin-project = { version = "0.4.23", default-features = false } +futures-intrusive = { version = "0.3.1", default-features = false } diff --git a/embassy/src/clock.rs b/embassy/src/clock.rs new file mode 100644 index 00000000..ca5f26a0 --- /dev/null +++ b/embassy/src/clock.rs @@ -0,0 +1,21 @@ +/// Monotonic clock with support for setting an alarm. +/// +/// The clock uses a "tick" time unit, whose length is an implementation-dependent constant. +pub trait Monotonic { + /// Returns 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; + + /// Sets an alarm at the given timestamp. When the clock reaches that + /// timestamp, the provided callback funcion will be called. + /// + /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. + /// + /// Only one alarm can be active at a time. This overwrites any previously-set alarm if any. + fn set_alarm(&self, timestamp: u64, callback: fn()); + + /// Clears the previously-set alarm. + /// If no alarm was set, this is a noop. + fn clear_alarm(&self); +} diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index 45716c6c..89eef3f4 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs @@ -3,6 +3,7 @@ #![feature(generic_associated_types)] #![feature(const_fn)] +pub mod clock; pub mod flash; -pub mod util; pub mod io; +pub mod util; diff --git a/examples/src/bin/rtc_async.rs b/examples/src/bin/rtc_async.rs index 838a0fae..977621d4 100644 --- a/examples/src/bin/rtc_async.rs +++ b/examples/src/bin/rtc_async.rs @@ -8,6 +8,7 @@ use example_common::*; use core::mem::MaybeUninit; use cortex_m_rt::entry; +use embassy::clock::Monotonic; use embassy_nrf::rtc; use futures_intrusive::timer::{Clock, LocalTimer, LocalTimerService}; use nrf52840_hal::clocks; diff --git a/examples/src/bin/rtc_raw.rs b/examples/src/bin/rtc_raw.rs index 8debf12e..aa98409c 100644 --- a/examples/src/bin/rtc_raw.rs +++ b/examples/src/bin/rtc_raw.rs @@ -8,6 +8,7 @@ use example_common::*; use core::mem::MaybeUninit; use cortex_m_rt::entry; +use embassy::clock::Monotonic; use embassy_nrf::rtc; use nrf52840_hal::clocks;