diff options
| -rw-r--r-- | embassy-nrf/src/rtc.rs | 34 | ||||
| -rw-r--r-- | embassy/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy/src/clock.rs | 21 | ||||
| -rw-r--r-- | embassy/src/lib.rs | 3 | ||||
| -rw-r--r-- | examples/src/bin/rtc_async.rs | 1 | ||||
| -rw-r--r-- | examples/src/bin/rtc_raw.rs | 1 |
6 files changed, 44 insertions, 17 deletions
diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index 95ee1a068..55869c6e5 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use core::cell::Cell; | 1 | use core::cell::Cell; |
| 2 | use core::ops::Deref; | 2 | use core::ops::Deref; |
| 3 | use core::sync::atomic::{AtomicU32, Ordering}; | 3 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 4 | |||
| 5 | use defmt::trace; | 4 | use defmt::trace; |
| 5 | use embassy::clock::Monotonic; | ||
| 6 | 6 | ||
| 7 | use crate::interrupt; | 7 | use crate::interrupt; |
| 8 | use crate::interrupt::Mutex; | 8 | use crate::interrupt::Mutex; |
| @@ -121,12 +121,6 @@ impl<T: Instance> RTC<T> { | |||
| 121 | }) | 121 | }) |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | pub fn now(&self) -> u64 { | ||
| 125 | let counter = self.rtc.counter.read().bits(); | ||
| 126 | let period = self.period.load(Ordering::Relaxed); | ||
| 127 | calc_now(period, counter) | ||
| 128 | } | ||
| 129 | |||
| 130 | fn trigger_alarm(&self) { | 124 | fn trigger_alarm(&self) { |
| 131 | self.rtc.intenclr.write(|w| w.compare1().clear()); | 125 | self.rtc.intenclr.write(|w| w.compare1().clear()); |
| 132 | interrupt::free(|cs| { | 126 | interrupt::free(|cs| { |
| @@ -139,19 +133,19 @@ impl<T: Instance> RTC<T> { | |||
| 139 | }); | 133 | }); |
| 140 | } | 134 | } |
| 141 | 135 | ||
| 142 | fn do_set_alarm(&self, at: u64, f: Option<fn()>) { | 136 | fn do_set_alarm(&self, timestamp: u64, callback: Option<fn()>) { |
| 143 | interrupt::free(|cs| { | 137 | interrupt::free(|cs| { |
| 144 | self.alarm.borrow(cs).set((at, f)); | 138 | self.alarm.borrow(cs).set((timestamp, callback)); |
| 145 | 139 | ||
| 146 | let t = self.now(); | 140 | let t = self.now(); |
| 147 | if at <= t { | 141 | if timestamp <= t { |
| 148 | self.trigger_alarm(); | 142 | self.trigger_alarm(); |
| 149 | return; | 143 | return; |
| 150 | } | 144 | } |
| 151 | 145 | ||
| 152 | let diff = at - t; | 146 | let diff = timestamp - t; |
| 153 | if diff < 0xc00000 { | 147 | if diff < 0xc00000 { |
| 154 | self.rtc.cc[1].write(|w| unsafe { w.bits(at as u32 & 0xFFFFFF) }); | 148 | self.rtc.cc[1].write(|w| unsafe { w.bits(timestamp as u32 & 0xFFFFFF) }); |
| 155 | self.rtc.intenset.write(|w| w.compare1().set()); | 149 | self.rtc.intenset.write(|w| w.compare1().set()); |
| 156 | 150 | ||
| 157 | // We may have been preempted for arbitrary time between checking if `at` is in the past | 151 | // We may have been preempted for arbitrary time between checking if `at` is in the past |
| @@ -159,7 +153,7 @@ impl<T: Instance> RTC<T> { | |||
| 159 | // So, we check again just in case. | 153 | // So, we check again just in case. |
| 160 | 154 | ||
| 161 | let t = self.now(); | 155 | let t = self.now(); |
| 162 | if at <= t { | 156 | if timestamp <= t { |
| 163 | self.trigger_alarm(); | 157 | self.trigger_alarm(); |
| 164 | return; | 158 | return; |
| 165 | } | 159 | } |
| @@ -168,12 +162,20 @@ impl<T: Instance> RTC<T> { | |||
| 168 | } | 162 | } |
| 169 | }) | 163 | }) |
| 170 | } | 164 | } |
| 165 | } | ||
| 166 | |||
| 167 | impl<T: Instance> Monotonic for RTC<T> { | ||
| 168 | fn now(&self) -> u64 { | ||
| 169 | let counter = self.rtc.counter.read().bits(); | ||
| 170 | let period = self.period.load(Ordering::Relaxed); | ||
| 171 | calc_now(period, counter) | ||
| 172 | } | ||
| 171 | 173 | ||
| 172 | pub fn set_alarm(&self, at: u64, f: fn()) { | 174 | fn set_alarm(&self, timestamp: u64, callback: fn()) { |
| 173 | self.do_set_alarm(at, Some(f)); | 175 | self.do_set_alarm(timestamp, Some(callback)); |
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | pub fn clear_alarm(&self) { | 178 | fn clear_alarm(&self) { |
| 177 | self.do_set_alarm(u64::MAX, None); | 179 | self.do_set_alarm(u64::MAX, None); |
| 178 | } | 180 | } |
| 179 | } | 181 | } |
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index f621015ab..5826e8ba6 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml | |||
| @@ -12,3 +12,4 @@ defmt = "0.1.0" | |||
| 12 | cortex-m = "0.6.3" | 12 | cortex-m = "0.6.3" |
| 13 | futures = { version = "0.3.5", default-features = false, features = [ "async-await" ] } | 13 | futures = { version = "0.3.5", default-features = false, features = [ "async-await" ] } |
| 14 | pin-project = { version = "0.4.23", default-features = false } | 14 | pin-project = { version = "0.4.23", default-features = false } |
| 15 | 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 000000000..ca5f26a05 --- /dev/null +++ b/embassy/src/clock.rs | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /// Monotonic clock with support for setting an alarm. | ||
| 2 | /// | ||
| 3 | /// The clock uses a "tick" time unit, whose length is an implementation-dependent constant. | ||
| 4 | pub trait Monotonic { | ||
| 5 | /// Returns the current timestamp in ticks. | ||
| 6 | /// This is guaranteed to be monotonic, i.e. a call to now() will always return | ||
| 7 | /// a greater or equal value than earler calls. | ||
| 8 | fn now(&self) -> u64; | ||
| 9 | |||
| 10 | /// Sets an alarm at the given timestamp. When the clock reaches that | ||
| 11 | /// timestamp, the provided callback funcion will be called. | ||
| 12 | /// | ||
| 13 | /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. | ||
| 14 | /// | ||
| 15 | /// Only one alarm can be active at a time. This overwrites any previously-set alarm if any. | ||
| 16 | fn set_alarm(&self, timestamp: u64, callback: fn()); | ||
| 17 | |||
| 18 | /// Clears the previously-set alarm. | ||
| 19 | /// If no alarm was set, this is a noop. | ||
| 20 | fn clear_alarm(&self); | ||
| 21 | } | ||
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index 45716c6cf..89eef3f4c 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #![feature(generic_associated_types)] | 3 | #![feature(generic_associated_types)] |
| 4 | #![feature(const_fn)] | 4 | #![feature(const_fn)] |
| 5 | 5 | ||
| 6 | pub mod clock; | ||
| 6 | pub mod flash; | 7 | pub mod flash; |
| 7 | pub mod util; | ||
| 8 | pub mod io; | 8 | pub mod io; |
| 9 | pub mod util; | ||
diff --git a/examples/src/bin/rtc_async.rs b/examples/src/bin/rtc_async.rs index 838a0faef..977621d4c 100644 --- a/examples/src/bin/rtc_async.rs +++ b/examples/src/bin/rtc_async.rs | |||
| @@ -8,6 +8,7 @@ use example_common::*; | |||
| 8 | 8 | ||
| 9 | use core::mem::MaybeUninit; | 9 | use core::mem::MaybeUninit; |
| 10 | use cortex_m_rt::entry; | 10 | use cortex_m_rt::entry; |
| 11 | use embassy::clock::Monotonic; | ||
| 11 | use embassy_nrf::rtc; | 12 | use embassy_nrf::rtc; |
| 12 | use futures_intrusive::timer::{Clock, LocalTimer, LocalTimerService}; | 13 | use futures_intrusive::timer::{Clock, LocalTimer, LocalTimerService}; |
| 13 | use nrf52840_hal::clocks; | 14 | use nrf52840_hal::clocks; |
diff --git a/examples/src/bin/rtc_raw.rs b/examples/src/bin/rtc_raw.rs index 8debf12e3..aa98409c4 100644 --- a/examples/src/bin/rtc_raw.rs +++ b/examples/src/bin/rtc_raw.rs | |||
| @@ -8,6 +8,7 @@ use example_common::*; | |||
| 8 | 8 | ||
| 9 | use core::mem::MaybeUninit; | 9 | use core::mem::MaybeUninit; |
| 10 | use cortex_m_rt::entry; | 10 | use cortex_m_rt::entry; |
| 11 | use embassy::clock::Monotonic; | ||
| 11 | use embassy_nrf::rtc; | 12 | use embassy_nrf::rtc; |
| 12 | use nrf52840_hal::clocks; | 13 | use nrf52840_hal::clocks; |
| 13 | 14 | ||
