aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-05 02:56:15 +0100
committerGitHub <[email protected]>2023-03-05 02:56:15 +0100
commitd91efe3e6252336a6e226700ca72afef2e13abc0 (patch)
treea940edf957ef7facb29d9881351abafd3f802747 /embassy-nrf/src
parentbef559307c2b63540e73539e3ba906f4c370a131 (diff)
parent7650fea5f2bed1c39a0ff6c5934709d316547a23 (diff)
Merge pull request #1208 from embassy-rs/nrf-uarte-lockfree
nrf/buffered_uarte: make it work without rts/cts, and lock-free.
Diffstat (limited to 'embassy-nrf/src')
-rw-r--r--embassy-nrf/src/buffered_uarte.rs825
-rw-r--r--embassy-nrf/src/lib.rs1
-rw-r--r--embassy-nrf/src/ppi/dppi.rs2
-rw-r--r--embassy-nrf/src/ppi/mod.rs104
-rw-r--r--embassy-nrf/src/ppi/ppi.rs2
-rw-r--r--embassy-nrf/src/timer.rs43
-rw-r--r--embassy-nrf/src/uarte.rs5
7 files changed, 627 insertions, 355 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 112f084c1..ab639aeea 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -1,10 +1,5 @@
1//! Async buffered UART driver. 1//! Async buffered UART driver.
2//! 2//!
3//! WARNING!!! The functionality provided here is intended to be used only
4//! in situations where hardware flow control are available i.e. CTS and RTS.
5//! This is a problem that should be addressed at a later stage and can be
6//! fully explained at <https://github.com/embassy-rs/embassy/issues/536>.
7//!
8//! Note that discarding a future from a read or write operation may lead to losing 3//! Note that discarding a future from a read or write operation may lead to losing
9//! data. For example, when using `futures_util::future::select` and completion occurs 4//! data. For example, when using `futures_util::future::select` and completion occurs
10//! on the "other" future, you should capture the incomplete future and continue to use 5//! on the "other" future, you should capture the incomplete future and continue to use
@@ -13,82 +8,128 @@
13//! 8//!
14//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used. 9//! Please also see [crate::uarte] to understand when [BufferedUarte] should be used.
15 10
16use core::cell::RefCell;
17use core::cmp::min; 11use core::cmp::min;
18use core::future::poll_fn; 12use core::future::poll_fn;
19use core::sync::atomic::{compiler_fence, Ordering}; 13use core::slice;
14use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering};
20use core::task::Poll; 15use core::task::Poll;
21 16
22use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 17use embassy_cortex_m::interrupt::Interrupt;
23use embassy_hal_common::ring_buffer::RingBuffer; 18use embassy_hal_common::atomic_ring_buffer::RingBuffer;
24use embassy_hal_common::{into_ref, PeripheralRef}; 19use embassy_hal_common::{into_ref, PeripheralRef};
25use embassy_sync::waitqueue::WakerRegistration; 20use embassy_sync::waitqueue::AtomicWaker;
26// Re-export SVD variants to allow user to directly set values 21// Re-export SVD variants to allow user to directly set values
27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 22pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
28 23
29use crate::gpio::{self, Pin as GpioPin}; 24use crate::gpio::sealed::Pin;
25use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
30use crate::interrupt::InterruptExt; 26use crate::interrupt::InterruptExt;
31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 27use crate::ppi::{
32use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 28 self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task,
29};
30use crate::timer::{Instance as TimerInstance, Timer};
33use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance}; 31use crate::uarte::{apply_workaround_for_enable_anomaly, Config, Instance as UarteInstance};
34use crate::{pac, Peripheral}; 32use crate::{pac, Peripheral};
35 33
36#[derive(Copy, Clone, Debug, PartialEq)] 34mod sealed {
37enum RxState { 35 use super::*;
38 Idle,
39 Receiving,
40}
41 36
42#[derive(Copy, Clone, Debug, PartialEq)] 37 pub struct State {
43enum TxState { 38 pub tx_waker: AtomicWaker,
44 Idle, 39 pub tx_buf: RingBuffer,
45 Transmitting(usize), 40 pub tx_count: AtomicUsize,
46}
47 41
48/// A type for storing the state of the UARTE peripheral that can be stored in a static. 42 pub rx_waker: AtomicWaker,
49pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>); 43 pub rx_buf: RingBuffer,
50impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> { 44 pub rx_bufs: AtomicU8,
51 /// Create an instance for storing UARTE peripheral state. 45 pub rx_ppi_ch: AtomicU8,
52 pub fn new() -> Self {
53 Self(StateStorage::new())
54 } 46 }
55} 47}
56 48
57struct StateInner<'d, U: UarteInstance, T: TimerInstance> { 49/// UART error.
58 _peri: PeripheralRef<'d, U>, 50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59 timer: Timer<'d, T>, 51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, 52#[non_exhaustive]
61 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, 53pub enum Error {
54 // No errors for now
55}
62 56
63 rx: RingBuffer<'d>, 57pub(crate) use sealed::State;
64 rx_state: RxState,
65 rx_waker: WakerRegistration,
66 58
67 tx: RingBuffer<'d>, 59impl State {
68 tx_state: TxState, 60 pub(crate) const fn new() -> Self {
69 tx_waker: WakerRegistration, 61 Self {
62 tx_waker: AtomicWaker::new(),
63 tx_buf: RingBuffer::new(),
64 tx_count: AtomicUsize::new(0),
65
66 rx_waker: AtomicWaker::new(),
67 rx_buf: RingBuffer::new(),
68 rx_bufs: AtomicU8::new(0),
69 rx_ppi_ch: AtomicU8::new(0),
70 }
71 }
70} 72}
71 73
72/// Buffered UARTE driver. 74/// Buffered UARTE driver.
73pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { 75pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
74 inner: RefCell<PeripheralMutex<'d, StateInner<'d, U, T>>>, 76 _peri: PeripheralRef<'d, U>,
77 timer: Timer<'d, T>,
78 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>,
79 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>,
80 _ppi_group: PpiGroup<'d, AnyGroup>,
75} 81}
76 82
77impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} 83impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {}
78 84
79impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { 85impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
80 /// Create a new instance of a BufferedUarte. 86 /// Create a new BufferedUarte without hardware flow control.
81 /// 87 ///
82 /// See the [module documentation](crate::buffered_uarte) for more details about the intended use. 88 /// # Panics
83 /// 89 ///
84 /// The BufferedUarte uses the provided state to store the buffers and peripheral state. The timer and ppi channels are used to 'emulate' idle line detection so that read operations 90 /// Panics if `rx_buffer.len()` is odd.
85 /// can return early if there is no data to receive.
86 pub fn new( 91 pub fn new(
87 state: &'d mut State<'d, U, T>, 92 uarte: impl Peripheral<P = U> + 'd,
88 peri: impl Peripheral<P = U> + 'd, 93 timer: impl Peripheral<P = T> + 'd,
94 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
95 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
96 ppi_group: impl Peripheral<P = impl Group> + 'd,
97 irq: impl Peripheral<P = U::Interrupt> + 'd,
98 rxd: impl Peripheral<P = impl GpioPin> + 'd,
99 txd: impl Peripheral<P = impl GpioPin> + 'd,
100 config: Config,
101 rx_buffer: &'d mut [u8],
102 tx_buffer: &'d mut [u8],
103 ) -> Self {
104 into_ref!(rxd, txd, ppi_ch1, ppi_ch2, ppi_group);
105 Self::new_inner(
106 uarte,
107 timer,
108 ppi_ch1.map_into(),
109 ppi_ch2.map_into(),
110 ppi_group.map_into(),
111 irq,
112 rxd.map_into(),
113 txd.map_into(),
114 None,
115 None,
116 config,
117 rx_buffer,
118 tx_buffer,
119 )
120 }
121
122 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
123 ///
124 /// # Panics
125 ///
126 /// Panics if `rx_buffer.len()` is odd.
127 pub fn new_with_rtscts(
128 uarte: impl Peripheral<P = U> + 'd,
89 timer: impl Peripheral<P = T> + 'd, 129 timer: impl Peripheral<P = T> + 'd,
90 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 130 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
91 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 131 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
132 ppi_group: impl Peripheral<P = impl Group> + 'd,
92 irq: impl Peripheral<P = U::Interrupt> + 'd, 133 irq: impl Peripheral<P = U::Interrupt> + 'd,
93 rxd: impl Peripheral<P = impl GpioPin> + 'd, 134 rxd: impl Peripheral<P = impl GpioPin> + 'd,
94 txd: impl Peripheral<P = impl GpioPin> + 'd, 135 txd: impl Peripheral<P = impl GpioPin> + 'd,
@@ -98,11 +139,44 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
98 rx_buffer: &'d mut [u8], 139 rx_buffer: &'d mut [u8],
99 tx_buffer: &'d mut [u8], 140 tx_buffer: &'d mut [u8],
100 ) -> Self { 141 ) -> Self {
101 into_ref!(peri, ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); 142 into_ref!(rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group);
143 Self::new_inner(
144 uarte,
145 timer,
146 ppi_ch1.map_into(),
147 ppi_ch2.map_into(),
148 ppi_group.map_into(),
149 irq,
150 rxd.map_into(),
151 txd.map_into(),
152 Some(cts.map_into()),
153 Some(rts.map_into()),
154 config,
155 rx_buffer,
156 tx_buffer,
157 )
158 }
102 159
103 let r = U::regs(); 160 fn new_inner(
161 peri: impl Peripheral<P = U> + 'd,
162 timer: impl Peripheral<P = T> + 'd,
163 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
164 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
165 ppi_group: PeripheralRef<'d, AnyGroup>,
166 irq: impl Peripheral<P = U::Interrupt> + 'd,
167 rxd: PeripheralRef<'d, AnyPin>,
168 txd: PeripheralRef<'d, AnyPin>,
169 cts: Option<PeripheralRef<'d, AnyPin>>,
170 rts: Option<PeripheralRef<'d, AnyPin>>,
171 config: Config,
172 rx_buffer: &'d mut [u8],
173 tx_buffer: &'d mut [u8],
174 ) -> Self {
175 into_ref!(peri, timer, irq);
176
177 assert!(rx_buffer.len() % 2 == 0);
104 178
105 let mut timer = Timer::new(timer); 179 let r = U::regs();
106 180
107 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 181 rxd.conf().write(|w| w.input().connect().drive().h0h1());
108 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 182 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@@ -111,92 +185,200 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
111 txd.conf().write(|w| w.dir().output().drive().h0h1()); 185 txd.conf().write(|w| w.dir().output().drive().h0h1());
112 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); 186 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
113 187
114 cts.conf().write(|w| w.input().connect().drive().h0h1()); 188 if let Some(pin) = &cts {
189 pin.conf().write(|w| w.input().connect().drive().h0h1());
190 }
115 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); 191 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
116 192
117 rts.set_high(); 193 if let Some(pin) = &rts {
118 rts.conf().write(|w| w.dir().output().drive().h0h1()); 194 pin.set_high();
195 pin.conf().write(|w| w.dir().output().drive().h0h1());
196 }
119 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 197 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
120 198
121 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 199 // Initialize state
122 r.config.write(|w| w.parity().variant(config.parity)); 200 let s = U::buffered_state();
201 s.tx_count.store(0, Ordering::Relaxed);
202 s.rx_bufs.store(0, Ordering::Relaxed);
203 let len = tx_buffer.len();
204 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
205 let len = rx_buffer.len();
206 unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
123 207
124 // Configure 208 // Configure
125 r.config.write(|w| { 209 r.config.write(|w| {
126 w.hwfc().bit(true); 210 w.hwfc().bit(false);
127 w.parity().variant(config.parity); 211 w.parity().variant(config.parity);
128 w 212 w
129 }); 213 });
130 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 214 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
131 215
132 // Enable interrupts 216 // clear errors
133 r.intenset.write(|w| w.endrx().set().endtx().set()); 217 let errors = r.errorsrc.read().bits();
218 r.errorsrc.write(|w| unsafe { w.bits(errors) });
134 219
135 // Disable the irq, let the Registration enable it when everything is set up. 220 r.events_rxstarted.reset();
136 irq.disable(); 221 r.events_txstarted.reset();
137 irq.pend(); 222 r.events_error.reset();
223 r.events_endrx.reset();
224 r.events_endtx.reset();
225
226 // Enable interrupts
227 r.intenclr.write(|w| unsafe { w.bits(!0) });
228 r.intenset.write(|w| {
229 w.endtx().set();
230 w.rxstarted().set();
231 w.error().set();
232 w
233 });
138 234
139 // Enable UARTE instance 235 // Enable UARTE instance
140 apply_workaround_for_enable_anomaly(&r); 236 apply_workaround_for_enable_anomaly(&r);
141 r.enable.write(|w| w.enable().enabled()); 237 r.enable.write(|w| w.enable().enabled());
142 238
143 // BAUDRATE register values are `baudrate * 2^32 / 16000000` 239 // Configure byte counter.
144 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values 240 let mut timer = Timer::new_counter(timer);
145 // 241 timer.cc(1).write(rx_buffer.len() as u32 * 2);
146 // We want to stop RX if line is idle for 2 bytes worth of time 242 timer.cc(1).short_compare_clear();
147 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) 243 timer.clear();
148 // This gives us the amount of 16M ticks for 20 bits. 244 timer.start();
149 let timeout = 0x8000_0000 / (config.baudrate as u32 / 40);
150 245
151 timer.set_frequency(Frequency::F16MHz); 246 let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_rxdrdy), timer.task_count());
152 timer.cc(0).write(timeout);
153 timer.cc(0).short_compare_clear();
154 timer.cc(0).short_compare_stop();
155
156 let mut ppi_ch1 = Ppi::new_one_to_two(
157 ppi_ch1.map_into(),
158 Event::from_reg(&r.events_rxdrdy),
159 timer.task_clear(),
160 timer.task_start(),
161 );
162 ppi_ch1.enable(); 247 ppi_ch1.enable();
163 248
164 let mut ppi_ch2 = Ppi::new_one_to_one( 249 s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed);
165 ppi_ch2.map_into(), 250 let mut ppi_group = PpiGroup::new(ppi_group);
166 timer.cc(0).event_compare(), 251 let mut ppi_ch2 = Ppi::new_one_to_two(
167 Task::from_reg(&r.tasks_stoprx), 252 ppi_ch2,
253 Event::from_reg(&r.events_endrx),
254 Task::from_reg(&r.tasks_startrx),
255 ppi_group.task_disable_all(),
168 ); 256 );
169 ppi_ch2.enable(); 257 ppi_ch2.disable();
258 ppi_group.add_channel(&ppi_ch2);
259
260 irq.disable();
261 irq.set_handler(Self::on_interrupt);
262 irq.pend();
263 irq.enable();
170 264
171 Self { 265 Self {
172 inner: RefCell::new(PeripheralMutex::new(irq, &mut state.0, move || StateInner { 266 _peri: peri,
173 _peri: peri, 267 timer,
174 timer, 268 _ppi_ch1: ppi_ch1,
175 _ppi_ch1: ppi_ch1, 269 _ppi_ch2: ppi_ch2,
176 _ppi_ch2: ppi_ch2, 270 _ppi_group: ppi_group,
177
178 rx: RingBuffer::new(rx_buffer),
179 rx_state: RxState::Idle,
180 rx_waker: WakerRegistration::new(),
181
182 tx: RingBuffer::new(tx_buffer),
183 tx_state: TxState::Idle,
184 tx_waker: WakerRegistration::new(),
185 })),
186 } 271 }
187 } 272 }
188 273
189 /// Adjust the baud rate to the provided value. 274 fn pend_irq() {
190 pub fn set_baudrate(&mut self, baudrate: Baudrate) { 275 unsafe { <U::Interrupt as Interrupt>::steal() }.pend()
191 self.inner.borrow_mut().with(|state| { 276 }
192 let r = U::regs(); 277
278 fn on_interrupt(_: *mut ()) {
279 //trace!("irq: start");
280 let r = U::regs();
281 let s = U::buffered_state();
193 282
194 let timeout = 0x8000_0000 / (baudrate as u32 / 40); 283 let buf_len = s.rx_buf.len();
195 state.timer.cc(0).write(timeout); 284 let half_len = buf_len / 2;
196 state.timer.clear(); 285 let mut tx = unsafe { s.tx_buf.reader() };
286 let mut rx = unsafe { s.rx_buf.writer() };
197 287
198 r.baudrate.write(|w| w.baudrate().variant(baudrate)); 288 if r.events_error.read().bits() != 0 {
199 }); 289 r.events_error.reset();
290 let errs = r.errorsrc.read();
291 r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) });
292
293 if errs.overrun().bit() {
294 panic!("BufferedUarte overrun");
295 }
296 }
297
298 // Received some bytes, wake task.
299 if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().bits() != 0 {
300 r.intenclr.write(|w| w.rxdrdy().clear());
301 r.events_rxdrdy.reset();
302 s.rx_waker.wake();
303 }
304
305 // If not RXing, start.
306 if s.rx_bufs.load(Ordering::Relaxed) == 0 {
307 let (ptr, len) = rx.push_buf();
308 if len >= half_len {
309 //trace!(" irq_rx: starting {:?}", half_len);
310 s.rx_bufs.store(1, Ordering::Relaxed);
311
312 // Set up the DMA read
313 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
314 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
315
316 // Start UARTE Receive transaction
317 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
318 rx.push_done(half_len);
319 r.intenset.write(|w| w.rxstarted().set());
320 }
321 }
322
323 if r.events_rxstarted.read().bits() != 0 {
324 //trace!(" irq_rx: rxstarted");
325 let (ptr, len) = rx.push_buf();
326 if len >= half_len {
327 //trace!(" irq_rx: starting second {:?}", half_len);
328
329 // Set up the DMA read
330 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
331 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
332
333 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
334
335 ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
336
337 rx.push_done(half_len);
338
339 r.events_rxstarted.reset();
340 } else {
341 //trace!(" irq_rx: rxstarted no buf");
342 r.intenclr.write(|w| w.rxstarted().clear());
343 }
344 }
345
346 // =============================
347
348 // TX end
349 if r.events_endtx.read().bits() != 0 {
350 r.events_endtx.reset();
351
352 let n = s.tx_count.load(Ordering::Relaxed);
353 //trace!(" irq_tx: endtx {:?}", n);
354 tx.pop_done(n);
355 s.tx_waker.wake();
356 s.tx_count.store(0, Ordering::Relaxed);
357 }
358
359 // If not TXing, start.
360 if s.tx_count.load(Ordering::Relaxed) == 0 {
361 let (ptr, len) = tx.pop_buf();
362 if len != 0 {
363 //trace!(" irq_tx: starting {:?}", len);
364 s.tx_count.store(len, Ordering::Relaxed);
365
366 // Set up the DMA write
367 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
368 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
369
370 // Start UARTE Transmit transaction
371 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
372 }
373 }
374
375 //trace!("irq: end");
376 }
377
378 /// Adjust the baud rate to the provided value.
379 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
380 let r = U::regs();
381 r.baudrate.write(|w| w.baudrate().variant(baudrate));
200 } 382 }
201 383
202 /// Split the UART in reader and writer parts. 384 /// Split the UART in reader and writer parts.
@@ -206,120 +388,142 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
206 (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self }) 388 (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self })
207 } 389 }
208 390
209 async fn inner_read<'a>(&'a self, buf: &'a mut [u8]) -> Result<usize, core::convert::Infallible> { 391 async fn inner_read(&self, buf: &mut [u8]) -> Result<usize, Error> {
392 let data = self.inner_fill_buf().await?;
393 let n = data.len().min(buf.len());
394 buf[..n].copy_from_slice(&data[..n]);
395 self.inner_consume(n);
396 Ok(n)
397 }
398
399 async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, Error> {
210 poll_fn(move |cx| { 400 poll_fn(move |cx| {
211 let mut do_pend = false; 401 //trace!("poll_write: {:?}", buf.len());
212 let mut inner = self.inner.borrow_mut(); 402 let s = U::buffered_state();
213 let res = inner.with(|state| { 403 let mut tx = unsafe { s.tx_buf.writer() };
214 compiler_fence(Ordering::SeqCst); 404
215 trace!("poll_read"); 405 let tx_buf = tx.push_slice();
216 406 if tx_buf.is_empty() {
217 // We have data ready in buffer? Return it. 407 //trace!("poll_write: pending");
218 let data = state.rx.pop_buf(); 408 s.tx_waker.register(cx.waker());
219 if !data.is_empty() { 409 return Poll::Pending;
220 trace!(" got {:?} {:?}", data.as_ptr() as u32, data.len());
221 let len = data.len().min(buf.len());
222 buf[..len].copy_from_slice(&data[..len]);
223 state.rx.pop(len);
224 do_pend = true;
225 return Poll::Ready(Ok(len));
226 }
227
228 trace!(" empty");
229 state.rx_waker.register(cx.waker());
230 Poll::Pending
231 });
232 if do_pend {
233 inner.pend();
234 } 410 }
235 411
236 res 412 let n = min(tx_buf.len(), buf.len());
413 tx_buf[..n].copy_from_slice(&buf[..n]);
414 tx.push_done(n);
415
416 //trace!("poll_write: queued {:?}", n);
417
418 compiler_fence(Ordering::SeqCst);
419 Self::pend_irq();
420
421 Poll::Ready(Ok(n))
237 }) 422 })
238 .await 423 .await
239 } 424 }
240 425
241 async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, core::convert::Infallible> { 426 async fn inner_flush<'a>(&'a self) -> Result<(), Error> {
242 poll_fn(move |cx| { 427 poll_fn(move |cx| {
243 let mut inner = self.inner.borrow_mut(); 428 //trace!("poll_flush");
244 let res = inner.with(|state| { 429 let s = U::buffered_state();
245 trace!("poll_write: {:?}", buf.len()); 430 if !s.tx_buf.is_empty() {
431 //trace!("poll_flush: pending");
432 s.tx_waker.register(cx.waker());
433 return Poll::Pending;
434 }
246 435
247 let tx_buf = state.tx.push_buf(); 436 Poll::Ready(Ok(()))
248 if tx_buf.is_empty() { 437 })
249 trace!("poll_write: pending"); 438 .await
250 state.tx_waker.register(cx.waker()); 439 }
251 return Poll::Pending;
252 }
253 440
254 let n = min(tx_buf.len(), buf.len()); 441 async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], Error> {
255 tx_buf[..n].copy_from_slice(&buf[..n]); 442 poll_fn(move |cx| {
256 state.tx.push(n); 443 compiler_fence(Ordering::SeqCst);
444 //trace!("poll_read");
257 445
258 trace!("poll_write: queued {:?}", n); 446 let r = U::regs();
447 let s = U::buffered_state();
448
449 // Read the RXDRDY counter.
450 T::regs().tasks_capture[0].write(|w| unsafe { w.bits(1) });
451 let mut end = T::regs().cc[0].read().bits() as usize;
452 //trace!(" rxdrdy count = {:?}", end);
453
454 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
455 // However, it's unclear if that's instant, or there's a small window where you can
456 // still read `len()*2`.
457 // This could happen if in one clock cycle the counter is updated, and in the next the
458 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
459 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
460 // clock cycle of the PCLK16M." :shrug:
461 // So, we wrap the counter ourselves, just in case.
462 if end > s.rx_buf.len() * 2 {
463 end = 0
464 }
259 465
260 compiler_fence(Ordering::SeqCst); 466 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()`
467 let mut start = s.rx_buf.start.load(Ordering::Relaxed);
468 let len = s.rx_buf.len();
469 if start == end {
470 //trace!(" empty");
471 s.rx_waker.register(cx.waker());
472 r.intenset.write(|w| w.rxdrdy().set_bit());
473 return Poll::Pending;
474 }
261 475
262 Poll::Ready(Ok(n)) 476 if start >= len {
263 }); 477 start -= len
478 }
479 if end >= len {
480 end -= len
481 }
264 482
265 inner.pend(); 483 let n = if end > start { end - start } else { len - start };
484 assert!(n != 0);
485 //trace!(" uarte ringbuf: pop_buf {:?}..{:?}", start, start + n);
266 486
267 res 487 let buf = s.rx_buf.buf.load(Ordering::Relaxed);
488 Poll::Ready(Ok(unsafe { slice::from_raw_parts(buf.add(start), n) }))
268 }) 489 })
269 .await 490 .await
270 } 491 }
271 492
272 async fn inner_flush<'a>(&'a self) -> Result<(), core::convert::Infallible> { 493 fn inner_consume(&self, amt: usize) {
273 poll_fn(move |cx| { 494 if amt == 0 {
274 self.inner.borrow_mut().with(|state| { 495 return;
275 trace!("poll_flush"); 496 }
276 497
277 if !state.tx.is_empty() { 498 let s = U::buffered_state();
278 trace!("poll_flush: pending"); 499 let mut rx = unsafe { s.rx_buf.reader() };
279 state.tx_waker.register(cx.waker()); 500 rx.pop_done(amt);
280 return Poll::Pending; 501 U::regs().intenset.write(|w| w.rxstarted().set());
281 } 502 }
282 503
283 Poll::Ready(Ok(())) 504 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
284 }) 505 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
285 }) 506 self.inner_read(buf).await
286 .await
287 } 507 }
288 508
289 async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], core::convert::Infallible> { 509 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
290 poll_fn(move |cx| { 510 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
291 self.inner.borrow_mut().with(|state| { 511 self.inner_fill_buf().await
292 compiler_fence(Ordering::SeqCst);
293 trace!("fill_buf");
294
295 // We have data ready in buffer? Return it.
296 let buf = state.rx.pop_buf();
297 if !buf.is_empty() {
298 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
299 let buf: &[u8] = buf;
300 // Safety: buffer lives as long as uart
301 let buf: &[u8] = unsafe { core::mem::transmute(buf) };
302 return Poll::Ready(Ok(buf));
303 }
304
305 trace!(" empty");
306 state.rx_waker.register(cx.waker());
307 Poll::<Result<&[u8], core::convert::Infallible>>::Pending
308 })
309 })
310 .await
311 } 512 }
312 513
313 fn inner_consume(&self, amt: usize) { 514 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
314 let mut inner = self.inner.borrow_mut(); 515 pub fn consume(&mut self, amt: usize) {
315 let signal = inner.with(|state| { 516 self.inner_consume(amt)
316 let full = state.rx.is_full(); 517 }
317 state.rx.pop(amt); 518
318 full 519 /// Write a buffer into this writer, returning how many bytes were written.
319 }); 520 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
320 if signal { 521 self.inner_write(buf).await
321 inner.pend(); 522 }
322 } 523
524 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
525 pub async fn flush(&mut self) -> Result<(), Error> {
526 self.inner_flush().await
323 } 527 }
324} 528}
325 529
@@ -328,76 +532,116 @@ pub struct BufferedUarteTx<'u, 'd, U: UarteInstance, T: TimerInstance> {
328 inner: &'u BufferedUarte<'d, U, T>, 532 inner: &'u BufferedUarte<'d, U, T>,
329} 533}
330 534
535impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteTx<'u, 'd, U, T> {
536 /// Write a buffer into this writer, returning how many bytes were written.
537 pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
538 self.inner.inner_write(buf).await
539 }
540
541 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
542 pub async fn flush(&mut self) -> Result<(), Error> {
543 self.inner.inner_flush().await
544 }
545}
546
331/// Writer part of the buffered UARTE driver. 547/// Writer part of the buffered UARTE driver.
332pub struct BufferedUarteRx<'u, 'd, U: UarteInstance, T: TimerInstance> { 548pub struct BufferedUarteRx<'u, 'd, U: UarteInstance, T: TimerInstance> {
333 inner: &'u BufferedUarte<'d, U, T>, 549 inner: &'u BufferedUarte<'d, U, T>,
334} 550}
335 551
336impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> { 552impl<'u, 'd, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'u, 'd, U, T> {
337 type Error = core::convert::Infallible; 553 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
338} 554 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
555 self.inner.inner_read(buf).await
556 }
339 557
340impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteRx<'u, 'd, U, T> { 558 /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty.
341 type Error = core::convert::Infallible; 559 pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
342} 560 self.inner.inner_fill_buf().await
561 }
343 562
344impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteTx<'u, 'd, U, T> { 563 /// Tell this buffer that `amt` bytes have been consumed from the buffer, so they should no longer be returned in calls to `fill_buf`.
345 type Error = core::convert::Infallible; 564 pub fn consume(&mut self, amt: usize) {
565 self.inner.inner_consume(amt)
566 }
346} 567}
347 568
348impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> { 569#[cfg(feature = "nightly")]
349 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 570mod _embedded_io {
350 self.inner_read(buf).await 571 use super::*;
572
573 impl embedded_io::Error for Error {
574 fn kind(&self) -> embedded_io::ErrorKind {
575 match *self {}
576 }
351 } 577 }
352}
353 578
354impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> { 579 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarte<'d, U, T> {
355 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 580 type Error = Error;
356 self.inner.inner_read(buf).await
357 } 581 }
358}
359 582
360impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> { 583 impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteRx<'u, 'd, U, T> {
361 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { 584 type Error = Error;
362 self.inner_fill_buf().await
363 } 585 }
364 586
365 fn consume(&mut self, amt: usize) { 587 impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUarteTx<'u, 'd, U, T> {
366 self.inner_consume(amt) 588 type Error = Error;
367 } 589 }
368}
369 590
370impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> { 591 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> {
371 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { 592 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
372 self.inner.inner_fill_buf().await 593 self.inner_read(buf).await
594 }
373 } 595 }
374 596
375 fn consume(&mut self, amt: usize) { 597 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> {
376 self.inner.inner_consume(amt) 598 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
599 self.inner.inner_read(buf).await
600 }
377 } 601 }
378}
379 602
380impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> { 603 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> {
381 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { 604 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
382 self.inner_write(buf).await 605 self.inner_fill_buf().await
606 }
607
608 fn consume(&mut self, amt: usize) {
609 self.inner_consume(amt)
610 }
383 } 611 }
384 612
385 async fn flush(&mut self) -> Result<(), Self::Error> { 613 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> {
386 self.inner_flush().await 614 async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
615 self.inner.inner_fill_buf().await
616 }
617
618 fn consume(&mut self, amt: usize) {
619 self.inner.inner_consume(amt)
620 }
387 } 621 }
388}
389 622
390impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> { 623 impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> {
391 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { 624 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
392 self.inner.inner_write(buf).await 625 self.inner_write(buf).await
626 }
627
628 async fn flush(&mut self) -> Result<(), Self::Error> {
629 self.inner_flush().await
630 }
393 } 631 }
394 632
395 async fn flush(&mut self) -> Result<(), Self::Error> { 633 impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> {
396 self.inner.inner_flush().await 634 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
635 self.inner.inner_write(buf).await
636 }
637
638 async fn flush(&mut self) -> Result<(), Self::Error> {
639 self.inner.inner_flush().await
640 }
397 } 641 }
398} 642}
399 643
400impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> { 644impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarte<'a, U, T> {
401 fn drop(&mut self) { 645 fn drop(&mut self) {
402 let r = U::regs(); 646 let r = U::regs();
403 647
@@ -418,108 +662,11 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> {
418 gpio::deconfigure_pin(r.psel.txd.read().bits()); 662 gpio::deconfigure_pin(r.psel.txd.read().bits());
419 gpio::deconfigure_pin(r.psel.rts.read().bits()); 663 gpio::deconfigure_pin(r.psel.rts.read().bits());
420 gpio::deconfigure_pin(r.psel.cts.read().bits()); 664 gpio::deconfigure_pin(r.psel.cts.read().bits());
421 }
422}
423 665
424impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, U, T> { 666 let s = U::buffered_state();
425 type Interrupt = U::Interrupt; 667 unsafe {
426 fn on_interrupt(&mut self) { 668 s.rx_buf.deinit();
427 trace!("irq: start"); 669 s.tx_buf.deinit();
428 let r = U::regs();
429
430 loop {
431 match self.rx_state {
432 RxState::Idle => {
433 trace!(" irq_rx: in state idle");
434
435 let buf = self.rx.push_buf();
436 if !buf.is_empty() {
437 trace!(" irq_rx: starting {:?}", buf.len());
438 self.rx_state = RxState::Receiving;
439
440 // Set up the DMA read
441 r.rxd.ptr.write(|w|
442 // The PTR field is a full 32 bits wide and accepts the full range
443 // of values.
444 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
445 r.rxd.maxcnt.write(|w|
446 // We're giving it the length of the buffer, so no danger of
447 // accessing invalid memory. We have verified that the length of the
448 // buffer fits in an `u8`, so the cast to `u8` is also fine.
449 //
450 // The MAXCNT field is at least 8 bits wide and accepts the full
451 // range of values.
452 unsafe { w.maxcnt().bits(buf.len() as _) });
453 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
454
455 // Start UARTE Receive transaction
456 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
457 }
458 break;
459 }
460 RxState::Receiving => {
461 trace!(" irq_rx: in state receiving");
462 if r.events_endrx.read().bits() != 0 {
463 self.timer.stop();
464
465 let n: usize = r.rxd.amount.read().amount().bits() as usize;
466 trace!(" irq_rx: endrx {:?}", n);
467 self.rx.push(n);
468
469 r.events_endrx.reset();
470
471 self.rx_waker.wake();
472 self.rx_state = RxState::Idle;
473 } else {
474 break;
475 }
476 }
477 }
478 }
479
480 loop {
481 match self.tx_state {
482 TxState::Idle => {
483 trace!(" irq_tx: in state Idle");
484 let buf = self.tx.pop_buf();
485 if !buf.is_empty() {
486 trace!(" irq_tx: starting {:?}", buf.len());
487 self.tx_state = TxState::Transmitting(buf.len());
488
489 // Set up the DMA write
490 r.txd.ptr.write(|w|
491 // The PTR field is a full 32 bits wide and accepts the full range
492 // of values.
493 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
494 r.txd.maxcnt.write(|w|
495 // We're giving it the length of the buffer, so no danger of
496 // accessing invalid memory. We have verified that the length of the
497 // buffer fits in an `u8`, so the cast to `u8` is also fine.
498 //
499 // The MAXCNT field is 8 bits wide and accepts the full range of
500 // values.
501 unsafe { w.maxcnt().bits(buf.len() as _) });
502
503 // Start UARTE Transmit transaction
504 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
505 }
506 break;
507 }
508 TxState::Transmitting(n) => {
509 trace!(" irq_tx: in state Transmitting");
510 if r.events_endtx.read().bits() != 0 {
511 r.events_endtx.reset();
512
513 trace!(" irq_tx: endtx {:?}", n);
514 self.tx.pop(n);
515 self.tx_waker.wake();
516 self.tx_state = TxState::Idle;
517 } else {
518 break;
519 }
520 }
521 }
522 } 670 }
523 trace!("irq: end");
524 } 671 }
525} 672}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index a9683df44..6b7dc7791 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -37,7 +37,6 @@ pub(crate) mod util;
37#[cfg(feature = "_time-driver")] 37#[cfg(feature = "_time-driver")]
38mod time_driver; 38mod time_driver;
39 39
40#[cfg(feature = "nightly")]
41pub mod buffered_uarte; 40pub mod buffered_uarte;
42pub mod gpio; 41pub mod gpio;
43#[cfg(feature = "gpiote")] 42#[cfg(feature = "gpiote")]
diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs
index 0908cd7be..3a1e7f170 100644
--- a/embassy-nrf/src/ppi/dppi.rs
+++ b/embassy-nrf/src/ppi/dppi.rs
@@ -6,7 +6,7 @@ use crate::{pac, Peripheral};
6const DPPI_ENABLE_BIT: u32 = 0x8000_0000; 6const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
7const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; 7const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
8 8
9fn regs() -> &'static pac::dppic::RegisterBlock { 9pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock {
10 unsafe { &*pac::DPPIC::ptr() } 10 unsafe { &*pac::DPPIC::ptr() }
11} 11}
12 12
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index b76eccf0b..7c18da6ee 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -17,16 +17,16 @@
17 17
18use core::ptr::NonNull; 18use core::ptr::NonNull;
19 19
20use embassy_hal_common::{impl_peripheral, PeripheralRef}; 20use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
21 21
22use crate::{peripherals, Peripheral}; 22use crate::{peripherals, Peripheral};
23 23
24#[cfg(feature = "_dppi")] 24#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
25mod dppi; 25#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
26#[cfg(feature = "_ppi")] 26mod _version;
27mod ppi; 27pub(crate) use _version::*;
28 28
29/// An instance of the Programmable peripheral interconnect on nRF devices. 29/// PPI channel driver.
30pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { 30pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
31 ch: PeripheralRef<'d, C>, 31 ch: PeripheralRef<'d, C>,
32 #[cfg(feature = "_dppi")] 32 #[cfg(feature = "_dppi")]
@@ -35,6 +35,88 @@ pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize
35 tasks: [Task; TASK_COUNT], 35 tasks: [Task; TASK_COUNT],
36} 36}
37 37
38/// PPI channel group driver.
39pub struct PpiGroup<'d, G: Group> {
40 g: PeripheralRef<'d, G>,
41}
42
43impl<'d, G: Group> PpiGroup<'d, G> {
44 /// Create a new PPI group driver.
45 ///
46 /// The group is initialized as containing no channels.
47 pub fn new(g: impl Peripheral<P = G> + 'd) -> Self {
48 into_ref!(g);
49
50 let r = regs();
51 let n = g.number();
52 r.chg[n].write(|w| unsafe { w.bits(0) });
53
54 Self { g }
55 }
56
57 /// Add a PPI channel to this group.
58 ///
59 /// If the channel is already in the group, this is a no-op.
60 pub fn add_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
61 &mut self,
62 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
63 ) {
64 let r = regs();
65 let ng = self.g.number();
66 let nc = ch.ch.number();
67 r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() | 1 << nc) });
68 }
69
70 /// Remove a PPI channel from this group.
71 ///
72 /// If the channel is already not in the group, this is a no-op.
73 pub fn remove_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
74 &mut self,
75 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
76 ) {
77 let r = regs();
78 let ng = self.g.number();
79 let nc = ch.ch.number();
80 r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() & !(1 << nc)) });
81 }
82
83 /// Enable all the channels in this group.
84 pub fn enable_all(&mut self) {
85 let n = self.g.number();
86 regs().tasks_chg[n].en.write(|w| unsafe { w.bits(1) });
87 }
88
89 /// Disable all the channels in this group.
90 pub fn disable_all(&mut self) {
91 let n = self.g.number();
92 regs().tasks_chg[n].dis.write(|w| unsafe { w.bits(1) });
93 }
94
95 /// Get a reference to the "enable all" task.
96 ///
97 /// When triggered, it will enable all the channels in this group.
98 pub fn task_enable_all(&self) -> Task {
99 let n = self.g.number();
100 Task::from_reg(&regs().tasks_chg[n].en)
101 }
102
103 /// Get a reference to the "disable all" task.
104 ///
105 /// When triggered, it will disable all the channels in this group.
106 pub fn task_disable_all(&self) -> Task {
107 let n = self.g.number();
108 Task::from_reg(&regs().tasks_chg[n].dis)
109 }
110}
111
112impl<'d, G: Group> Drop for PpiGroup<'d, G> {
113 fn drop(&mut self) {
114 let r = regs();
115 let n = self.g.number();
116 r.chg[n].write(|w| unsafe { w.bits(0) });
117 }
118}
119
38#[cfg(feature = "_dppi")] 120#[cfg(feature = "_dppi")]
39const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>(); 121const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
40 122
@@ -112,7 +194,7 @@ pub(crate) mod sealed {
112} 194}
113 195
114/// Interface for PPI channels. 196/// Interface for PPI channels.
115pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized { 197pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized + 'static {
116 /// Returns the number of the channel 198 /// Returns the number of the channel
117 fn number(&self) -> usize; 199 fn number(&self) -> usize;
118} 200}
@@ -130,7 +212,7 @@ pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
130} 212}
131 213
132/// Interface for a group of PPI channels. 214/// Interface for a group of PPI channels.
133pub trait Group: sealed::Group + Sized { 215pub trait Group: sealed::Group + Peripheral<P = Self> + Into<AnyGroup> + Sized + 'static {
134 /// Returns the number of the group. 216 /// Returns the number of the group.
135 fn number(&self) -> usize; 217 fn number(&self) -> usize;
136 /// Convert into a type erased group. 218 /// Convert into a type erased group.
@@ -248,6 +330,12 @@ macro_rules! impl_group {
248 $number 330 $number
249 } 331 }
250 } 332 }
333
334 impl From<peripherals::$type> for crate::ppi::AnyGroup {
335 fn from(val: peripherals::$type) -> Self {
336 crate::ppi::Group::degrade(val)
337 }
338 }
251 }; 339 };
252} 340}
253 341
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs
index a96ab50b7..f1eeaee1e 100644
--- a/embassy-nrf/src/ppi/ppi.rs
+++ b/embassy-nrf/src/ppi/ppi.rs
@@ -14,7 +14,7 @@ impl Event {
14 } 14 }
15} 15}
16 16
17fn regs() -> &'static pac::ppi::RegisterBlock { 17pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock {
18 unsafe { &*pac::PPI::ptr() } 18 unsafe { &*pac::PPI::ptr() }
19} 19}
20 20
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index d1ae57237..3b0d2f1ca 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -132,7 +132,21 @@ impl<'d, T: Instance> Timer<'d, T, Awaitable> {
132 irq.unpend(); 132 irq.unpend();
133 irq.enable(); 133 irq.enable();
134 134
135 Self::new_inner(timer) 135 Self::new_inner(timer, false)
136 }
137
138 /// Create a new async-capable timer driver in counter mode.
139 pub fn new_awaitable_counter(
140 timer: impl Peripheral<P = T> + 'd,
141 irq: impl Peripheral<P = T::Interrupt> + 'd,
142 ) -> Self {
143 into_ref!(irq);
144
145 irq.set_handler(Self::on_interrupt);
146 irq.unpend();
147 irq.enable();
148
149 Self::new_inner(timer, true)
136 } 150 }
137} 151}
138 152
@@ -142,7 +156,15 @@ impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
142 /// This can be useful for triggering tasks via PPI 156 /// This can be useful for triggering tasks via PPI
143 /// `Uarte` uses this internally. 157 /// `Uarte` uses this internally.
144 pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self { 158 pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self {
145 Self::new_inner(timer) 159 Self::new_inner(timer, false)
160 }
161
162 /// Create a `Timer` driver in counter mode without an interrupt, meaning `Cc::wait` won't work.
163 ///
164 /// This can be useful for triggering tasks via PPI
165 /// `Uarte` uses this internally.
166 pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self {
167 Self::new_inner(timer, true)
146 } 168 }
147} 169}
148 170
@@ -150,7 +172,7 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
150 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work. 172 /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
151 /// 173 ///
152 /// This is used by the public constructors. 174 /// This is used by the public constructors.
153 fn new_inner(timer: impl Peripheral<P = T> + 'd) -> Self { 175 fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self {
154 into_ref!(timer); 176 into_ref!(timer);
155 177
156 let regs = T::regs(); 178 let regs = T::regs();
@@ -164,8 +186,11 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
164 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. 186 // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
165 this.stop(); 187 this.stop();
166 188
167 // Set the instance to timer mode. 189 if is_counter {
168 regs.mode.write(|w| w.mode().timer()); 190 regs.mode.write(|w| w.mode().counter());
191 } else {
192 regs.mode.write(|w| w.mode().timer());
193 }
169 194
170 // Make the counter's max value as high as possible. 195 // Make the counter's max value as high as possible.
171 // TODO: is there a reason someone would want to set this lower? 196 // TODO: is there a reason someone would want to set this lower?
@@ -225,6 +250,14 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
225 Task::from_reg(&T::regs().tasks_clear) 250 Task::from_reg(&T::regs().tasks_clear)
226 } 251 }
227 252
253 /// Returns the COUNT task, for use with PPI.
254 ///
255 /// When triggered, this task increments the timer's counter by 1.
256 /// Only works in counter mode.
257 pub fn task_count(&self) -> Task {
258 Task::from_reg(&T::regs().tasks_count)
259 }
260
228 /// Change the timer's frequency. 261 /// Change the timer's frequency.
229 /// 262 ///
230 /// This will stop the timer if it isn't already stopped, 263 /// This will stop the timer if it isn't already stopped,
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 48457744b..00afbd059 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -883,6 +883,7 @@ pub(crate) mod sealed {
883 pub trait Instance { 883 pub trait Instance {
884 fn regs() -> &'static pac::uarte0::RegisterBlock; 884 fn regs() -> &'static pac::uarte0::RegisterBlock;
885 fn state() -> &'static State; 885 fn state() -> &'static State;
886 fn buffered_state() -> &'static crate::buffered_uarte::State;
886 } 887 }
887} 888}
888 889
@@ -902,6 +903,10 @@ macro_rules! impl_uarte {
902 static STATE: crate::uarte::sealed::State = crate::uarte::sealed::State::new(); 903 static STATE: crate::uarte::sealed::State = crate::uarte::sealed::State::new();
903 &STATE 904 &STATE
904 } 905 }
906 fn buffered_state() -> &'static crate::buffered_uarte::State {
907 static STATE: crate::buffered_uarte::State = crate::buffered_uarte::State::new();
908 &STATE
909 }
905 } 910 }
906 impl crate::uarte::Instance for peripherals::$type { 911 impl crate::uarte::Instance for peripherals::$type {
907 type Interrupt = crate::interrupt::$irq; 912 type Interrupt = crate::interrupt::$irq;