aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/buffered_uarte.rs672
-rw-r--r--embassy-nrf/src/uarte.rs5
-rw-r--r--examples/nrf52840/src/bin/buffered_uart.rs12
3 files changed, 381 insertions, 308 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 112f084c1..79f9a1f78 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,120 @@
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> { 49pub(crate) use sealed::State;
58 _peri: PeripheralRef<'d, U>,
59 timer: Timer<'d, T>,
60 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
61 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
62
63 rx: RingBuffer<'d>,
64 rx_state: RxState,
65 rx_waker: WakerRegistration,
66 50
67 tx: RingBuffer<'d>, 51impl State {
68 tx_state: TxState, 52 pub(crate) const fn new() -> Self {
69 tx_waker: WakerRegistration, 53 Self {
54 tx_waker: AtomicWaker::new(),
55 tx_buf: RingBuffer::new(),
56 tx_count: AtomicUsize::new(0),
57
58 rx_waker: AtomicWaker::new(),
59 rx_buf: RingBuffer::new(),
60 rx_bufs: AtomicU8::new(0),
61 rx_ppi_ch: AtomicU8::new(0),
62 }
63 }
70} 64}
71 65
72/// Buffered UARTE driver. 66/// Buffered UARTE driver.
73pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { 67pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
74 inner: RefCell<PeripheralMutex<'d, StateInner<'d, U, T>>>, 68 _peri: PeripheralRef<'d, U>,
69 timer: Timer<'d, T>,
70 _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>,
71 _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>,
72 _ppi_group: PpiGroup<'d, AnyGroup>,
75} 73}
76 74
77impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} 75impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {}
78 76
79impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { 77impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
80 /// Create a new instance of a BufferedUarte. 78 /// Create a new BufferedUarte without hardware flow control.
81 /// 79 ///
82 /// See the [module documentation](crate::buffered_uarte) for more details about the intended use. 80 /// # Panics
83 /// 81 ///
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 82 /// Panics if `rx_buffer.len()` is odd.
85 /// can return early if there is no data to receive.
86 pub fn new( 83 pub fn new(
87 state: &'d mut State<'d, U, T>, 84 uarte: impl Peripheral<P = U> + 'd,
88 peri: impl Peripheral<P = U> + 'd, 85 timer: impl Peripheral<P = T> + 'd,
86 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
87 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
88 ppi_group: impl Peripheral<P = impl Group> + 'd,
89 irq: impl Peripheral<P = U::Interrupt> + 'd,
90 rxd: impl Peripheral<P = impl GpioPin> + 'd,
91 txd: impl Peripheral<P = impl GpioPin> + 'd,
92 config: Config,
93 rx_buffer: &'d mut [u8],
94 tx_buffer: &'d mut [u8],
95 ) -> Self {
96 into_ref!(rxd, txd, ppi_ch1, ppi_ch2, ppi_group);
97 Self::new_inner(
98 uarte,
99 timer,
100 ppi_ch1.map_into(),
101 ppi_ch2.map_into(),
102 ppi_group.map_into(),
103 irq,
104 rxd.map_into(),
105 txd.map_into(),
106 None,
107 None,
108 config,
109 rx_buffer,
110 tx_buffer,
111 )
112 }
113
114 /// Create a new BufferedUarte with hardware flow control (RTS/CTS)
115 ///
116 /// # Panics
117 ///
118 /// Panics if `rx_buffer.len()` is odd.
119 pub fn new_with_rtscts(
120 uarte: impl Peripheral<P = U> + 'd,
89 timer: impl Peripheral<P = T> + 'd, 121 timer: impl Peripheral<P = T> + 'd,
90 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 122 ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
91 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd, 123 ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
124 ppi_group: impl Peripheral<P = impl Group> + 'd,
92 irq: impl Peripheral<P = U::Interrupt> + 'd, 125 irq: impl Peripheral<P = U::Interrupt> + 'd,
93 rxd: impl Peripheral<P = impl GpioPin> + 'd, 126 rxd: impl Peripheral<P = impl GpioPin> + 'd,
94 txd: impl Peripheral<P = impl GpioPin> + 'd, 127 txd: impl Peripheral<P = impl GpioPin> + 'd,
@@ -98,11 +131,44 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
98 rx_buffer: &'d mut [u8], 131 rx_buffer: &'d mut [u8],
99 tx_buffer: &'d mut [u8], 132 tx_buffer: &'d mut [u8],
100 ) -> Self { 133 ) -> Self {
101 into_ref!(peri, ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); 134 into_ref!(rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group);
135 Self::new_inner(
136 uarte,
137 timer,
138 ppi_ch1.map_into(),
139 ppi_ch2.map_into(),
140 ppi_group.map_into(),
141 irq,
142 rxd.map_into(),
143 txd.map_into(),
144 Some(cts.map_into()),
145 Some(rts.map_into()),
146 config,
147 rx_buffer,
148 tx_buffer,
149 )
150 }
102 151
103 let r = U::regs(); 152 fn new_inner(
153 peri: impl Peripheral<P = U> + 'd,
154 timer: impl Peripheral<P = T> + 'd,
155 ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
156 ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
157 ppi_group: PeripheralRef<'d, AnyGroup>,
158 irq: impl Peripheral<P = U::Interrupt> + 'd,
159 rxd: PeripheralRef<'d, AnyPin>,
160 txd: PeripheralRef<'d, AnyPin>,
161 cts: Option<PeripheralRef<'d, AnyPin>>,
162 rts: Option<PeripheralRef<'d, AnyPin>>,
163 config: Config,
164 rx_buffer: &'d mut [u8],
165 tx_buffer: &'d mut [u8],
166 ) -> Self {
167 into_ref!(peri, timer, irq);
168
169 assert!(rx_buffer.len() % 2 == 0);
104 170
105 let mut timer = Timer::new(timer); 171 let r = U::regs();
106 172
107 rxd.conf().write(|w| w.input().connect().drive().h0h1()); 173 rxd.conf().write(|w| w.input().connect().drive().h0h1());
108 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); 174 r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@@ -111,92 +177,200 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
111 txd.conf().write(|w| w.dir().output().drive().h0h1()); 177 txd.conf().write(|w| w.dir().output().drive().h0h1());
112 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); 178 r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) });
113 179
114 cts.conf().write(|w| w.input().connect().drive().h0h1()); 180 if let Some(pin) = &cts {
181 pin.conf().write(|w| w.input().connect().drive().h0h1());
182 }
115 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); 183 r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) });
116 184
117 rts.set_high(); 185 if let Some(pin) = &rts {
118 rts.conf().write(|w| w.dir().output().drive().h0h1()); 186 pin.set_high();
187 pin.conf().write(|w| w.dir().output().drive().h0h1());
188 }
119 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); 189 r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) });
120 190
121 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 191 // Initialize state
122 r.config.write(|w| w.parity().variant(config.parity)); 192 let s = U::buffered_state();
193 s.tx_count.store(0, Ordering::Relaxed);
194 s.rx_bufs.store(0, Ordering::Relaxed);
195 let len = tx_buffer.len();
196 unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
197 let len = rx_buffer.len();
198 unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
123 199
124 // Configure 200 // Configure
125 r.config.write(|w| { 201 r.config.write(|w| {
126 w.hwfc().bit(true); 202 w.hwfc().bit(false);
127 w.parity().variant(config.parity); 203 w.parity().variant(config.parity);
128 w 204 w
129 }); 205 });
130 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 206 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
131 207
132 // Enable interrupts 208 // clear errors
133 r.intenset.write(|w| w.endrx().set().endtx().set()); 209 let errors = r.errorsrc.read().bits();
210 r.errorsrc.write(|w| unsafe { w.bits(errors) });
134 211
135 // Disable the irq, let the Registration enable it when everything is set up. 212 r.events_rxstarted.reset();
136 irq.disable(); 213 r.events_txstarted.reset();
137 irq.pend(); 214 r.events_error.reset();
215 r.events_endrx.reset();
216 r.events_endtx.reset();
217
218 // Enable interrupts
219 r.intenclr.write(|w| unsafe { w.bits(!0) });
220 r.intenset.write(|w| {
221 w.endtx().set();
222 w.rxstarted().set();
223 w.error().set();
224 w
225 });
138 226
139 // Enable UARTE instance 227 // Enable UARTE instance
140 apply_workaround_for_enable_anomaly(&r); 228 apply_workaround_for_enable_anomaly(&r);
141 r.enable.write(|w| w.enable().enabled()); 229 r.enable.write(|w| w.enable().enabled());
142 230
143 // BAUDRATE register values are `baudrate * 2^32 / 16000000` 231 // Configure byte counter.
144 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values 232 let mut timer = Timer::new_counter(timer);
145 // 233 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 234 timer.cc(1).short_compare_clear();
147 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit) 235 timer.clear();
148 // This gives us the amount of 16M ticks for 20 bits. 236 timer.start();
149 let timeout = 0x8000_0000 / (config.baudrate as u32 / 40);
150
151 timer.set_frequency(Frequency::F16MHz);
152 timer.cc(0).write(timeout);
153 timer.cc(0).short_compare_clear();
154 timer.cc(0).short_compare_stop();
155 237
156 let mut ppi_ch1 = Ppi::new_one_to_two( 238 let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(&r.events_rxdrdy), timer.task_count());
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(); 239 ppi_ch1.enable();
163 240
164 let mut ppi_ch2 = Ppi::new_one_to_one( 241 s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed);
165 ppi_ch2.map_into(), 242 let mut ppi_group = PpiGroup::new(ppi_group);
166 timer.cc(0).event_compare(), 243 let mut ppi_ch2 = Ppi::new_one_to_two(
167 Task::from_reg(&r.tasks_stoprx), 244 ppi_ch2,
245 Event::from_reg(&r.events_endrx),
246 Task::from_reg(&r.tasks_startrx),
247 ppi_group.task_disable_all(),
168 ); 248 );
169 ppi_ch2.enable(); 249 ppi_ch2.disable();
250 ppi_group.add_channel(&ppi_ch2);
251
252 irq.disable();
253 irq.set_handler(Self::on_interrupt);
254 irq.pend();
255 irq.enable();
170 256
171 Self { 257 Self {
172 inner: RefCell::new(PeripheralMutex::new(irq, &mut state.0, move || StateInner { 258 _peri: peri,
173 _peri: peri, 259 timer,
174 timer, 260 _ppi_ch1: ppi_ch1,
175 _ppi_ch1: ppi_ch1, 261 _ppi_ch2: ppi_ch2,
176 _ppi_ch2: ppi_ch2, 262 _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 } 263 }
187 } 264 }
188 265
189 /// Adjust the baud rate to the provided value. 266 fn pend_irq() {
190 pub fn set_baudrate(&mut self, baudrate: Baudrate) { 267 unsafe { <U::Interrupt as Interrupt>::steal() }.pend()
191 self.inner.borrow_mut().with(|state| { 268 }
192 let r = U::regs();
193 269
194 let timeout = 0x8000_0000 / (baudrate as u32 / 40); 270 fn on_interrupt(_: *mut ()) {
195 state.timer.cc(0).write(timeout); 271 //trace!("irq: start");
196 state.timer.clear(); 272 let r = U::regs();
273 let s = U::buffered_state();
197 274
198 r.baudrate.write(|w| w.baudrate().variant(baudrate)); 275 let buf_len = s.rx_buf.len();
199 }); 276 let half_len = buf_len / 2;
277 let mut tx = unsafe { s.tx_buf.reader() };
278 let mut rx = unsafe { s.rx_buf.writer() };
279
280 if r.events_error.read().bits() != 0 {
281 r.events_error.reset();
282 let errs = r.errorsrc.read();
283 r.errorsrc.write(|w| unsafe { w.bits(errs.bits()) });
284
285 if errs.overrun().bit() {
286 panic!("BufferedUarte overrun");
287 }
288 }
289
290 // Received some bytes, wake task.
291 if r.inten.read().rxdrdy().bit_is_set() && r.events_rxdrdy.read().events_rxdrdy().bit_is_set() {
292 r.intenclr.write(|w| w.rxdrdy().clear());
293 r.events_rxdrdy.reset();
294 s.rx_waker.wake();
295 }
296
297 // If not RXing, start.
298 if s.rx_bufs.load(Ordering::Relaxed) == 0 {
299 let (ptr, len) = rx.push_buf();
300 if len >= half_len {
301 //trace!(" irq_rx: starting {:?}", half_len);
302 s.rx_bufs.store(1, Ordering::Relaxed);
303
304 // Set up the DMA read
305 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
306 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
307
308 // Start UARTE Receive transaction
309 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
310 rx.push_done(half_len);
311 r.intenset.write(|w| w.rxstarted().set());
312 }
313 }
314
315 if r.events_rxstarted.read().bits() != 0 {
316 //trace!(" irq_rx: rxstarted");
317 let (ptr, len) = rx.push_buf();
318 if len >= half_len {
319 //trace!(" irq_rx: starting second {:?}", half_len);
320
321 // Set up the DMA read
322 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
323 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(half_len as _) });
324
325 let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
326
327 ppi::regs().chenset.write(|w| unsafe { w.bits(1 << chn) });
328
329 rx.push_done(half_len);
330
331 r.events_rxstarted.reset();
332 } else {
333 //trace!(" irq_rx: rxstarted no buf");
334 r.intenclr.write(|w| w.rxstarted().clear());
335 }
336 }
337
338 // =============================
339
340 // TX end
341 if r.events_endtx.read().bits() != 0 {
342 r.events_endtx.reset();
343
344 let n = s.tx_count.load(Ordering::Relaxed);
345 //trace!(" irq_tx: endtx {:?}", n);
346 tx.pop_done(n);
347 s.tx_waker.wake();
348 s.tx_count.store(0, Ordering::Relaxed);
349 }
350
351 // If not TXing, start.
352 if s.tx_count.load(Ordering::Relaxed) == 0 {
353 let (ptr, len) = tx.pop_buf();
354 if len != 0 {
355 //trace!(" irq_tx: starting {:?}", len);
356 s.tx_count.store(len, Ordering::Relaxed);
357
358 // Set up the DMA write
359 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
360 r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
361
362 // Start UARTE Transmit transaction
363 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
364 }
365 }
366
367 //trace!("irq: end");
368 }
369
370 /// Adjust the baud rate to the provided value.
371 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
372 let r = U::regs();
373 r.baudrate.write(|w| w.baudrate().variant(baudrate));
200 } 374 }
201 375
202 /// Split the UART in reader and writer parts. 376 /// Split the UART in reader and writer parts.
@@ -206,120 +380,117 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
206 (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self }) 380 (BufferedUarteRx { inner: self }, BufferedUarteTx { inner: self })
207 } 381 }
208 382
209 async fn inner_read<'a>(&'a self, buf: &'a mut [u8]) -> Result<usize, core::convert::Infallible> { 383 async fn inner_read(&self, buf: &mut [u8]) -> Result<usize, core::convert::Infallible> {
210 poll_fn(move |cx| { 384 let data = self.inner_fill_buf().await?;
211 let mut do_pend = false; 385 let n = data.len().min(buf.len());
212 let mut inner = self.inner.borrow_mut(); 386 buf[..n].copy_from_slice(&data[..n]);
213 let res = inner.with(|state| { 387 self.inner_consume(n);
214 compiler_fence(Ordering::SeqCst); 388 Ok(n)
215 trace!("poll_read");
216
217 // We have data ready in buffer? Return it.
218 let data = state.rx.pop_buf();
219 if !data.is_empty() {
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 }
235
236 res
237 })
238 .await
239 } 389 }
240 390
241 async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, core::convert::Infallible> { 391 async fn inner_write<'a>(&'a self, buf: &'a [u8]) -> Result<usize, core::convert::Infallible> {
242 poll_fn(move |cx| { 392 poll_fn(move |cx| {
243 let mut inner = self.inner.borrow_mut(); 393 //trace!("poll_write: {:?}", buf.len());
244 let res = inner.with(|state| { 394 let s = U::buffered_state();
245 trace!("poll_write: {:?}", buf.len()); 395 let mut tx = unsafe { s.tx_buf.writer() };
246 396
247 let tx_buf = state.tx.push_buf(); 397 let tx_buf = tx.push_slice();
248 if tx_buf.is_empty() { 398 if tx_buf.is_empty() {
249 trace!("poll_write: pending"); 399 //trace!("poll_write: pending");
250 state.tx_waker.register(cx.waker()); 400 s.tx_waker.register(cx.waker());
251 return Poll::Pending; 401 return Poll::Pending;
252 } 402 }
253
254 let n = min(tx_buf.len(), buf.len());
255 tx_buf[..n].copy_from_slice(&buf[..n]);
256 state.tx.push(n);
257
258 trace!("poll_write: queued {:?}", n);
259 403
260 compiler_fence(Ordering::SeqCst); 404 let n = min(tx_buf.len(), buf.len());
405 tx_buf[..n].copy_from_slice(&buf[..n]);
406 tx.push_done(n);
261 407
262 Poll::Ready(Ok(n)) 408 //trace!("poll_write: queued {:?}", n);
263 });
264 409
265 inner.pend(); 410 compiler_fence(Ordering::SeqCst);
411 Self::pend_irq();
266 412
267 res 413 Poll::Ready(Ok(n))
268 }) 414 })
269 .await 415 .await
270 } 416 }
271 417
272 async fn inner_flush<'a>(&'a self) -> Result<(), core::convert::Infallible> { 418 async fn inner_flush<'a>(&'a self) -> Result<(), core::convert::Infallible> {
273 poll_fn(move |cx| { 419 poll_fn(move |cx| {
274 self.inner.borrow_mut().with(|state| { 420 //trace!("poll_flush");
275 trace!("poll_flush"); 421 let s = U::buffered_state();
276 422 if !s.tx_buf.is_empty() {
277 if !state.tx.is_empty() { 423 //trace!("poll_flush: pending");
278 trace!("poll_flush: pending"); 424 s.tx_waker.register(cx.waker());
279 state.tx_waker.register(cx.waker()); 425 return Poll::Pending;
280 return Poll::Pending; 426 }
281 }
282 427
283 Poll::Ready(Ok(())) 428 Poll::Ready(Ok(()))
284 })
285 }) 429 })
286 .await 430 .await
287 } 431 }
288 432
289 async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], core::convert::Infallible> { 433 async fn inner_fill_buf<'a>(&'a self) -> Result<&'a [u8], core::convert::Infallible> {
290 poll_fn(move |cx| { 434 poll_fn(move |cx| {
291 self.inner.borrow_mut().with(|state| { 435 compiler_fence(Ordering::SeqCst);
292 compiler_fence(Ordering::SeqCst); 436 //trace!("poll_read");
293 trace!("fill_buf"); 437
294 438 let r = U::regs();
295 // We have data ready in buffer? Return it. 439 let s = U::buffered_state();
296 let buf = state.rx.pop_buf(); 440
297 if !buf.is_empty() { 441 // Read the RXDRDY counter.
298 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len()); 442 T::regs().tasks_capture[0].write(|w| unsafe { w.bits(1) });
299 let buf: &[u8] = buf; 443 let mut end = T::regs().cc[0].read().bits() as usize;
300 // Safety: buffer lives as long as uart 444 //trace!(" rxdrdy count = {:?}", end);
301 let buf: &[u8] = unsafe { core::mem::transmute(buf) }; 445
302 return Poll::Ready(Ok(buf)); 446 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
303 } 447 // However, it's unclear if that's instant, or there's a small window where you can
304 448 // still read `len()*2`.
305 trace!(" empty"); 449 // This could happen if in one clock cycle the counter is updated, and in the next the
306 state.rx_waker.register(cx.waker()); 450 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
307 Poll::<Result<&[u8], core::convert::Infallible>>::Pending 451 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
308 }) 452 // clock cycle of the PCLK16M." :shrug:
453 // So, we wrap the counter ourselves, just in case.
454 if end > s.rx_buf.len() * 2 {
455 end = 0
456 }
457
458 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()`
459 let mut start = s.rx_buf.start.load(Ordering::Relaxed);
460 let len = s.rx_buf.len();
461 if start == end {
462 //trace!(" empty");
463 s.rx_waker.register(cx.waker());
464 r.intenset.write(|w| w.rxdrdy().set_bit());
465 return Poll::Pending;
466 }
467
468 if start >= len {
469 start -= len
470 }
471 if end >= len {
472 end -= len
473 }
474
475 let n = if end > start { end - start } else { len - start };
476 assert!(n != 0);
477 //trace!(" uarte ringbuf: pop_buf {:?}..{:?}", start, start + n);
478
479 let buf = s.rx_buf.buf.load(Ordering::Relaxed);
480 Poll::Ready(Ok(unsafe { slice::from_raw_parts(buf.add(start), n) }))
309 }) 481 })
310 .await 482 .await
311 } 483 }
312 484
313 fn inner_consume(&self, amt: usize) { 485 fn inner_consume(&self, amt: usize) {
314 let mut inner = self.inner.borrow_mut(); 486 if amt == 0 {
315 let signal = inner.with(|state| { 487 return;
316 let full = state.rx.is_full();
317 state.rx.pop(amt);
318 full
319 });
320 if signal {
321 inner.pend();
322 } 488 }
489
490 let s = U::buffered_state();
491 let mut rx = unsafe { s.rx_buf.reader() };
492 rx.pop_done(amt);
493 U::regs().intenset.write(|w| w.rxstarted().set());
323 } 494 }
324} 495}
325 496
@@ -397,7 +568,7 @@ impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write
397 } 568 }
398} 569}
399 570
400impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> { 571impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarte<'a, U, T> {
401 fn drop(&mut self) { 572 fn drop(&mut self) {
402 let r = U::regs(); 573 let r = U::regs();
403 574
@@ -418,108 +589,11 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> {
418 gpio::deconfigure_pin(r.psel.txd.read().bits()); 589 gpio::deconfigure_pin(r.psel.txd.read().bits());
419 gpio::deconfigure_pin(r.psel.rts.read().bits()); 590 gpio::deconfigure_pin(r.psel.rts.read().bits());
420 gpio::deconfigure_pin(r.psel.cts.read().bits()); 591 gpio::deconfigure_pin(r.psel.cts.read().bits());
421 }
422}
423
424impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, U, T> {
425 type Interrupt = U::Interrupt;
426 fn on_interrupt(&mut self) {
427 trace!("irq: start");
428 let r = U::regs();
429 592
430 loop { 593 let s = U::buffered_state();
431 match self.rx_state { 594 unsafe {
432 RxState::Idle => { 595 s.rx_buf.deinit();
433 trace!(" irq_rx: in state idle"); 596 s.tx_buf.deinit();
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 } 597 }
523 trace!("irq: end");
524 } 598 }
525} 599}
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;
diff --git a/examples/nrf52840/src/bin/buffered_uart.rs b/examples/nrf52840/src/bin/buffered_uart.rs
index ea566f4b2..584e6b2bc 100644
--- a/examples/nrf52840/src/bin/buffered_uart.rs
+++ b/examples/nrf52840/src/bin/buffered_uart.rs
@@ -4,10 +4,9 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::buffered_uarte::{BufferedUarte, State}; 7use embassy_nrf::buffered_uarte::BufferedUarte;
8use embassy_nrf::{interrupt, uarte}; 8use embassy_nrf::{interrupt, uarte};
9use embedded_io::asynch::{BufRead, Write}; 9use embedded_io::asynch::{BufRead, Write};
10use futures::pin_mut;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
13#[embassy_executor::main] 12#[embassy_executor::main]
@@ -21,24 +20,19 @@ async fn main(_spawner: Spawner) {
21 let mut rx_buffer = [0u8; 4096]; 20 let mut rx_buffer = [0u8; 4096];
22 21
23 let irq = interrupt::take!(UARTE0_UART0); 22 let irq = interrupt::take!(UARTE0_UART0);
24 let mut state = State::new(); 23 let mut u = BufferedUarte::new(
25 // Please note - important to have hardware flow control (https://github.com/embassy-rs/embassy/issues/536)
26 let u = BufferedUarte::new(
27 &mut state,
28 p.UARTE0, 24 p.UARTE0,
29 p.TIMER0, 25 p.TIMER0,
30 p.PPI_CH0, 26 p.PPI_CH0,
31 p.PPI_CH1, 27 p.PPI_CH1,
28 p.PPI_GROUP0,
32 irq, 29 irq,
33 p.P0_08, 30 p.P0_08,
34 p.P0_06, 31 p.P0_06,
35 p.P0_07,
36 p.P0_05,
37 config, 32 config,
38 &mut rx_buffer, 33 &mut rx_buffer,
39 &mut tx_buffer, 34 &mut tx_buffer,
40 ); 35 );
41 pin_mut!(u);
42 36
43 info!("uarte initialized!"); 37 info!("uarte initialized!");
44 38