aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml5
-rw-r--r--embassy-nrf/src/rtc.rs35
-rw-r--r--embassy/Cargo.toml1
-rw-r--r--embassy/src/clock.rs21
-rw-r--r--embassy/src/executor.rs72
-rw-r--r--embassy/src/lib.rs3
-rw-r--r--embassy/src/time.rs287
-rw-r--r--examples/Cargo.toml3
-rw-r--r--examples/src/bin/rtc_async.rs61
-rw-r--r--examples/src/bin/rtc_raw.rs7
11 files changed, 413 insertions, 83 deletions
diff --git a/.gitignore b/.gitignore
index 96ef6c0b9..25d18d5aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
1/target 1/target
2Cargo.lock 2Cargo.lock
3third_party
diff --git a/Cargo.toml b/Cargo.toml
index 25e30eff1..abce83ec6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,11 +6,16 @@ members = [
6 "examples", 6 "examples",
7] 7]
8 8
9exclude = [
10 "third_party"
11]
12
9[patch.crates-io] 13[patch.crates-io]
10panic-probe = { git = "https://github.com/knurling-rs/probe-run", branch="main" } 14panic-probe = { git = "https://github.com/knurling-rs/probe-run", branch="main" }
11defmt-rtt = { git = "https://github.com/knurling-rs/defmt", branch="cursed-symbol-names-linkers-must-repent-for-their-sins" } 15defmt-rtt = { git = "https://github.com/knurling-rs/defmt", branch="cursed-symbol-names-linkers-must-repent-for-their-sins" }
12defmt = { git = "https://github.com/knurling-rs/defmt", branch="cursed-symbol-names-linkers-must-repent-for-their-sins" } 16defmt = { git = "https://github.com/knurling-rs/defmt", branch="cursed-symbol-names-linkers-must-repent-for-their-sins" }
13static-executor = { git = "https://github.com/Dirbaio/static-executor", branch="multi"} 17static-executor = { git = "https://github.com/Dirbaio/static-executor", branch="multi"}
18futures-intrusive = { git = "https://github.com/Dirbaio/futures-intrusive", branch="master"}
14 19
15[profile.dev] 20[profile.dev]
16codegen-units = 1 21codegen-units = 1
diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs
index 55869c6e5..ddb4fd367 100644
--- a/embassy-nrf/src/rtc.rs
+++ b/embassy-nrf/src/rtc.rs
@@ -1,8 +1,6 @@
1use core::cell::Cell; 1use core::cell::Cell;
2use core::ops::Deref; 2use core::ops::Deref;
3use core::sync::atomic::{AtomicU32, Ordering}; 3use core::sync::atomic::{AtomicU32, Ordering};
4use defmt::trace;
5use embassy::clock::Monotonic;
6 4
7use crate::interrupt; 5use crate::interrupt;
8use crate::interrupt::Mutex; 6use crate::interrupt::Mutex;
@@ -86,22 +84,25 @@ impl<T: Instance> RTC<T> {
86 interrupt::enable(T::INTERRUPT); 84 interrupt::enable(T::INTERRUPT);
87 } 85 }
88 86
87 pub fn now(&self) -> u64 {
88 let counter = self.rtc.counter.read().bits();
89 let period = self.period.load(Ordering::Relaxed);
90 calc_now(period, counter)
91 }
92
89 fn on_interrupt(&self) { 93 fn on_interrupt(&self) {
90 if self.rtc.events_ovrflw.read().bits() == 1 { 94 if self.rtc.events_ovrflw.read().bits() == 1 {
91 self.rtc.events_ovrflw.write(|w| w); 95 self.rtc.events_ovrflw.write(|w| w);
92 trace!("rtc overflow");
93 self.next_period(); 96 self.next_period();
94 } 97 }
95 98
96 if self.rtc.events_compare[0].read().bits() == 1 { 99 if self.rtc.events_compare[0].read().bits() == 1 {
97 self.rtc.events_compare[0].write(|w| w); 100 self.rtc.events_compare[0].write(|w| w);
98 trace!("rtc compare0");
99 self.next_period(); 101 self.next_period();
100 } 102 }
101 103
102 if self.rtc.events_compare[1].read().bits() == 1 { 104 if self.rtc.events_compare[1].read().bits() == 1 {
103 self.rtc.events_compare[1].write(|w| w); 105 self.rtc.events_compare[1].write(|w| w);
104 trace!("rtc compare1");
105 self.trigger_alarm(); 106 self.trigger_alarm();
106 } 107 }
107 } 108 }
@@ -162,26 +163,28 @@ impl<T: Instance> RTC<T> {
162 } 163 }
163 }) 164 })
164 } 165 }
165}
166 166
167impl<T: Instance> Monotonic for RTC<T> { 167 pub fn alarm0(&'static self) -> Alarm<T> {
168 fn now(&self) -> u64 { 168 Alarm { rtc: self }
169 let counter = self.rtc.counter.read().bits();
170 let period = self.period.load(Ordering::Relaxed);
171 calc_now(period, counter)
172 } 169 }
170}
171
172pub struct Alarm<T: Instance> {
173 rtc: &'static RTC<T>,
174}
173 175
174 fn set_alarm(&self, timestamp: u64, callback: fn()) { 176impl<T: Instance> embassy::time::Alarm for Alarm<T> {
175 self.do_set_alarm(timestamp, Some(callback)); 177 fn set(&self, timestamp: u64, callback: fn()) {
178 self.rtc.do_set_alarm(timestamp, Some(callback));
176 } 179 }
177 180
178 fn clear_alarm(&self) { 181 fn clear(&self) {
179 self.do_set_alarm(u64::MAX, None); 182 self.rtc.do_set_alarm(u64::MAX, None);
180 } 183 }
181} 184}
182 185
183/// Implemented by all RTC instances. 186/// Implemented by all RTC instances.
184pub trait Instance: Deref<Target = rtc0::RegisterBlock> + Sized { 187pub trait Instance: Deref<Target = rtc0::RegisterBlock> + Sized + 'static {
185 /// The interrupt associated with this RTC instance. 188 /// The interrupt associated with this RTC instance.
186 const INTERRUPT: Interrupt; 189 const INTERRUPT: Interrupt;
187 190
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml
index 5826e8ba6..60428f10d 100644
--- a/embassy/Cargo.toml
+++ b/embassy/Cargo.toml
@@ -13,3 +13,4 @@ cortex-m = "0.6.3"
13futures = { version = "0.3.5", default-features = false, features = [ "async-await" ] } 13futures = { version = "0.3.5", default-features = false, features = [ "async-await" ] }
14pin-project = { version = "0.4.23", default-features = false } 14pin-project = { version = "0.4.23", default-features = false }
15futures-intrusive = { version = "0.3.1", default-features = false } 15futures-intrusive = { version = "0.3.1", default-features = false }
16static-executor = { version = "0.1.0", features=["defmt"]}
diff --git a/embassy/src/clock.rs b/embassy/src/clock.rs
deleted file mode 100644
index ca5f26a05..000000000
--- a/embassy/src/clock.rs
+++ /dev/null
@@ -1,21 +0,0 @@
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.
4pub 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/executor.rs b/embassy/src/executor.rs
new file mode 100644
index 000000000..c5d024f7b
--- /dev/null
+++ b/embassy/src/executor.rs
@@ -0,0 +1,72 @@
1use core::marker::PhantomData;
2use static_executor as se;
3
4use crate::time;
5use crate::time::Alarm;
6
7pub use se::{task, SpawnError, SpawnToken};
8
9pub trait Model {
10 fn signal();
11}
12
13pub struct WfeModel;
14
15impl Model for WfeModel {
16 fn signal() {
17 cortex_m::asm::sev()
18 }
19}
20
21pub struct Executor<M, A: Alarm> {
22 inner: se::Executor,
23 alarm: A,
24 timer: time::TimerService,
25 _phantom: PhantomData<M>,
26}
27
28impl<M: Model, A: Alarm> Executor<M, A> {
29 pub fn new(alarm: A) -> Self {
30 Self {
31 inner: se::Executor::new(M::signal),
32 alarm,
33 timer: time::TimerService::new(time::IntrusiveClock),
34 _phantom: PhantomData,
35 }
36 }
37
38 /// Spawn a future on this executor.
39 ///
40 /// safety: can only be called from the executor thread
41 pub unsafe fn spawn(&'static self, token: SpawnToken) -> Result<(), SpawnError> {
42 self.inner.spawn(token)
43 }
44
45 /// Runs the executor until the queue is empty.
46 ///
47 /// safety: can only be called from the executor thread
48 pub unsafe fn run_once(&'static self) {
49 time::with_timer_service(&self.timer, || {
50 self.timer.check_expirations();
51 self.inner.run();
52
53 match self.timer.next_expiration() {
54 // If this is in the past, set_alarm will immediately trigger the alarm,
55 // which will make the wfe immediately return so we do another loop iteration.
56 Some(at) => self.alarm.set(at, M::signal),
57 None => self.alarm.clear(),
58 }
59 })
60 }
61}
62
63impl<A: Alarm> Executor<WfeModel, A> {
64 /// Runs the executor forever
65 /// safety: can only be called from the executor thread
66 pub unsafe fn run(&'static self) -> ! {
67 loop {
68 self.run_once();
69 cortex_m::asm::wfe()
70 }
71 }
72}
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index 89eef3f4c..92ad77424 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -3,7 +3,8 @@
3#![feature(generic_associated_types)] 3#![feature(generic_associated_types)]
4#![feature(const_fn)] 4#![feature(const_fn)]
5 5
6pub mod clock; 6pub mod executor;
7pub mod flash; 7pub mod flash;
8pub mod io; 8pub mod io;
9pub mod time;
9pub mod util; 10pub mod util;
diff --git a/embassy/src/time.rs b/embassy/src/time.rs
new file mode 100644
index 000000000..30fd1b680
--- /dev/null
+++ b/embassy/src/time.rs
@@ -0,0 +1,287 @@
1use core::cell::Cell;
2use core::convert::TryInto;
3use core::future::Future;
4use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
5use core::pin::Pin;
6use core::ptr;
7use core::sync::atomic::{AtomicPtr, Ordering};
8use core::task::{Context, Poll};
9
10use fi::LocalTimer;
11use futures_intrusive::timer as fi;
12
13static mut CLOCK: fn() -> u64 = clock_not_set;
14
15fn clock_not_set() -> u64 {
16 panic!("No clock set. You must call embassy::time::set_clock() before trying to use the clock")
17}
18
19pub unsafe fn set_clock(clock: fn() -> u64) {
20 CLOCK = clock;
21}
22
23fn now() -> u64 {
24 unsafe { CLOCK() }
25}
26
27#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
28pub struct Instant {
29 ticks: u64,
30}
31
32impl Instant {
33 pub fn now() -> Instant {
34 Instant { ticks: now() }
35 }
36
37 pub fn into_ticks(&self) -> u64 {
38 self.ticks
39 }
40
41 pub fn duration_since(&self, earlier: Instant) -> Duration {
42 Duration {
43 ticks: (self.ticks - earlier.ticks).try_into().unwrap(),
44 }
45 }
46
47 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
48 if self.ticks < earlier.ticks {
49 None
50 } else {
51 Some(Duration {
52 ticks: (self.ticks - earlier.ticks).try_into().unwrap(),
53 })
54 }
55 }
56
57 pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
58 Duration {
59 ticks: if self.ticks < earlier.ticks {
60 0
61 } else {
62 (self.ticks - earlier.ticks).try_into().unwrap()
63 },
64 }
65 }
66
67 pub fn elapsed(&self) -> Duration {
68 Instant::now() - *self
69 }
70
71 pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
72 self.ticks
73 .checked_add(duration.ticks.into())
74 .map(|ticks| Instant { ticks })
75 }
76 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
77 self.ticks
78 .checked_sub(duration.ticks.into())
79 .map(|ticks| Instant { ticks })
80 }
81}
82
83impl Add<Duration> for Instant {
84 type Output = Instant;
85
86 fn add(self, other: Duration) -> Instant {
87 self.checked_add(other)
88 .expect("overflow when adding duration to instant")
89 }
90}
91
92impl AddAssign<Duration> for Instant {
93 fn add_assign(&mut self, other: Duration) {
94 *self = *self + other;
95 }
96}
97
98impl Sub<Duration> for Instant {
99 type Output = Instant;
100
101 fn sub(self, other: Duration) -> Instant {
102 self.checked_sub(other)
103 .expect("overflow when subtracting duration from instant")
104 }
105}
106
107impl SubAssign<Duration> for Instant {
108 fn sub_assign(&mut self, other: Duration) {
109 *self = *self - other;
110 }
111}
112
113impl Sub<Instant> for Instant {
114 type Output = Duration;
115
116 fn sub(self, other: Instant) -> Duration {
117 self.duration_since(other)
118 }
119}
120
121#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
122pub struct Duration {
123 ticks: u32,
124}
125
126impl Duration {
127 pub const fn from_ticks(ticks: u32) -> Duration {
128 Duration { ticks }
129 }
130
131 pub fn checked_add(self, rhs: Duration) -> Option<Duration> {
132 self.ticks
133 .checked_add(rhs.ticks)
134 .map(|ticks| Duration { ticks })
135 }
136
137 pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
138 self.ticks
139 .checked_sub(rhs.ticks)
140 .map(|ticks| Duration { ticks })
141 }
142
143 pub fn checked_mul(self, rhs: u32) -> Option<Duration> {
144 self.ticks.checked_mul(rhs).map(|ticks| Duration { ticks })
145 }
146
147 pub fn checked_div(self, rhs: u32) -> Option<Duration> {
148 self.ticks.checked_div(rhs).map(|ticks| Duration { ticks })
149 }
150}
151
152impl Add for Duration {
153 type Output = Duration;
154
155 fn add(self, rhs: Duration) -> Duration {
156 self.checked_add(rhs)
157 .expect("overflow when adding durations")
158 }
159}
160
161impl AddAssign for Duration {
162 fn add_assign(&mut self, rhs: Duration) {
163 *self = *self + rhs;
164 }
165}
166
167impl Sub for Duration {
168 type Output = Duration;
169
170 fn sub(self, rhs: Duration) -> Duration {
171 self.checked_sub(rhs)
172 .expect("overflow when subtracting durations")
173 }
174}
175
176impl SubAssign for Duration {
177 fn sub_assign(&mut self, rhs: Duration) {
178 *self = *self - rhs;
179 }
180}
181
182impl Mul<u32> for Duration {
183 type Output = Duration;
184
185 fn mul(self, rhs: u32) -> Duration {
186 self.checked_mul(rhs)
187 .expect("overflow when multiplying duration by scalar")
188 }
189}
190
191impl Mul<Duration> for u32 {
192 type Output = Duration;
193
194 fn mul(self, rhs: Duration) -> Duration {
195 rhs * self
196 }
197}
198
199impl MulAssign<u32> for Duration {
200 fn mul_assign(&mut self, rhs: u32) {
201 *self = *self * rhs;
202 }
203}
204
205impl Div<u32> for Duration {
206 type Output = Duration;
207
208 fn div(self, rhs: u32) -> Duration {
209 self.checked_div(rhs)
210 .expect("divide by zero error when dividing duration by scalar")
211 }
212}
213
214impl DivAssign<u32> for Duration {
215 fn div_assign(&mut self, rhs: u32) {
216 *self = *self / rhs;
217 }
218}
219
220pub(crate) struct IntrusiveClock;
221
222impl fi::Clock for IntrusiveClock {
223 fn now(&self) -> u64 {
224 now()
225 }
226}
227
228pub(crate) type TimerService = fi::LocalTimerService<IntrusiveClock>;
229
230static CURRENT_TIMER_SERVICE: AtomicPtr<TimerService> = AtomicPtr::new(ptr::null_mut());
231
232pub(crate) fn with_timer_service<R>(svc: &'static TimerService, f: impl FnOnce() -> R) -> R {
233 let svc = svc as *const _ as *mut _;
234 let prev_svc = CURRENT_TIMER_SERVICE.swap(svc, Ordering::Relaxed);
235 let r = f();
236 let svc2 = CURRENT_TIMER_SERVICE.swap(prev_svc, Ordering::Relaxed);
237 assert_eq!(svc, svc2);
238 r
239}
240
241fn current_timer_service() -> &'static TimerService {
242 unsafe {
243 CURRENT_TIMER_SERVICE
244 .load(Ordering::Relaxed)
245 .as_ref()
246 .unwrap()
247 }
248}
249
250pub struct Timer {
251 inner: fi::LocalTimerFuture<'static>,
252}
253
254impl Timer {
255 pub fn at(when: Instant) -> Self {
256 let svc: &TimerService = current_timer_service();
257 Self {
258 inner: svc.deadline(when.into_ticks()),
259 }
260 }
261
262 pub fn after(dur: Duration) -> Self {
263 Self::at(Instant::now() + dur)
264 }
265}
266
267impl Future for Timer {
268 type Output = ();
269 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
270 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }.poll(cx)
271 }
272}
273
274/// Trait to register a callback at a given timestamp.
275pub trait Alarm {
276 /// Sets an alarm at the given timestamp. When the clock reaches that
277 /// timestamp, the provided callback funcion will be called.
278 ///
279 /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp.
280 ///
281 /// Only one alarm can be active at a time. This overwrites any previously-set alarm if any.
282 fn set(&self, timestamp: u64, callback: fn());
283
284 /// Clears the previously-set alarm.
285 /// If no alarm was set, this is a noop.
286 fn clear(&self);
287}
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index 4e81d1daa..7b49ffb1f 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -27,5 +27,4 @@ nrf52840-hal = { version = "0.11.0" }
27embassy = { version = "0.1.0", path = "../embassy" } 27embassy = { version = "0.1.0", path = "../embassy" }
28embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt-trace", "52840"] } 28embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt-trace", "52840"] }
29static-executor = { version = "0.1.0", features=["defmt"]} 29static-executor = { version = "0.1.0", features=["defmt"]}
30futures = { version = "0.3.5", default-features = false } 30futures = { version = "0.3.5", default-features = false } \ No newline at end of file
31futures-intrusive = { version = "0.3.1", default-features = false } \ No newline at end of file
diff --git a/examples/src/bin/rtc_async.rs b/examples/src/bin/rtc_async.rs
index 977621d4c..3bffabf0f 100644
--- a/examples/src/bin/rtc_async.rs
+++ b/examples/src/bin/rtc_async.rs
@@ -8,39 +8,30 @@ use example_common::*;
8 8
9use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
10use cortex_m_rt::entry; 10use cortex_m_rt::entry;
11use embassy::clock::Monotonic; 11use embassy::executor::{task, Executor, WfeModel};
12use embassy::time::{Duration, Instant, Timer};
13use embassy_nrf::pac;
12use embassy_nrf::rtc; 14use embassy_nrf::rtc;
13use futures_intrusive::timer::{Clock, LocalTimer, LocalTimerService};
14use nrf52840_hal::clocks; 15use nrf52840_hal::clocks;
15use static_executor::{task, Executor};
16
17struct RtcClock<T>(rtc::RTC<T>);
18
19impl<T: rtc::Instance> Clock for RtcClock<T> {
20 fn now(&self) -> u64 {
21 self.0.now()
22 }
23}
24 16
25#[task] 17#[task]
26async fn run1(rtc: &'static rtc::RTC<embassy_nrf::pac::RTC1>, timer: &'static LocalTimerService) { 18async fn run1() {
27 loop { 19 loop {
28 info!("tick 1"); 20 info!("BIG INFREQUENT TICK");
29 timer.deadline(rtc.now() + 64000).await; 21 Timer::after(Duration::from_ticks(64000)).await;
30 } 22 }
31} 23}
32 24
33#[task] 25#[task]
34async fn run2(rtc: &'static rtc::RTC<embassy_nrf::pac::RTC1>, timer: &'static LocalTimerService) { 26async fn run2() {
35 loop { 27 loop {
36 info!("tick 2"); 28 info!("tick");
37 timer.deadline(rtc.now() + 23000).await; 29 Timer::after(Duration::from_ticks(13000)).await;
38 } 30 }
39} 31}
40 32
41static EXECUTOR: Executor = Executor::new(cortex_m::asm::sev); 33static mut RTC: MaybeUninit<rtc::RTC<pac::RTC1>> = MaybeUninit::uninit();
42static mut RTC: MaybeUninit<RtcClock<embassy_nrf::pac::RTC1>> = MaybeUninit::uninit(); 34static mut EXECUTOR: MaybeUninit<Executor<WfeModel, rtc::Alarm<pac::RTC1>>> = MaybeUninit::uninit();
43static mut TIMER: MaybeUninit<LocalTimerService> = MaybeUninit::uninit();
44 35
45#[entry] 36#[entry]
46fn main() -> ! { 37fn main() -> ! {
@@ -55,35 +46,23 @@ fn main() -> ! {
55 46
56 let rtc: &'static _ = unsafe { 47 let rtc: &'static _ = unsafe {
57 let ptr = RTC.as_mut_ptr(); 48 let ptr = RTC.as_mut_ptr();
58 ptr.write(RtcClock(rtc::RTC::new(p.RTC1))); 49 ptr.write(rtc::RTC::new(p.RTC1));
59 &*ptr 50 &*ptr
60 }; 51 };
61 52
62 rtc.0.start(); 53 rtc.start();
54 unsafe { embassy::time::set_clock(|| RTC.as_ptr().as_ref().unwrap().now()) };
63 55
64 let timer: &'static _ = unsafe { 56 let executor: &'static _ = unsafe {
65 let ptr = TIMER.as_mut_ptr(); 57 let ptr = EXECUTOR.as_mut_ptr();
66 ptr.write(LocalTimerService::new(rtc)); 58 ptr.write(Executor::new(rtc.alarm0()));
67 &*ptr 59 &*ptr
68 }; 60 };
69 61
70 unsafe { 62 unsafe {
71 EXECUTOR.spawn(run1(&rtc.0, timer)).dewrap(); 63 executor.spawn(run1()).dewrap();
72 EXECUTOR.spawn(run2(&rtc.0, timer)).dewrap(); 64 executor.spawn(run2()).dewrap();
73
74 loop {
75 timer.check_expirations();
76
77 EXECUTOR.run();
78
79 match timer.next_expiration() {
80 // If this is in the past, set_alarm will immediately trigger the alarm,
81 // which will make the wfe immediately return so we do another loop iteration.
82 Some(at) => rtc.0.set_alarm(at, cortex_m::asm::sev),
83 None => rtc.0.clear_alarm(),
84 }
85 65
86 cortex_m::asm::wfe(); 66 executor.run()
87 }
88 } 67 }
89} 68}
diff --git a/examples/src/bin/rtc_raw.rs b/examples/src/bin/rtc_raw.rs
index aa98409c4..2e4b28653 100644
--- a/examples/src/bin/rtc_raw.rs
+++ b/examples/src/bin/rtc_raw.rs
@@ -8,7 +8,7 @@ use example_common::*;
8 8
9use core::mem::MaybeUninit; 9use core::mem::MaybeUninit;
10use cortex_m_rt::entry; 10use cortex_m_rt::entry;
11use embassy::clock::Monotonic; 11use embassy::time::Alarm;
12use embassy_nrf::rtc; 12use embassy_nrf::rtc;
13use nrf52840_hal::clocks; 13use nrf52840_hal::clocks;
14 14
@@ -31,8 +31,11 @@ fn main() -> ! {
31 &*ptr 31 &*ptr
32 }; 32 };
33 33
34 let alarm = rtc.alarm0();
35
34 rtc.start(); 36 rtc.start();
35 rtc.set_alarm(53719, || info!("ALARM TRIGGERED")); 37
38 alarm.set(53719, || info!("ALARM TRIGGERED"));
36 39
37 info!("initialized!"); 40 info!("initialized!");
38 41