aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiam Murphy <[email protected]>2021-06-26 17:58:36 +1000
committerLiam Murphy <[email protected]>2021-06-26 17:58:36 +1000
commit02781ed744b6e76d3790844f898235088b0fd8aa (patch)
tree4f5cd29aebc7b54beee6f7e3541fcc583ed9d755
parente6d6e82e54bca88ab1144802d2b716b867934225 (diff)
Add an nRF Timer driver
Resolves #189
-rw-r--r--embassy-nrf/src/buffered_uarte.rs40
-rw-r--r--embassy-nrf/src/timer.rs377
-rw-r--r--embassy-nrf/src/uarte.rs36
3 files changed, 405 insertions, 48 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 517afa38c..39a8cd887 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -15,7 +15,9 @@ use crate::gpio::sealed::Pin as _;
15use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; 15use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
16use crate::pac; 16use crate::pac;
17use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 17use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
18use crate::timer::Frequency;
18use crate::timer::Instance as TimerInstance; 19use crate::timer::Instance as TimerInstance;
20use crate::timer::Timer;
19use crate::uarte::{Config, Instance as UarteInstance}; 21use crate::uarte::{Config, Instance as UarteInstance};
20 22
21// Re-export SVD variants to allow user to directly set values 23// Re-export SVD variants to allow user to directly set values
@@ -35,7 +37,7 @@ enum TxState {
35 37
36struct State<'d, U: UarteInstance, T: TimerInstance> { 38struct State<'d, U: UarteInstance, T: TimerInstance> {
37 phantom: PhantomData<&'d mut U>, 39 phantom: PhantomData<&'d mut U>,
38 timer: T, 40 timer: Timer<'d, T>,
39 _ppi_ch1: Ppi<'d, AnyConfigurableChannel>, 41 _ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
40 _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, 42 _ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
41 43
@@ -76,10 +78,11 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
76 rx_buffer: &'d mut [u8], 78 rx_buffer: &'d mut [u8],
77 tx_buffer: &'d mut [u8], 79 tx_buffer: &'d mut [u8],
78 ) -> Self { 80 ) -> Self {
79 unborrow!(timer, ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); 81 unborrow!(ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts);
80 82
81 let r = U::regs(); 83 let r = U::regs();
82 let rt = timer.regs(); 84
85 let timer = Timer::new_irqless(timer);
83 86
84 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 87 rxd.conf().write(|w| w.input().connect().drive().h0h1());
85 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 88 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@@ -133,25 +136,19 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
133 // This gives us the amount of 16M ticks for 20 bits. 136 // This gives us the amount of 16M ticks for 20 bits.
134 let timeout = 0x8000_0000 / (config.baudrate as u32 / 40); 137 let timeout = 0x8000_0000 / (config.baudrate as u32 / 40);
135 138
136 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 139 timer.set_frequency(Frequency::F16MHz);
137 rt.bitmode.write(|w| w.bitmode()._32bit()); 140 timer.cc0().set(timeout);
138 rt.prescaler.write(|w| unsafe { w.prescaler().bits(0) }); 141 timer.cc0().short_compare_clear();
139 rt.cc[0].write(|w| unsafe { w.bits(timeout) }); 142 timer.cc0().short_compare_stop();
140 rt.mode.write(|w| w.mode().timer());
141 rt.shorts.write(|w| {
142 w.compare0_clear().set_bit();
143 w.compare0_stop().set_bit();
144 w
145 });
146 143
147 let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); 144 let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
148 ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); 145 ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
149 ppi_ch1.set_task(Task::from_reg(&rt.tasks_clear)); 146 ppi_ch1.set_task(timer.task_clear());
150 ppi_ch1.set_fork_task(Task::from_reg(&rt.tasks_start)); 147 ppi_ch1.set_fork_task(timer.task_start());
151 ppi_ch1.enable(); 148 ppi_ch1.enable();
152 149
153 let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); 150 let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
154 ppi_ch2.set_event(Event::from_reg(&rt.events_compare[0])); 151 ppi_ch2.set_event(timer.cc0().event_compare());
155 ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); 152 ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
156 ppi_ch2.enable(); 153 ppi_ch2.enable();
157 154
@@ -181,11 +178,10 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
181 inner.as_mut().register_interrupt(); 178 inner.as_mut().register_interrupt();
182 inner.with(|state, _irq| { 179 inner.with(|state, _irq| {
183 let r = U::regs(); 180 let r = U::regs();
184 let rt = state.timer.regs();
185 181
186 let timeout = 0x8000_0000 / (baudrate as u32 / 40); 182 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
187 rt.cc[0].write(|w| unsafe { w.bits(timeout) }); 183 state.timer.cc0().set(timeout);
188 rt.tasks_clear.write(|w| unsafe { w.bits(1) }); 184 state.timer.clear();
189 185
190 r.baudrate.write(|w| w.baudrate().variant(baudrate)); 186 r.baudrate.write(|w| w.baudrate().variant(baudrate));
191 }); 187 });
@@ -268,11 +264,10 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U,
268impl<'a, U: UarteInstance, T: TimerInstance> Drop for State<'a, U, T> { 264impl<'a, U: UarteInstance, T: TimerInstance> Drop for State<'a, U, T> {
269 fn drop(&mut self) { 265 fn drop(&mut self) {
270 let r = U::regs(); 266 let r = U::regs();
271 let rt = self.timer.regs();
272 267
273 // TODO this probably deadlocks. do like Uarte instead. 268 // TODO this probably deadlocks. do like Uarte instead.
274 269
275 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 270 self.timer.stop();
276 if let RxState::Receiving = self.rx_state { 271 if let RxState::Receiving = self.rx_state {
277 r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 272 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
278 } 273 }
@@ -293,7 +288,6 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for State<'a, U, T>
293 fn on_interrupt(&mut self) { 288 fn on_interrupt(&mut self) {
294 trace!("irq: start"); 289 trace!("irq: start");
295 let r = U::regs(); 290 let r = U::regs();
296 let rt = self.timer.regs();
297 291
298 loop { 292 loop {
299 match self.rx_state { 293 match self.rx_state {
@@ -330,7 +324,7 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for State<'a, U, T>
330 RxState::Receiving => { 324 RxState::Receiving => {
331 trace!(" irq_rx: in state receiving"); 325 trace!(" irq_rx: in state receiving");
332 if r.events_endrx.read().bits() != 0 { 326 if r.events_endrx.read().bits() != 0 {
333 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 327 self.timer.stop();
334 328
335 let n: usize = r.rxd.amount.read().amount().bits() as usize; 329 let n: usize = r.rxd.amount.read().amount().bits() as usize;
336 trace!(" irq_rx: endrx {:?}", n); 330 trace!(" irq_rx: endrx {:?}", n);
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index 2490bfd93..3b2678a0b 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -1,15 +1,30 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::marker::PhantomData;
4use core::task::Poll;
5
3use embassy::interrupt::Interrupt; 6use embassy::interrupt::Interrupt;
7use embassy::interrupt::InterruptExt;
8use embassy::util::OnDrop;
4use embassy::util::Unborrow; 9use embassy::util::Unborrow;
10use embassy_extras::unborrow;
11use futures::future::poll_fn;
5 12
6use crate::pac; 13use crate::pac;
14use crate::ppi::Event;
15use crate::ppi::Task;
7 16
8pub(crate) mod sealed { 17pub(crate) mod sealed {
18 use embassy::util::AtomicWaker;
19
9 use super::*; 20 use super::*;
10 21
11 pub trait Instance { 22 pub trait Instance {
12 fn regs(&self) -> &pac::timer0::RegisterBlock; 23 /// The number of CC registers this instance has.
24 const CCS: usize;
25 fn regs() -> &'static pac::timer0::RegisterBlock;
26 /// Storage for the waker for CC register `n`.
27 fn waker(n: usize) -> &'static AtomicWaker;
13 } 28 }
14 pub trait ExtendedInstance {} 29 pub trait ExtendedInstance {}
15} 30}
@@ -20,19 +35,373 @@ pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
20pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {} 35pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {}
21 36
22macro_rules! impl_timer { 37macro_rules! impl_timer {
23 ($type:ident, $pac_type:ident, $irq:ident) => { 38 ($type:ident, $pac_type:ident, $irq:ident, $ccs:literal) => {
24 impl crate::timer::sealed::Instance for peripherals::$type { 39 impl crate::timer::sealed::Instance for peripherals::$type {
25 fn regs(&self) -> &pac::timer0::RegisterBlock { 40 const CCS: usize = $ccs;
41 fn regs() -> &'static pac::timer0::RegisterBlock {
26 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } 42 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
27 } 43 }
44 fn waker(n: usize) -> &'static ::embassy::util::AtomicWaker {
45 use ::embassy::util::AtomicWaker;
46 const NEW_AW: AtomicWaker = AtomicWaker::new();
47 static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
48 &WAKERS[n]
49 }
28 } 50 }
29 impl crate::timer::Instance for peripherals::$type { 51 impl crate::timer::Instance for peripherals::$type {
30 type Interrupt = crate::interrupt::$irq; 52 type Interrupt = crate::interrupt::$irq;
31 } 53 }
32 }; 54 };
55 ($type:ident, $pac_type:ident, $irq:ident) => {
56 impl_timer!($type, $pac_type, $irq, 4);
57 };
33 ($type:ident, $pac_type:ident, $irq:ident, extended) => { 58 ($type:ident, $pac_type:ident, $irq:ident, extended) => {
34 impl_timer!($type, $pac_type, $irq); 59 impl_timer!($type, $pac_type, $irq, 6);
35 impl crate::timer::sealed::ExtendedInstance for peripherals::$type {} 60 impl crate::timer::sealed::ExtendedInstance for peripherals::$type {}
36 impl crate::timer::ExtendedInstance for peripherals::$type {} 61 impl crate::timer::ExtendedInstance for peripherals::$type {}
37 }; 62 };
38} 63}
64
65#[repr(u8)]
66pub enum Frequency {
67 // TODO: These variant names are terrible, what should they be?
68 F16MHz = 0,
69 F8MHz = 1,
70 F4MHz = 2,
71 F2MHz = 3,
72 F1MHz = 4,
73 F500kHz = 5,
74 F250kHz = 6,
75 F125kHz = 7,
76 F62500Hz = 8,
77 F31250Hz = 9,
78}
79
80/// nRF Timer driver.
81///
82/// The timer has an internal counter, which is incremented for every tick of the timer.
83/// The counter is 32-bit, so it wraps back to 0 at 4294967296.
84///
85/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter
86/// or trigger an event when the counter reaches a certain value.
87pub struct Timer<'d, T: Instance> {
88 phantom: PhantomData<&'d mut T>,
89}
90
91impl<'d, T: Instance> Timer<'d, T> {
92 pub fn new(
93 timer: impl Unborrow<Target = T> + 'd,
94 irq: impl Unborrow<Target = T::Interrupt> + 'd,
95 ) -> Self {
96 unborrow!(irq);
97
98 irq.set_handler(Self::on_interrupt);
99 irq.unpend();
100 irq.enable();
101
102 Self::new_irqless(timer)
103 }
104
105 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
106 ///
107 /// This is used by `Uarte` internally.
108 pub(crate) fn new_irqless(_timer: impl Unborrow<Target = T> + 'd) -> Self {
109 let regs = T::regs();
110
111 // Set the instance to timer mode.
112 regs.mode.write(|w| w.mode().timer());
113
114 // Make the counter's max value as high as possible.
115 // TODO: is there a reason someone would want to set this lower?
116 regs.bitmode.write(|w| w.bitmode()._32bit());
117
118 let this = Self {
119 phantom: PhantomData,
120 };
121
122 // Initialize the timer as stopped.
123 this.stop();
124
125 // Initialize the counter at 0.
126 this.clear();
127
128 // Initialize all the shorts as disabled.
129 for n in 0..T::CCS {
130 let cc = Cc::<T> {
131 n,
132 phantom: PhantomData,
133 };
134 cc.unshort_compare_clear();
135 cc.unshort_compare_stop();
136 }
137
138 this
139 }
140
141 /// Starts the timer.
142 pub fn start(&self) {
143 T::regs().tasks_start.write(|w| w.tasks_start().trigger())
144 }
145
146 /// Stops the timer.
147 pub fn stop(&self) {
148 T::regs().tasks_stop.write(|w| w.tasks_stop().trigger())
149 }
150
151 /// Reset the timer's counter to 0.
152 pub fn clear(&self) {
153 T::regs().tasks_clear.write(|w| w.tasks_clear().trigger())
154 }
155
156 /// Returns the START task, for use with PPI.
157 ///
158 /// When triggered, this task starts the timer.
159 pub fn task_start(&self) -> Task {
160 Task::from_reg(&T::regs().tasks_start)
161 }
162
163 /// Returns the STOP task, for use with PPI.
164 ///
165 /// When triggered, this task stops the timer.
166 pub fn task_stop(&self) -> Task {
167 Task::from_reg(&T::regs().tasks_stop)
168 }
169
170 /// Returns the CLEAR task, for use with PPI.
171 ///
172 /// When triggered, this task resets the timer's counter to 0.
173 pub fn task_clear(&self) -> Task {
174 Task::from_reg(&T::regs().tasks_clear)
175 }
176
177 /// Change the timer's frequency.
178 ///
179 /// This will stop the timer if it isn't already stopped,
180 /// because the timer may exhibit 'unpredictable behaviour' if it's frequency is changed while it's running.
181 pub fn set_frequency(&self, frequency: Frequency) {
182 self.stop();
183
184 T::regs()
185 .prescaler
186 // SAFETY: `frequency` is a variant of `Frequency`,
187 // whose values are all in the range of 0-9 (the valid range of `prescaler`).
188 .write(|w| unsafe { w.prescaler().bits(frequency as u8) })
189 }
190
191 fn on_interrupt(_: *mut ()) {
192 let regs = T::regs();
193 for n in 0..T::CCS {
194 if regs.events_compare[n]
195 .read()
196 .events_compare()
197 .is_generated()
198 {
199 T::waker(n).wake();
200 }
201 }
202 }
203
204 /// Returns the 0th CC register.
205 pub fn cc0<'a>(&'a self) -> Cc<'a, T> {
206 Cc {
207 n: 0,
208 phantom: PhantomData,
209 }
210 }
211
212 /// Returns the 1st CC register.
213 pub fn cc1<'a>(&'a self) -> Cc<'a, T> {
214 Cc {
215 n: 1,
216 phantom: PhantomData,
217 }
218 }
219
220 /// Returns the 2nd CC register.
221 pub fn cc2<'a>(&'a self) -> Cc<'a, T> {
222 Cc {
223 n: 2,
224 phantom: PhantomData,
225 }
226 }
227
228 /// Returns the 3rd CC register.
229 pub fn cc3<'a>(&'a self) -> Cc<'a, T> {
230 Cc {
231 n: 3,
232 phantom: PhantomData,
233 }
234 }
235}
236
237impl<'d, T: ExtendedInstance> Timer<'d, T> {
238 /// Returns the 4th CC register.
239 pub fn cc4<'a>(&'a self) -> Cc<'a, T> {
240 Cc {
241 n: 4,
242 phantom: PhantomData,
243 }
244 }
245
246 /// Returns the 5th CC register.
247 pub fn cc5<'a>(&'a self) -> Cc<'a, T> {
248 Cc {
249 n: 5,
250 phantom: PhantomData,
251 }
252 }
253}
254
255/// A representation of a timer's Capture/Compare (CC) register.
256///
257/// A CC register holds a 32-bit value.
258/// This is used either to store a capture of the timer's current count, or to specify the value for the timer to compare against.
259///
260/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register.
261/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
262pub struct Cc<'a, T: Instance> {
263 n: usize,
264 phantom: PhantomData<&'a mut T>,
265}
266
267impl<'a, T: Instance> Cc<'a, T> {
268 /// Get the current value stored in the register.
269 pub fn value(&self) -> u32 {
270 T::regs().cc[self.n].read().cc().bits()
271 }
272
273 /// Set the value stored in the register.
274 ///
275 /// `event_compare` will fire when the timer's counter reaches this value.
276 pub fn set(&self, value: u32) {
277 // SAFETY: there are no invalid values for the CC register.
278 T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) })
279 }
280
281 /// Capture the current value of the timer's counter in this register, and return it.
282 pub fn capture(&self) -> u32 {
283 T::regs().tasks_capture[self.n].write(|w| w.tasks_capture().trigger());
284 self.value()
285 }
286
287 /// Returns this CC register's CAPTURE task, for use with PPI.
288 ///
289 /// When triggered, this task will capture the current value of the timer's counter in this register.
290 pub fn task_capture(&self) -> Task {
291 Task::from_reg(&T::regs().tasks_capture[self.n])
292 }
293
294 /// Returns this CC register's COMPARE event, for use with PPI.
295 ///
296 /// This event will fire when the timer's counter reaches the value in this CC register.
297 pub fn event_compare(&self) -> Event {
298 Event::from_reg(&T::regs().events_compare)
299 }
300
301 /// Enable the shortcut between this CC register's COMPARE event and the timer's CLEAR task.
302 ///
303 /// This means that when the COMPARE event is fired, the CLEAR task will be triggered.
304 ///
305 /// So, when the timer's counter reaches the value stored in this register, the timer's counter will be reset to 0.
306 pub fn short_compare_clear(&self) {
307 T::regs().shorts.write(|w| match self.n {
308 0 => w.compare0_clear().enabled(),
309 1 => w.compare1_clear().enabled(),
310 2 => w.compare2_clear().enabled(),
311 3 => w.compare3_clear().enabled(),
312 4 => w.compare4_clear().enabled(),
313 5 => w.compare5_clear().enabled(),
314 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
315 })
316 }
317
318 /// Disable the shortcut between this CC register's COMPARE event and the timer's CLEAR task.
319 pub fn unshort_compare_clear(&self) {
320 T::regs().shorts.write(|w| match self.n {
321 0 => w.compare0_clear().disabled(),
322 1 => w.compare1_clear().disabled(),
323 2 => w.compare2_clear().disabled(),
324 3 => w.compare3_clear().disabled(),
325 4 => w.compare4_clear().disabled(),
326 5 => w.compare5_clear().disabled(),
327 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
328 })
329 }
330
331 /// Enable the shortcut between this CC register's COMPARE event and the timer's STOP task.
332 ///
333 /// This means that when the COMPARE event is fired, the STOP task will be triggered.
334 ///
335 /// So, when the timer's counter reaches the value stored in this register, the timer will stop counting up.
336 pub fn short_compare_stop(&self) {
337 T::regs().shorts.write(|w| match self.n {
338 0 => w.compare0_stop().enabled(),
339 1 => w.compare1_stop().enabled(),
340 2 => w.compare2_stop().enabled(),
341 3 => w.compare3_stop().enabled(),
342 4 => w.compare4_stop().enabled(),
343 5 => w.compare5_stop().enabled(),
344 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
345 })
346 }
347
348 /// Disable the shortcut between this CC register's COMPARE event and the timer's STOP task.
349 pub fn unshort_compare_stop(&self) {
350 T::regs().shorts.write(|w| match self.n {
351 0 => w.compare0_stop().disabled(),
352 1 => w.compare1_stop().disabled(),
353 2 => w.compare2_stop().disabled(),
354 3 => w.compare3_stop().disabled(),
355 4 => w.compare4_stop().disabled(),
356 5 => w.compare5_stop().disabled(),
357 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
358 })
359 }
360
361 /// Wait until the timer's counter reaches the value stored in this register.
362 pub async fn wait(&self) {
363 let regs = T::regs();
364
365 // Enable the interrupt for this CC's COMPARE event.
366 regs.intenset.write(|w| match self.n {
367 0 => w.compare0().set(),
368 1 => w.compare1().set(),
369 2 => w.compare2().set(),
370 3 => w.compare3().set(),
371 4 => w.compare4().set(),
372 5 => w.compare5().set(),
373 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
374 });
375
376 // Disable the interrupt if the future is dropped.
377 let on_drop = OnDrop::new(|| {
378 regs.intenclr.write(|w| match self.n {
379 0 => w.compare0().clear(),
380 1 => w.compare1().clear(),
381 2 => w.compare2().clear(),
382 3 => w.compare3().clear(),
383 4 => w.compare4().clear(),
384 5 => w.compare5().clear(),
385 _ => unreachable!("a `Cc` cannot be created with `n > 5`"),
386 });
387 });
388
389 poll_fn(|cx| {
390 T::waker(self.n).register(cx.waker());
391
392 if regs.events_compare[self.n]
393 .read()
394 .events_compare()
395 .is_generated()
396 {
397 Poll::Ready(())
398 } else {
399 Poll::Pending
400 }
401 })
402 .await;
403
404 // Trigger the interrupt to be disabled.
405 drop(on_drop);
406 }
407}
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index de093c7f0..d138257c7 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -18,7 +18,9 @@ use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
18use crate::interrupt::Interrupt; 18use crate::interrupt::Interrupt;
19use crate::pac; 19use crate::pac;
20use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 20use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
21use crate::timer::Frequency;
21use crate::timer::Instance as TimerInstance; 22use crate::timer::Instance as TimerInstance;
23use crate::timer::Timer;
22 24
23// Re-export SVD variants to allow user to directly set values. 25// Re-export SVD variants to allow user to directly set values.
24pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 26pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@@ -287,7 +289,7 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
287/// allowing it to implement the ReadUntilIdle trait. 289/// allowing it to implement the ReadUntilIdle trait.
288pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { 290pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
289 uarte: Uarte<'d, U>, 291 uarte: Uarte<'d, U>,
290 timer: T, 292 timer: Timer<'d, T>,
291 ppi_ch1: Ppi<'d, AnyConfigurableChannel>, 293 ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
292 _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, 294 _ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
293} 295}
@@ -316,11 +318,11 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
316 ) -> Self { 318 ) -> Self {
317 let baudrate = config.baudrate; 319 let baudrate = config.baudrate;
318 let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); 320 let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config);
321 let timer = Timer::new_irqless(timer);
319 322
320 unborrow!(timer, ppi_ch1, ppi_ch2); 323 unborrow!(ppi_ch1, ppi_ch2);
321 324
322 let r = U::regs(); 325 let r = U::regs();
323 let rt = timer.regs();
324 326
325 // BAUDRATE register values are `baudrate * 2^32 / 16000000` 327 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
326 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values 328 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
@@ -330,25 +332,19 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
330 // This gives us the amount of 16M ticks for 20 bits. 332 // This gives us the amount of 16M ticks for 20 bits.
331 let timeout = 0x8000_0000 / (baudrate as u32 / 40); 333 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
332 334
333 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 335 timer.set_frequency(Frequency::F16MHz);
334 rt.bitmode.write(|w| w.bitmode()._32bit()); 336 timer.cc0().set(timeout);
335 rt.prescaler.write(|w| unsafe { w.prescaler().bits(0) }); 337 timer.cc0().short_compare_clear();
336 rt.cc[0].write(|w| unsafe { w.bits(timeout) }); 338 timer.cc0().short_compare_stop();
337 rt.mode.write(|w| w.mode().timer());
338 rt.shorts.write(|w| {
339 w.compare0_clear().set_bit();
340 w.compare0_stop().set_bit();
341 w
342 });
343 339
344 let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); 340 let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
345 ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); 341 ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
346 ppi_ch1.set_task(Task::from_reg(&rt.tasks_clear)); 342 ppi_ch1.set_task(timer.task_clear());
347 ppi_ch1.set_fork_task(Task::from_reg(&rt.tasks_start)); 343 ppi_ch1.set_fork_task(timer.task_start());
348 ppi_ch1.enable(); 344 ppi_ch1.enable();
349 345
350 let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); 346 let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
351 ppi_ch2.set_event(Event::from_reg(&rt.events_compare[0])); 347 ppi_ch2.set_event(timer.cc0().event_compare());
352 ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); 348 ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
353 ppi_ch2.enable(); 349 ppi_ch2.enable();
354 350
@@ -373,12 +369,10 @@ impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T
373 let r = U::regs(); 369 let r = U::regs();
374 let s = U::state(); 370 let s = U::state();
375 371
376 let rt = self.timer.regs(); 372 let drop = OnDrop::new(|| {
377
378 let drop = OnDrop::new(move || {
379 info!("read drop: stopping"); 373 info!("read drop: stopping");
380 374
381 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 375 self.timer.stop();
382 376
383 r.intenclr.write(|w| w.endrx().clear()); 377 r.intenclr.write(|w| w.endrx().clear());
384 r.events_rxto.reset(); 378 r.events_rxto.reset();
@@ -413,7 +407,7 @@ impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T
413 let n = r.rxd.amount.read().amount().bits() as usize; 407 let n = r.rxd.amount.read().amount().bits() as usize;
414 408
415 // Stop timer 409 // Stop timer
416 rt.tasks_stop.write(|w| unsafe { w.bits(1) }); 410 self.timer.stop();
417 r.events_rxstarted.reset(); 411 r.events_rxstarted.reset();
418 412
419 drop.defuse(); 413 drop.defuse();