aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-01 15:35:39 +0000
committerGitHub <[email protected]>2023-05-01 15:35:39 +0000
commit05c36e05f9f6b1a0a36982239b2e7c697f0d3734 (patch)
tree68852621ce845a7e5a6e15ee07bbcb54b49ef9a8
parentac0ea406f91a5b630811accd0c97a622a020c700 (diff)
parentb58b9ff390fb885f0cca2ad15fc89d537f3a9818 (diff)
Merge #1414
1414: rp: report errors from buffered and dma uart receives r=Dirbaio a=pennae neither of these reported errors so far, which is not ideal. add error reporting to both of them that matches the blocking error reporting as closely as is feasible, even allowing partial receives from buffered uarts before errors are reported where they would have been by the blocking code. dma transfers don't do this, if an errors applies to any byte in a transfer the entire transfer is nuked (though we probably could report how many bytes have been transferred). Co-authored-by: pennae <[email protected]>
-rw-r--r--embassy-rp/src/uart/buffered.rs235
-rw-r--r--embassy-rp/src/uart/mod.rs266
-rw-r--r--examples/rp/src/bin/uart_unidir.rs9
-rw-r--r--tests/rp/src/bin/uart.rs159
-rw-r--r--tests/rp/src/bin/uart_buffered.rs249
-rw-r--r--tests/rp/src/bin/uart_dma.rs238
6 files changed, 1005 insertions, 151 deletions
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index cb0461930..59fec8f1b 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -2,11 +2,14 @@ use core::future::{poll_fn, Future};
2use core::slice; 2use core::slice;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicU8, Ordering};
5use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
6use embassy_hal_common::atomic_ring_buffer::RingBuffer; 7use embassy_hal_common::atomic_ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::{Duration, Timer};
8 10
9use super::*; 11use super::*;
12use crate::clocks::clk_peri_freq;
10use crate::RegExt; 13use crate::RegExt;
11 14
12pub struct State { 15pub struct State {
@@ -14,8 +17,15 @@ pub struct State {
14 tx_buf: RingBuffer, 17 tx_buf: RingBuffer,
15 rx_waker: AtomicWaker, 18 rx_waker: AtomicWaker,
16 rx_buf: RingBuffer, 19 rx_buf: RingBuffer,
20 rx_error: AtomicU8,
17} 21}
18 22
23// these must match bits 8..11 in UARTDR
24const RXE_OVERRUN: u8 = 8;
25const RXE_BREAK: u8 = 4;
26const RXE_PARITY: u8 = 2;
27const RXE_FRAMING: u8 = 1;
28
19impl State { 29impl State {
20 pub const fn new() -> Self { 30 pub const fn new() -> Self {
21 Self { 31 Self {
@@ -23,6 +33,7 @@ impl State {
23 tx_buf: RingBuffer::new(), 33 tx_buf: RingBuffer::new(),
24 rx_waker: AtomicWaker::new(), 34 rx_waker: AtomicWaker::new(),
25 tx_waker: AtomicWaker::new(), 35 tx_waker: AtomicWaker::new(),
36 rx_error: AtomicU8::new(0),
26 } 37 }
27 } 38 }
28} 39}
@@ -45,7 +56,7 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
45 tx_buffer: &'d mut [u8], 56 tx_buffer: &'d mut [u8],
46 rx_buffer: &'d mut [u8], 57 rx_buffer: &'d mut [u8],
47) { 58) {
48 let state = T::state(); 59 let state = T::buffered_state();
49 let len = tx_buffer.len(); 60 let len = tx_buffer.len();
50 unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; 61 unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
51 let len = rx_buffer.len(); 62 let len = rx_buffer.len();
@@ -63,7 +74,7 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
63 // to pend the ISR when we want data transmission to start. 74 // to pend the ISR when we want data transmission to start.
64 let regs = T::regs(); 75 let regs = T::regs();
65 unsafe { 76 unsafe {
66 regs.uartimsc().write_set(|w| { 77 regs.uartimsc().write(|w| {
67 w.set_rxim(true); 78 w.set_rxim(true);
68 w.set_rtim(true); 79 w.set_rtim(true);
69 w.set_txim(true); 80 w.set_txim(true);
@@ -136,6 +147,14 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
136 self.rx.blocking_read(buffer) 147 self.rx.blocking_read(buffer)
137 } 148 }
138 149
150 pub fn busy(&self) -> bool {
151 self.tx.busy()
152 }
153
154 pub async fn send_break(&mut self, bits: u32) {
155 self.tx.send_break(bits).await
156 }
157
139 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) { 158 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
140 (self.rx, self.tx) 159 (self.rx, self.tx)
141 } 160 }
@@ -173,90 +192,113 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
173 Self { phantom: PhantomData } 192 Self { phantom: PhantomData }
174 } 193 }
175 194
176 fn read<'a>(buf: &'a mut [u8]) -> impl Future<Output = Result<usize, Error>> + 'a { 195 fn read<'a>(buf: &'a mut [u8]) -> impl Future<Output = Result<usize, Error>> + 'a
196 where
197 T: 'd,
198 {
177 poll_fn(move |cx| { 199 poll_fn(move |cx| {
178 if buf.is_empty() { 200 if let Poll::Ready(r) = Self::try_read(buf) {
179 return Poll::Ready(Ok(0)); 201 return Poll::Ready(r);
180 }
181
182 let state = T::state();
183 let mut rx_reader = unsafe { state.rx_buf.reader() };
184 let n = rx_reader.pop(|data| {
185 let n = data.len().min(buf.len());
186 buf[..n].copy_from_slice(&data[..n]);
187 n
188 });
189 if n == 0 {
190 state.rx_waker.register(cx.waker());
191 return Poll::Pending;
192 }
193
194 // (Re-)Enable the interrupt to receive more data in case it was
195 // disabled because the buffer was full.
196 let regs = T::regs();
197 unsafe {
198 regs.uartimsc().write_set(|w| {
199 w.set_rxim(true);
200 w.set_rtim(true);
201 });
202 } 202 }
203 203 T::buffered_state().rx_waker.register(cx.waker());
204 Poll::Ready(Ok(n)) 204 Poll::Pending
205 }) 205 })
206 } 206 }
207 207
208 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 208 fn get_rx_error() -> Option<Error> {
209 let errs = T::buffered_state().rx_error.swap(0, Ordering::Relaxed);
210 if errs & RXE_OVERRUN != 0 {
211 Some(Error::Overrun)
212 } else if errs & RXE_BREAK != 0 {
213 Some(Error::Break)
214 } else if errs & RXE_PARITY != 0 {
215 Some(Error::Parity)
216 } else if errs & RXE_FRAMING != 0 {
217 Some(Error::Framing)
218 } else {
219 None
220 }
221 }
222
223 fn try_read(buf: &mut [u8]) -> Poll<Result<usize, Error>>
224 where
225 T: 'd,
226 {
209 if buf.is_empty() { 227 if buf.is_empty() {
210 return Ok(0); 228 return Poll::Ready(Ok(0));
211 } 229 }
212 230
213 loop { 231 let state = T::buffered_state();
214 let state = T::state(); 232 let mut rx_reader = unsafe { state.rx_buf.reader() };
215 let mut rx_reader = unsafe { state.rx_buf.reader() }; 233 let n = rx_reader.pop(|data| {
216 let n = rx_reader.pop(|data| { 234 let n = data.len().min(buf.len());
217 let n = data.len().min(buf.len()); 235 buf[..n].copy_from_slice(&data[..n]);
218 buf[..n].copy_from_slice(&data[..n]); 236 n
219 n 237 });
238
239 let result = if n == 0 {
240 match Self::get_rx_error() {
241 None => return Poll::Pending,
242 Some(e) => Err(e),
243 }
244 } else {
245 Ok(n)
246 };
247
248 // (Re-)Enable the interrupt to receive more data in case it was
249 // disabled because the buffer was full or errors were detected.
250 let regs = T::regs();
251 unsafe {
252 regs.uartimsc().write_set(|w| {
253 w.set_rxim(true);
254 w.set_rtim(true);
220 }); 255 });
256 }
221 257
222 if n > 0 { 258 Poll::Ready(result)
223 // (Re-)Enable the interrupt to receive more data in case it was 259 }
224 // disabled because the buffer was full.
225 let regs = T::regs();
226 unsafe {
227 regs.uartimsc().write_set(|w| {
228 w.set_rxim(true);
229 w.set_rtim(true);
230 });
231 }
232 260
233 return Ok(n); 261 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
262 loop {
263 match Self::try_read(buf) {
264 Poll::Ready(res) => return res,
265 Poll::Pending => continue,
234 } 266 }
235 } 267 }
236 } 268 }
237 269
238 fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>> { 270 fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>>
271 where
272 T: 'd,
273 {
239 poll_fn(move |cx| { 274 poll_fn(move |cx| {
240 let state = T::state(); 275 let state = T::buffered_state();
241 let mut rx_reader = unsafe { state.rx_buf.reader() }; 276 let mut rx_reader = unsafe { state.rx_buf.reader() };
242 let (p, n) = rx_reader.pop_buf(); 277 let (p, n) = rx_reader.pop_buf();
243 if n == 0 { 278 let result = if n == 0 {
244 state.rx_waker.register(cx.waker()); 279 match Self::get_rx_error() {
245 return Poll::Pending; 280 None => {
246 } 281 state.rx_waker.register(cx.waker());
282 return Poll::Pending;
283 }
284 Some(e) => Err(e),
285 }
286 } else {
287 let buf = unsafe { slice::from_raw_parts(p, n) };
288 Ok(buf)
289 };
247 290
248 let buf = unsafe { slice::from_raw_parts(p, n) }; 291 Poll::Ready(result)
249 Poll::Ready(Ok(buf))
250 }) 292 })
251 } 293 }
252 294
253 fn consume(amt: usize) { 295 fn consume(amt: usize) {
254 let state = T::state(); 296 let state = T::buffered_state();
255 let mut rx_reader = unsafe { state.rx_buf.reader() }; 297 let mut rx_reader = unsafe { state.rx_buf.reader() };
256 rx_reader.pop_done(amt); 298 rx_reader.pop_done(amt);
257 299
258 // (Re-)Enable the interrupt to receive more data in case it was 300 // (Re-)Enable the interrupt to receive more data in case it was
259 // disabled because the buffer was full. 301 // disabled because the buffer was full or errors were detected.
260 let regs = T::regs(); 302 let regs = T::regs();
261 unsafe { 303 unsafe {
262 regs.uartimsc().write_set(|w| { 304 regs.uartimsc().write_set(|w| {
@@ -305,7 +347,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
305 return Poll::Ready(Ok(0)); 347 return Poll::Ready(Ok(0));
306 } 348 }
307 349
308 let state = T::state(); 350 let state = T::buffered_state();
309 let mut tx_writer = unsafe { state.tx_buf.writer() }; 351 let mut tx_writer = unsafe { state.tx_buf.writer() };
310 let n = tx_writer.push(|data| { 352 let n = tx_writer.push(|data| {
311 let n = data.len().min(buf.len()); 353 let n = data.len().min(buf.len());
@@ -328,7 +370,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
328 370
329 fn flush() -> impl Future<Output = Result<(), Error>> { 371 fn flush() -> impl Future<Output = Result<(), Error>> {
330 poll_fn(move |cx| { 372 poll_fn(move |cx| {
331 let state = T::state(); 373 let state = T::buffered_state();
332 if !state.tx_buf.is_empty() { 374 if !state.tx_buf.is_empty() {
333 state.tx_waker.register(cx.waker()); 375 state.tx_waker.register(cx.waker());
334 return Poll::Pending; 376 return Poll::Pending;
@@ -344,7 +386,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
344 } 386 }
345 387
346 loop { 388 loop {
347 let state = T::state(); 389 let state = T::buffered_state();
348 let mut tx_writer = unsafe { state.tx_buf.writer() }; 390 let mut tx_writer = unsafe { state.tx_buf.writer() };
349 let n = tx_writer.push(|data| { 391 let n = tx_writer.push(|data| {
350 let n = data.len().min(buf.len()); 392 let n = data.len().min(buf.len());
@@ -365,17 +407,54 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
365 407
366 pub fn blocking_flush(&mut self) -> Result<(), Error> { 408 pub fn blocking_flush(&mut self) -> Result<(), Error> {
367 loop { 409 loop {
368 let state = T::state(); 410 let state = T::buffered_state();
369 if state.tx_buf.is_empty() { 411 if state.tx_buf.is_empty() {
370 return Ok(()); 412 return Ok(());
371 } 413 }
372 } 414 }
373 } 415 }
416
417 pub fn busy(&self) -> bool {
418 unsafe { T::regs().uartfr().read().busy() }
419 }
420
421 /// Assert a break condition after waiting for the transmit buffers to empty,
422 /// for the specified number of bit times. This condition must be asserted
423 /// for at least two frame times to be effective, `bits` will adjusted
424 /// according to frame size, parity, and stop bit settings to ensure this.
425 ///
426 /// This method may block for a long amount of time since it has to wait
427 /// for the transmit fifo to empty, which may take a while on slow links.
428 pub async fn send_break(&mut self, bits: u32) {
429 let regs = T::regs();
430 let bits = bits.max(unsafe {
431 let lcr = regs.uartlcr_h().read();
432 let width = lcr.wlen() as u32 + 5;
433 let parity = lcr.pen() as u32;
434 let stops = 1 + lcr.stp2() as u32;
435 2 * (1 + width + parity + stops)
436 });
437 let divx64 = unsafe {
438 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32
439 } as u64;
440 let div_clk = clk_peri_freq() as u64 * 64;
441 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
442
443 Self::flush().await.unwrap();
444 while self.busy() {}
445 unsafe {
446 regs.uartlcr_h().write_set(|w| w.set_brk(true));
447 }
448 Timer::after(Duration::from_micros(wait_usecs)).await;
449 unsafe {
450 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
451 }
452 }
374} 453}
375 454
376impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { 455impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
377 fn drop(&mut self) { 456 fn drop(&mut self) {
378 let state = T::state(); 457 let state = T::buffered_state();
379 unsafe { 458 unsafe {
380 state.rx_buf.deinit(); 459 state.rx_buf.deinit();
381 460
@@ -390,7 +469,7 @@ impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
390 469
391impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> { 470impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
392 fn drop(&mut self) { 471 fn drop(&mut self) {
393 let state = T::state(); 472 let state = T::buffered_state();
394 unsafe { 473 unsafe {
395 state.tx_buf.deinit(); 474 state.tx_buf.deinit();
396 475
@@ -405,7 +484,7 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
405 484
406pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) { 485pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
407 let r = T::regs(); 486 let r = T::regs();
408 let s = T::state(); 487 let s = T::buffered_state();
409 488
410 unsafe { 489 unsafe {
411 // Clear TX and error interrupt flags 490 // Clear TX and error interrupt flags
@@ -439,19 +518,37 @@ pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
439 let mut rx_writer = s.rx_buf.writer(); 518 let mut rx_writer = s.rx_buf.writer();
440 let rx_buf = rx_writer.push_slice(); 519 let rx_buf = rx_writer.push_slice();
441 let mut n_read = 0; 520 let mut n_read = 0;
521 let mut error = false;
442 for rx_byte in rx_buf { 522 for rx_byte in rx_buf {
443 if r.uartfr().read().rxfe() { 523 if r.uartfr().read().rxfe() {
444 break; 524 break;
445 } 525 }
446 *rx_byte = r.uartdr().read().data(); 526 let dr = r.uartdr().read();
527 if (dr.0 >> 8) != 0 {
528 s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
529 error = true;
530 // only fill the buffer with valid characters. the current character is fine
531 // if the error is an overrun, but if we add it to the buffer we'll report
532 // the overrun one character too late. drop it instead and pretend we were
533 // a bit slower at draining the rx fifo than we actually were.
534 // this is consistent with blocking uart error reporting.
535 break;
536 }
537 *rx_byte = dr.data();
447 n_read += 1; 538 n_read += 1;
448 } 539 }
449 if n_read > 0 { 540 if n_read > 0 {
450 rx_writer.push_done(n_read); 541 rx_writer.push_done(n_read);
451 s.rx_waker.wake(); 542 s.rx_waker.wake();
543 } else if error {
544 s.rx_waker.wake();
452 } 545 }
453 // Disable any further RX interrupts when the buffer becomes full. 546 // Disable any further RX interrupts when the buffer becomes full or
454 if s.rx_buf.is_full() { 547 // errors have occured. this lets us buffer additional errors in the
548 // fifo without needing more error storage locations, and most applications
549 // will want to do a full reset of their uart state anyway once an error
550 // has happened.
551 if s.rx_buf.is_full() || error {
455 r.uartimsc().write_clear(|w| { 552 r.uartimsc().write_clear(|w| {
456 w.set_rxim(true); 553 w.set_rxim(true);
457 w.set_rtim(true); 554 w.set_rtim(true);
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index dedc390f0..ebe32cc66 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -1,12 +1,21 @@
1use core::future::poll_fn;
1use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::task::Poll;
2 4
5use atomic_polyfill::{AtomicU16, Ordering};
6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
7use embassy_futures::select::{select, Either};
3use embassy_hal_common::{into_ref, PeripheralRef}; 8use embassy_hal_common::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker;
10use embassy_time::{Duration, Timer};
11use pac::uart::regs::Uartris;
4 12
13use crate::clocks::clk_peri_freq;
5use crate::dma::{AnyChannel, Channel}; 14use crate::dma::{AnyChannel, Channel};
6use crate::gpio::sealed::Pin; 15use crate::gpio::sealed::Pin;
7use crate::gpio::AnyPin; 16use crate::gpio::AnyPin;
8use crate::pac::io::vals::{Inover, Outover}; 17use crate::pac::io::vals::{Inover, Outover};
9use crate::{pac, peripherals, Peripheral}; 18use crate::{pac, peripherals, Peripheral, RegExt};
10 19
11#[cfg(feature = "nightly")] 20#[cfg(feature = "nightly")]
12mod buffered; 21mod buffered;
@@ -95,6 +104,11 @@ pub enum Error {
95 Framing, 104 Framing,
96} 105}
97 106
107pub struct DmaState {
108 rx_err_waker: AtomicWaker,
109 rx_errs: AtomicU16,
110}
111
98pub struct Uart<'d, T: Instance, M: Mode> { 112pub struct Uart<'d, T: Instance, M: Mode> {
99 tx: UartTx<'d, T, M>, 113 tx: UartTx<'d, T, M>,
100 rx: UartRx<'d, T, M>, 114 rx: UartRx<'d, T, M>,
@@ -146,6 +160,43 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
146 unsafe { while !r.uartfr().read().txfe() {} } 160 unsafe { while !r.uartfr().read().txfe() {} }
147 Ok(()) 161 Ok(())
148 } 162 }
163
164 pub fn busy(&self) -> bool {
165 unsafe { T::regs().uartfr().read().busy() }
166 }
167
168 /// Assert a break condition after waiting for the transmit buffers to empty,
169 /// for the specified number of bit times. This condition must be asserted
170 /// for at least two frame times to be effective, `bits` will adjusted
171 /// according to frame size, parity, and stop bit settings to ensure this.
172 ///
173 /// This method may block for a long amount of time since it has to wait
174 /// for the transmit fifo to empty, which may take a while on slow links.
175 pub async fn send_break(&mut self, bits: u32) {
176 let regs = T::regs();
177 let bits = bits.max(unsafe {
178 let lcr = regs.uartlcr_h().read();
179 let width = lcr.wlen() as u32 + 5;
180 let parity = lcr.pen() as u32;
181 let stops = 1 + lcr.stp2() as u32;
182 2 * (1 + width + parity + stops)
183 });
184 let divx64 = unsafe {
185 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32
186 } as u64;
187 let div_clk = clk_peri_freq() as u64 * 64;
188 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
189
190 self.blocking_flush().unwrap();
191 while self.busy() {}
192 unsafe {
193 regs.uartlcr_h().write_set(|w| w.set_brk(true));
194 }
195 Timer::after(Duration::from_micros(wait_usecs)).await;
196 unsafe {
197 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
198 }
199 }
149} 200}
150 201
151impl<'d, T: Instance> UartTx<'d, T, Blocking> { 202impl<'d, T: Instance> UartTx<'d, T, Blocking> {
@@ -167,7 +218,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
167 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 218 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
168 let ch = self.tx_dma.as_mut().unwrap(); 219 let ch = self.tx_dma.as_mut().unwrap();
169 let transfer = unsafe { 220 let transfer = unsafe {
170 T::regs().uartdmacr().modify(|reg| { 221 T::regs().uartdmacr().write_set(|reg| {
171 reg.set_txdmae(true); 222 reg.set_txdmae(true);
172 }); 223 });
173 // If we don't assign future to a variable, the data register pointer 224 // If we don't assign future to a variable, the data register pointer
@@ -184,51 +235,86 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
184 pub fn new( 235 pub fn new(
185 _uart: impl Peripheral<P = T> + 'd, 236 _uart: impl Peripheral<P = T> + 'd,
186 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 237 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
238 irq: impl Peripheral<P = T::Interrupt> + 'd,
187 rx_dma: impl Peripheral<P = impl Channel> + 'd, 239 rx_dma: impl Peripheral<P = impl Channel> + 'd,
188 config: Config, 240 config: Config,
189 ) -> Self { 241 ) -> Self {
190 into_ref!(rx, rx_dma); 242 into_ref!(rx, irq, rx_dma);
191 Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config); 243 Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
192 Self::new_inner(Some(rx_dma.map_into())) 244 Self::new_inner(Some(irq), Some(rx_dma.map_into()))
193 } 245 }
194 246
195 fn new_inner(rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self { 247 fn new_inner(irq: Option<PeripheralRef<'d, T::Interrupt>>, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
248 debug_assert_eq!(irq.is_some(), rx_dma.is_some());
249 if let Some(irq) = irq {
250 unsafe {
251 // disable all error interrupts initially
252 T::regs().uartimsc().write(|w| w.0 = 0);
253 }
254 irq.set_handler(on_interrupt::<T>);
255 irq.unpend();
256 irq.enable();
257 }
196 Self { 258 Self {
197 rx_dma, 259 rx_dma,
198 phantom: PhantomData, 260 phantom: PhantomData,
199 } 261 }
200 } 262 }
201 263
202 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 264 pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> {
265 while buffer.len() > 0 {
266 let received = self.drain_fifo(buffer)?;
267 buffer = &mut buffer[received..];
268 }
269 Ok(())
270 }
271
272 fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
203 let r = T::regs(); 273 let r = T::regs();
204 unsafe { 274 for (i, b) in buffer.iter_mut().enumerate() {
205 for b in buffer { 275 if unsafe { r.uartfr().read().rxfe() } {
206 *b = loop { 276 return Ok(i);
207 if r.uartfr().read().rxfe() { 277 }
208 continue; 278
209 } 279 let dr = unsafe { r.uartdr().read() };
210 280
211 let dr = r.uartdr().read(); 281 if dr.oe() {
212 282 return Err(Error::Overrun);
213 if dr.oe() { 283 } else if dr.be() {
214 return Err(Error::Overrun); 284 return Err(Error::Break);
215 } else if dr.be() { 285 } else if dr.pe() {
216 return Err(Error::Break); 286 return Err(Error::Parity);
217 } else if dr.pe() { 287 } else if dr.fe() {
218 return Err(Error::Parity); 288 return Err(Error::Framing);
219 } else if dr.fe() { 289 } else {
220 return Err(Error::Framing); 290 *b = dr.data();
221 } else { 291 }
222 break dr.data(); 292 }
223 } 293 Ok(buffer.len())
224 }; 294 }
295}
296
297impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
298 fn drop(&mut self) {
299 if let Some(_) = self.rx_dma {
300 unsafe {
301 T::Interrupt::steal().disable();
225 } 302 }
226 } 303 }
227 Ok(())
228 } 304 }
229} 305}
230 306
231impl<'d, T: Instance> UartRx<'d, T, Blocking> { 307impl<'d, T: Instance> UartRx<'d, T, Blocking> {
308 pub fn new_blocking(
309 _uart: impl Peripheral<P = T> + 'd,
310 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
311 config: Config,
312 ) -> Self {
313 into_ref!(rx);
314 Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config);
315 Self::new_inner(None, None)
316 }
317
232 #[cfg(feature = "nightly")] 318 #[cfg(feature = "nightly")]
233 pub fn into_buffered( 319 pub fn into_buffered(
234 self, 320 self,
@@ -243,19 +329,93 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
243 } 329 }
244} 330}
245 331
332unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
333 let uart = T::regs();
334 let state = T::dma_state();
335 let errs = uart.uartris().read();
336 state.rx_errs.store(errs.0 as u16, Ordering::Relaxed);
337 state.rx_err_waker.wake();
338 // disable the error interrupts instead of clearing the flags. clearing the
339 // flags would allow the dma transfer to continue, potentially signaling
340 // completion before we can check for errors that happened *during* the transfer.
341 uart.uartimsc().write_clear(|w| w.0 = errs.0);
342}
343
246impl<'d, T: Instance> UartRx<'d, T, Async> { 344impl<'d, T: Instance> UartRx<'d, T, Async> {
247 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 345 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
346 // clear error flags before we drain the fifo. errors that have accumulated
347 // in the flags will also be present in the fifo.
348 T::dma_state().rx_errs.store(0, Ordering::Relaxed);
349 unsafe {
350 T::regs().uarticr().write(|w| {
351 w.set_oeic(true);
352 w.set_beic(true);
353 w.set_peic(true);
354 w.set_feic(true);
355 });
356 }
357
358 // then drain the fifo. we need to read at most 32 bytes. errors that apply
359 // to fifo bytes will be reported directly.
360 let buffer = match {
361 let limit = buffer.len().min(32);
362 self.drain_fifo(&mut buffer[0..limit])
363 } {
364 Ok(len) if len < buffer.len() => &mut buffer[len..],
365 Ok(_) => return Ok(()),
366 Err(e) => return Err(e),
367 };
368
369 // start a dma transfer. if errors have happened in the interim some error
370 // interrupt flags will have been raised, and those will be picked up immediately
371 // by the interrupt handler.
248 let ch = self.rx_dma.as_mut().unwrap(); 372 let ch = self.rx_dma.as_mut().unwrap();
249 let transfer = unsafe { 373 let transfer = unsafe {
250 T::regs().uartdmacr().modify(|reg| { 374 T::regs().uartimsc().write_set(|w| {
375 w.set_oeim(true);
376 w.set_beim(true);
377 w.set_peim(true);
378 w.set_feim(true);
379 });
380 T::regs().uartdmacr().write_set(|reg| {
251 reg.set_rxdmae(true); 381 reg.set_rxdmae(true);
382 reg.set_dmaonerr(true);
252 }); 383 });
253 // If we don't assign future to a variable, the data register pointer 384 // If we don't assign future to a variable, the data register pointer
254 // is held across an await and makes the future non-Send. 385 // is held across an await and makes the future non-Send.
255 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) 386 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ)
256 }; 387 };
257 transfer.await; 388
258 Ok(()) 389 // wait for either the transfer to complete or an error to happen.
390 let transfer_result = select(
391 transfer,
392 poll_fn(|cx| {
393 T::dma_state().rx_err_waker.register(cx.waker());
394 match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) {
395 0 => Poll::Pending,
396 e => Poll::Ready(Uartris(e as u32)),
397 }
398 }),
399 )
400 .await;
401
402 let errors = match transfer_result {
403 Either::First(()) => return Ok(()),
404 Either::Second(e) => e,
405 };
406
407 if errors.0 == 0 {
408 return Ok(());
409 } else if errors.oeris() {
410 return Err(Error::Overrun);
411 } else if errors.beris() {
412 return Err(Error::Break);
413 } else if errors.peris() {
414 return Err(Error::Parity);
415 } else if errors.feris() {
416 return Err(Error::Framing);
417 }
418 unreachable!("unrecognized rx error");
259 } 419 }
260} 420}
261 421
@@ -268,7 +428,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
268 config: Config, 428 config: Config,
269 ) -> Self { 429 ) -> Self {
270 into_ref!(tx, rx); 430 into_ref!(tx, rx);
271 Self::new_inner(uart, tx.map_into(), rx.map_into(), None, None, None, None, config) 431 Self::new_inner(uart, tx.map_into(), rx.map_into(), None, None, None, None, None, config)
272 } 432 }
273 433
274 /// Create a new UART with hardware flow control (RTS/CTS) 434 /// Create a new UART with hardware flow control (RTS/CTS)
@@ -289,6 +449,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
289 Some(cts.map_into()), 449 Some(cts.map_into()),
290 None, 450 None,
291 None, 451 None,
452 None,
292 config, 453 config,
293 ) 454 )
294 } 455 }
@@ -317,17 +478,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
317 uart: impl Peripheral<P = T> + 'd, 478 uart: impl Peripheral<P = T> + 'd,
318 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 479 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
319 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 480 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
481 irq: impl Peripheral<P = T::Interrupt> + 'd,
320 tx_dma: impl Peripheral<P = impl Channel> + 'd, 482 tx_dma: impl Peripheral<P = impl Channel> + 'd,
321 rx_dma: impl Peripheral<P = impl Channel> + 'd, 483 rx_dma: impl Peripheral<P = impl Channel> + 'd,
322 config: Config, 484 config: Config,
323 ) -> Self { 485 ) -> Self {
324 into_ref!(tx, rx, tx_dma, rx_dma); 486 into_ref!(tx, rx, irq, tx_dma, rx_dma);
325 Self::new_inner( 487 Self::new_inner(
326 uart, 488 uart,
327 tx.map_into(), 489 tx.map_into(),
328 rx.map_into(), 490 rx.map_into(),
329 None, 491 None,
330 None, 492 None,
493 Some(irq),
331 Some(tx_dma.map_into()), 494 Some(tx_dma.map_into()),
332 Some(rx_dma.map_into()), 495 Some(rx_dma.map_into()),
333 config, 496 config,
@@ -341,17 +504,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
341 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 504 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
342 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 505 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
343 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 506 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
507 irq: impl Peripheral<P = T::Interrupt> + 'd,
344 tx_dma: impl Peripheral<P = impl Channel> + 'd, 508 tx_dma: impl Peripheral<P = impl Channel> + 'd,
345 rx_dma: impl Peripheral<P = impl Channel> + 'd, 509 rx_dma: impl Peripheral<P = impl Channel> + 'd,
346 config: Config, 510 config: Config,
347 ) -> Self { 511 ) -> Self {
348 into_ref!(tx, rx, cts, rts, tx_dma, rx_dma); 512 into_ref!(tx, rx, cts, rts, irq, tx_dma, rx_dma);
349 Self::new_inner( 513 Self::new_inner(
350 uart, 514 uart,
351 tx.map_into(), 515 tx.map_into(),
352 rx.map_into(), 516 rx.map_into(),
353 Some(rts.map_into()), 517 Some(rts.map_into()),
354 Some(cts.map_into()), 518 Some(cts.map_into()),
519 Some(irq),
355 Some(tx_dma.map_into()), 520 Some(tx_dma.map_into()),
356 Some(rx_dma.map_into()), 521 Some(rx_dma.map_into()),
357 config, 522 config,
@@ -366,6 +531,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
366 mut rx: PeripheralRef<'d, AnyPin>, 531 mut rx: PeripheralRef<'d, AnyPin>,
367 mut rts: Option<PeripheralRef<'d, AnyPin>>, 532 mut rts: Option<PeripheralRef<'d, AnyPin>>,
368 mut cts: Option<PeripheralRef<'d, AnyPin>>, 533 mut cts: Option<PeripheralRef<'d, AnyPin>>,
534 irq: Option<PeripheralRef<'d, T::Interrupt>>,
369 tx_dma: Option<PeripheralRef<'d, AnyChannel>>, 535 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
370 rx_dma: Option<PeripheralRef<'d, AnyChannel>>, 536 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
371 config: Config, 537 config: Config,
@@ -380,7 +546,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
380 546
381 Self { 547 Self {
382 tx: UartTx::new_inner(tx_dma), 548 tx: UartTx::new_inner(tx_dma),
383 rx: UartRx::new_inner(rx_dma), 549 rx: UartRx::new_inner(irq, rx_dma),
384 } 550 }
385 } 551 }
386 552
@@ -516,6 +682,14 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
516 self.rx.blocking_read(buffer) 682 self.rx.blocking_read(buffer)
517 } 683 }
518 684
685 pub fn busy(&self) -> bool {
686 self.tx.busy()
687 }
688
689 pub async fn send_break(&mut self, bits: u32) {
690 self.tx.send_break(bits).await
691 }
692
519 /// Split the Uart into a transmitter and receiver, which is particuarly 693 /// Split the Uart into a transmitter and receiver, which is particuarly
520 /// useful when having two tasks correlating to transmitting and receiving. 694 /// useful when having two tasks correlating to transmitting and receiving.
521 pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { 695 pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) {
@@ -700,13 +874,16 @@ mod sealed {
700 pub trait Instance { 874 pub trait Instance {
701 const TX_DREQ: u8; 875 const TX_DREQ: u8;
702 const RX_DREQ: u8; 876 const RX_DREQ: u8;
877 const ID: usize;
703 878
704 type Interrupt: crate::interrupt::Interrupt; 879 type Interrupt: crate::interrupt::Interrupt;
705 880
706 fn regs() -> pac::uart::Uart; 881 fn regs() -> pac::uart::Uart;
707 882
708 #[cfg(feature = "nightly")] 883 #[cfg(feature = "nightly")]
709 fn state() -> &'static buffered::State; 884 fn buffered_state() -> &'static buffered::State;
885
886 fn dma_state() -> &'static DmaState;
710 } 887 }
711 pub trait TxPin<T: Instance> {} 888 pub trait TxPin<T: Instance> {}
712 pub trait RxPin<T: Instance> {} 889 pub trait RxPin<T: Instance> {}
@@ -732,10 +909,11 @@ impl_mode!(Async);
732pub trait Instance: sealed::Instance {} 909pub trait Instance: sealed::Instance {}
733 910
734macro_rules! impl_instance { 911macro_rules! impl_instance {
735 ($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => { 912 ($inst:ident, $irq:ident, $id:expr, $tx_dreq:expr, $rx_dreq:expr) => {
736 impl sealed::Instance for peripherals::$inst { 913 impl sealed::Instance for peripherals::$inst {
737 const TX_DREQ: u8 = $tx_dreq; 914 const TX_DREQ: u8 = $tx_dreq;
738 const RX_DREQ: u8 = $rx_dreq; 915 const RX_DREQ: u8 = $rx_dreq;
916 const ID: usize = $id;
739 917
740 type Interrupt = crate::interrupt::$irq; 918 type Interrupt = crate::interrupt::$irq;
741 919
@@ -744,17 +922,25 @@ macro_rules! impl_instance {
744 } 922 }
745 923
746 #[cfg(feature = "nightly")] 924 #[cfg(feature = "nightly")]
747 fn state() -> &'static buffered::State { 925 fn buffered_state() -> &'static buffered::State {
748 static STATE: buffered::State = buffered::State::new(); 926 static STATE: buffered::State = buffered::State::new();
749 &STATE 927 &STATE
750 } 928 }
929
930 fn dma_state() -> &'static DmaState {
931 static STATE: DmaState = DmaState {
932 rx_err_waker: AtomicWaker::new(),
933 rx_errs: AtomicU16::new(0),
934 };
935 &STATE
936 }
751 } 937 }
752 impl Instance for peripherals::$inst {} 938 impl Instance for peripherals::$inst {}
753 }; 939 };
754} 940}
755 941
756impl_instance!(UART0, UART0_IRQ, 20, 21); 942impl_instance!(UART0, UART0_IRQ, 0, 20, 21);
757impl_instance!(UART1, UART1_IRQ, 22, 23); 943impl_instance!(UART1, UART1_IRQ, 1, 22, 23);
758 944
759pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 945pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
760pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 946pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index f56e7009f..4119a309f 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -7,6 +7,7 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::interrupt;
10use embassy_rp::peripherals::UART1; 11use embassy_rp::peripherals::UART1;
11use embassy_rp::uart::{Async, Config, UartRx, UartTx}; 12use embassy_rp::uart::{Async, Config, UartRx, UartTx};
12use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
@@ -17,7 +18,13 @@ async fn main(spawner: Spawner) {
17 let p = embassy_rp::init(Default::default()); 18 let p = embassy_rp::init(Default::default());
18 19
19 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); 20 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
20 let uart_rx = UartRx::new(p.UART1, p.PIN_5, p.DMA_CH1, Config::default()); 21 let uart_rx = UartRx::new(
22 p.UART1,
23 p.PIN_5,
24 interrupt::take!(UART1_IRQ),
25 p.DMA_CH1,
26 Config::default(),
27 );
21 28
22 unwrap!(spawner.spawn(reader(uart_rx))); 29 unwrap!(spawner.spawn(reader(uart_rx)));
23 30
diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs
index 92f61464e..80c18c02e 100644
--- a/tests/rp/src/bin/uart.rs
+++ b/tests/rp/src/bin/uart.rs
@@ -4,28 +4,165 @@
4 4
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart}; 7use embassy_rp::gpio::{Level, Output};
8use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx};
9use embassy_time::{Duration, Timer};
8use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
9 11
12fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
13 let mut buf = [255; N];
14 uart.blocking_read(&mut buf)?;
15 Ok(buf)
16}
17
18fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
19 let mut buf = [255; N];
20 uart.blocking_read(&mut buf)?;
21 Ok(buf)
22}
23
24async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
25 pin.set_low();
26 Timer::after(Duration::from_millis(1)).await;
27 for i in 0..8 {
28 if v & (1 << i) == 0 {
29 pin.set_low();
30 } else {
31 pin.set_high();
32 }
33 Timer::after(Duration::from_millis(1)).await;
34 }
35 if let Some(b) = parity {
36 if b {
37 pin.set_high();
38 } else {
39 pin.set_low();
40 }
41 Timer::after(Duration::from_millis(1)).await;
42 }
43 pin.set_high();
44 Timer::after(Duration::from_millis(1)).await;
45}
46
10#[embassy_executor::main] 47#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 48async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default()); 49 let p = embassy_rp::init(Default::default());
13 info!("Hello World!"); 50 info!("Hello World!");
14 51
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); 52 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
53
54 {
55 let config = Config::default();
56 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
57
58 // We can't send too many bytes, they have to fit in the FIFO.
59 // This is because we aren't sending+receiving at the same time.
60
61 let data = [0xC0, 0xDE];
62 uart.blocking_write(&data).unwrap();
63 assert_eq!(read(&mut uart).unwrap(), data);
64 }
65
66 info!("test overflow detection");
67 {
68 let config = Config::default();
69 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
70
71 let data = [
72 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
73 30, 31, 32,
74 ];
75 let overflow = [
76 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
77 ];
78 uart.blocking_write(&data).unwrap();
79 uart.blocking_write(&overflow).unwrap();
80 while uart.busy() {}
81
82 // prefix in fifo is valid
83 assert_eq!(read(&mut uart).unwrap(), data);
84 // next received character causes overrun error and is discarded
85 uart.blocking_write(&[1, 2, 3]).unwrap();
86 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Overrun);
87 assert_eq!(read(&mut uart).unwrap(), [2, 3]);
88 }
89
90 info!("test break detection");
91 {
92 let config = Config::default();
93 let mut uart = Uart::new_blocking(&mut uart, &mut tx, &mut rx, config);
94
95 // break on empty fifo
96 uart.send_break(20).await;
97 uart.blocking_write(&[64]).unwrap();
98 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break);
99 assert_eq!(read(&mut uart).unwrap(), [64]);
100
101 // break on partially filled fifo
102 uart.blocking_write(&[65; 2]).unwrap();
103 uart.send_break(20).await;
104 uart.blocking_write(&[66]).unwrap();
105 assert_eq!(read(&mut uart).unwrap(), [65; 2]);
106 assert_eq!(read::<1>(&mut uart).unwrap_err(), Error::Break);
107 assert_eq!(read(&mut uart).unwrap(), [66]);
108 }
109
110 // parity detection. here we bitbang to not require two uarts.
111 info!("test parity error detection");
112 {
113 let mut pin = Output::new(&mut tx, Level::High);
114 let mut config = Config::default();
115 config.baudrate = 1000;
116 config.parity = Parity::ParityEven;
117 let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config);
118
119 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u8) {
120 send(pin, v, Some(parity != 0)).await;
121 }
122
123 // first check that we can send correctly
124 chr(&mut pin, 64, 1).await;
125 assert_eq!(read1(&mut uart).unwrap(), [64]);
126
127 // all good, check real errors
128 chr(&mut pin, 2, 1).await;
129 chr(&mut pin, 3, 0).await;
130 chr(&mut pin, 4, 0).await;
131 chr(&mut pin, 5, 0).await;
132 assert_eq!(read1(&mut uart).unwrap(), [2, 3]);
133 assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Parity);
134 assert_eq!(read1(&mut uart).unwrap(), [5]);
135 }
16 136
17 let config = Config::default(); 137 // framing error detection. here we bitbang because there's no other way.
18 let mut uart = Uart::new_blocking(uart, tx, rx, config); 138 info!("test framing error detection");
139 {
140 let mut pin = Output::new(&mut tx, Level::High);
141 let mut config = Config::default();
142 config.baudrate = 1000;
143 let mut uart = UartRx::new_blocking(&mut uart, &mut rx, config);
19 144
20 // We can't send too many bytes, they have to fit in the FIFO. 145 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
21 // This is because we aren't sending+receiving at the same time. 146 if good {
147 send(pin, v, None).await;
148 } else {
149 send(pin, v, Some(false)).await;
150 }
151 }
22 152
23 let data = [0xC0, 0xDE]; 153 // first check that we can send correctly
24 uart.blocking_write(&data).unwrap(); 154 chr(&mut pin, 64, true).await;
155 assert_eq!(read1(&mut uart).unwrap(), [64]);
25 156
26 let mut buf = [0; 2]; 157 // all good, check real errors
27 uart.blocking_read(&mut buf).unwrap(); 158 chr(&mut pin, 2, true).await;
28 assert_eq!(buf, data); 159 chr(&mut pin, 3, true).await;
160 chr(&mut pin, 4, false).await;
161 chr(&mut pin, 5, true).await;
162 assert_eq!(read1(&mut uart).unwrap(), [2, 3]);
163 assert_eq!(read1::<1>(&mut uart).unwrap_err(), Error::Framing);
164 assert_eq!(read1(&mut uart).unwrap(), [5]);
165 }
29 166
30 info!("Test OK"); 167 info!("Test OK");
31 cortex_m::asm::bkpt(); 168 cortex_m::asm::bkpt();
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs
index bea9283e7..1deb22ce6 100644
--- a/tests/rp/src/bin/uart_buffered.rs
+++ b/tests/rp/src/bin/uart_buffered.rs
@@ -2,39 +2,248 @@
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4 4
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::gpio::{Level, Output};
7use embassy_rp::interrupt; 8use embassy_rp::interrupt;
8use embassy_rp::uart::{BufferedUart, Config}; 9use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
9use embedded_io::asynch::{Read, Write}; 10use embassy_time::{Duration, Timer};
11use embedded_io::asynch::{Read, ReadExactError, Write};
10use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
11 13
14async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
15 let mut buf = [255; N];
16 match uart.read_exact(&mut buf).await {
17 Ok(()) => Ok(buf),
18 // we should not ever produce an Eof condition
19 Err(ReadExactError::UnexpectedEof) => panic!(),
20 Err(ReadExactError::Other(e)) => Err(e),
21 }
22}
23
24async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) -> Result<[u8; N], Error> {
25 let mut buf = [255; N];
26 match uart.read_exact(&mut buf).await {
27 Ok(()) => Ok(buf),
28 // we should not ever produce an Eof condition
29 Err(ReadExactError::UnexpectedEof) => panic!(),
30 Err(ReadExactError::Other(e)) => Err(e),
31 }
32}
33
34async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
35 pin.set_low();
36 Timer::after(Duration::from_millis(1)).await;
37 for i in 0..8 {
38 if v & (1 << i) == 0 {
39 pin.set_low();
40 } else {
41 pin.set_high();
42 }
43 Timer::after(Duration::from_millis(1)).await;
44 }
45 if let Some(b) = parity {
46 if b {
47 pin.set_high();
48 } else {
49 pin.set_low();
50 }
51 Timer::after(Duration::from_millis(1)).await;
52 }
53 pin.set_high();
54 Timer::after(Duration::from_millis(1)).await;
55}
56
12#[embassy_executor::main] 57#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 58async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default()); 59 let p = embassy_rp::init(Default::default());
15 info!("Hello World!"); 60 info!("Hello World!");
16 61
17 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); 62 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
63 let mut irq = interrupt::take!(UART0_IRQ);
64
65 {
66 let config = Config::default();
67 let tx_buf = &mut [0u8; 16];
68 let rx_buf = &mut [0u8; 16];
69 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config);
70
71 // Make sure we send more bytes than fits in the FIFO, to test the actual
72 // bufferedUart.
73
74 let data = [
75 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
76 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
77 ];
78 uart.write_all(&data).await.unwrap();
79 info!("Done writing");
80
81 assert_eq!(read(&mut uart).await.unwrap(), data);
82 }
83
84 info!("test overflow detection");
85 {
86 let config = Config::default();
87 let tx_buf = &mut [0u8; 16];
88 let rx_buf = &mut [0u8; 16];
89 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config);
90
91 // Make sure we send more bytes than fits in the FIFO, to test the actual
92 // bufferedUart.
93
94 let data = [
95 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
96 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
97 ];
98 let overflow = [
99 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
100 ];
101 // give each block time to settle into the fifo. we want the overrun to occur at a well-defined point.
102 uart.write_all(&data).await.unwrap();
103 uart.blocking_flush().unwrap();
104 while uart.busy() {}
105 uart.write_all(&overflow).await.unwrap();
106 uart.blocking_flush().unwrap();
107 while uart.busy() {}
108
109 // already buffered/fifod prefix is valid
110 assert_eq!(read(&mut uart).await.unwrap(), data);
111 // next received character causes overrun error and is discarded
112 uart.write_all(&[1, 2, 3]).await.unwrap();
113 uart.blocking_flush().unwrap();
114 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Overrun);
115 assert_eq!(read(&mut uart).await.unwrap(), [2, 3]);
116 }
117
118 info!("test break detection");
119 {
120 let mut config = Config::default();
121 config.baudrate = 1000;
122 let tx_buf = &mut [0u8; 16];
123 let rx_buf = &mut [0u8; 16];
124 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config);
125
126 // break on empty buffer
127 uart.send_break(20).await;
128 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
129 uart.write_all(&[64]).await.unwrap();
130 assert_eq!(read(&mut uart).await.unwrap(), [64]);
131
132 // break on partially filled buffer
133 uart.write_all(&[65; 2]).await.unwrap();
134 uart.send_break(20).await;
135 uart.write_all(&[66]).await.unwrap();
136 assert_eq!(read(&mut uart).await.unwrap(), [65; 2]);
137 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
138 assert_eq!(read(&mut uart).await.unwrap(), [66]);
139
140 // break on full buffer
141 uart.write_all(&[64; 16]).await.unwrap();
142 uart.send_break(20).await;
143 uart.write_all(&[65]).await.unwrap();
144 assert_eq!(read(&mut uart).await.unwrap(), [64; 16]);
145 assert_eq!(read::<1>(&mut uart).await.unwrap_err(), Error::Break);
146 assert_eq!(read(&mut uart).await.unwrap(), [65]);
147 }
148
149 // parity detection. here we bitbang to not require two uarts.
150 info!("test parity error detection");
151 {
152 let mut pin = Output::new(&mut tx, Level::High);
153 // choose a very slow baud rate to make tests reliable even with O0
154 let mut config = Config::default();
155 config.baudrate = 1000;
156 config.parity = Parity::ParityEven;
157 let rx_buf = &mut [0u8; 16];
158 let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config);
159
160 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
161 send(pin, v, Some(parity != 0)).await;
162 }
163
164 // first check that we can send correctly
165 chr(&mut pin, 64, 1).await;
166 assert_eq!(read1(&mut uart).await.unwrap(), [64]);
167
168 // parity on empty buffer
169 chr(&mut pin, 64, 0).await;
170 chr(&mut pin, 4, 1).await;
171 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
172 assert_eq!(read1(&mut uart).await.unwrap(), [4]);
173
174 // parity on partially filled buffer
175 chr(&mut pin, 64, 1).await;
176 chr(&mut pin, 32, 1).await;
177 chr(&mut pin, 64, 0).await;
178 chr(&mut pin, 65, 0).await;
179 assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]);
180 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
181 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
182
183 // parity on full buffer
184 for i in 0..16 {
185 chr(&mut pin, i, i.count_ones() % 2).await;
186 }
187 chr(&mut pin, 64, 0).await;
188 chr(&mut pin, 65, 0).await;
189 assert_eq!(
190 read1(&mut uart).await.unwrap(),
191 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
192 );
193 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
194 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
195 }
196
197 // framing error detection. here we bitbang because there's no other way.
198 info!("test framing error detection");
199 {
200 let mut pin = Output::new(&mut tx, Level::High);
201 // choose a very slow baud rate to make tests reliable even with O0
202 let mut config = Config::default();
203 config.baudrate = 1000;
204 let rx_buf = &mut [0u8; 16];
205 let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config);
206
207 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
208 if good {
209 send(pin, v, None).await;
210 } else {
211 send(pin, v, Some(false)).await;
212 }
213 }
18 214
19 let config = Config::default(); 215 // first check that we can send correctly
20 let irq = interrupt::take!(UART0_IRQ); 216 chr(&mut pin, 64, true).await;
21 let tx_buf = &mut [0u8; 16]; 217 assert_eq!(read1(&mut uart).await.unwrap(), [64]);
22 let rx_buf = &mut [0u8; 16];
23 let mut uart = BufferedUart::new(uart, irq, tx, rx, tx_buf, rx_buf, config);
24 218
25 // Make sure we send more bytes than fits in the FIFO, to test the actual 219 // framing on empty buffer
26 // bufferedUart. 220 chr(&mut pin, 64, false).await;
221 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
222 chr(&mut pin, 65, true).await;
223 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
27 224
28 let data = [ 225 // framing on partially filled buffer
29 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 226 chr(&mut pin, 64, true).await;
30 30, 31, 227 chr(&mut pin, 32, true).await;
31 ]; 228 chr(&mut pin, 64, false).await;
32 uart.write_all(&data).await.unwrap(); 229 chr(&mut pin, 65, true).await;
33 info!("Done writing"); 230 assert_eq!(read1(&mut uart).await.unwrap(), [64, 32]);
231 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
232 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
34 233
35 let mut buf = [0; 31]; 234 // framing on full buffer
36 uart.read_exact(&mut buf).await.unwrap(); 235 for i in 0..16 {
37 assert_eq!(buf, data); 236 chr(&mut pin, i, true).await;
237 }
238 chr(&mut pin, 64, false).await;
239 chr(&mut pin, 65, true).await;
240 assert_eq!(
241 read1(&mut uart).await.unwrap(),
242 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
243 );
244 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
245 assert_eq!(read1(&mut uart).await.unwrap(), [65]);
246 }
38 247
39 info!("Test OK"); 248 info!("Test OK");
40 cortex_m::asm::bkpt(); 249 cortex_m::asm::bkpt();
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
index 963c22707..92aa205c9 100644
--- a/tests/rp/src/bin/uart_dma.rs
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -4,28 +4,246 @@
4 4
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::uart::{Config, Uart}; 7use embassy_rp::gpio::{Level, Output};
8use embassy_rp::interrupt;
9use embassy_rp::uart::{Async, Config, Error, Instance, Parity, Uart, UartRx};
10use embassy_time::{Duration, Timer};
8use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
9 12
13async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
14 let mut buf = [255; N];
15 uart.read(&mut buf).await?;
16 Ok(buf)
17}
18
19async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
20 let mut buf = [255; N];
21 uart.read(&mut buf).await?;
22 Ok(buf)
23}
24
25async fn send(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: Option<bool>) {
26 pin.set_low();
27 Timer::after(Duration::from_millis(1)).await;
28 for i in 0..8 {
29 if v & (1 << i) == 0 {
30 pin.set_low();
31 } else {
32 pin.set_high();
33 }
34 Timer::after(Duration::from_millis(1)).await;
35 }
36 if let Some(b) = parity {
37 if b {
38 pin.set_high();
39 } else {
40 pin.set_low();
41 }
42 Timer::after(Duration::from_millis(1)).await;
43 }
44 pin.set_high();
45 Timer::after(Duration::from_millis(1)).await;
46}
47
10#[embassy_executor::main] 48#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 49async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default()); 50 let mut p = embassy_rp::init(Default::default());
13 info!("Hello World!"); 51 info!("Hello World!");
14 52
15 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); 53 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
54 let mut irq = interrupt::take!(UART0_IRQ);
16 55
17 let config = Config::default(); 56 // TODO
18 let mut uart = Uart::new(uart, tx, rx, p.DMA_CH0, p.DMA_CH1, config); 57 // nuclear error reporting. just abort the entire transfer and invalidate the
58 // dma buffer, buffered buffer, fifo etc.
19 59
20 // We can't send too many bytes, they have to fit in the FIFO. 60 // We can't send too many bytes, they have to fit in the FIFO.
21 // This is because we aren't sending+receiving at the same time. 61 // This is because we aren't sending+receiving at the same time.
62 {
63 let config = Config::default();
64 let mut uart = Uart::new(
65 &mut uart,
66 &mut tx,
67 &mut rx,
68 &mut irq,
69 &mut p.DMA_CH0,
70 &mut p.DMA_CH1,
71 config,
72 );
73
74 let data = [0xC0, 0xDE];
75 uart.write(&data).await.unwrap();
76
77 let mut buf = [0; 2];
78 uart.read(&mut buf).await.unwrap();
79 assert_eq!(buf, data);
80 }
81
82 info!("test overflow detection");
83 {
84 let config = Config::default();
85 let mut uart = Uart::new(
86 &mut uart,
87 &mut tx,
88 &mut rx,
89 &mut irq,
90 &mut p.DMA_CH0,
91 &mut p.DMA_CH1,
92 config,
93 );
94
95 uart.blocking_write(&[42; 32]).unwrap();
96 uart.blocking_write(&[1, 2, 3]).unwrap();
97 uart.blocking_flush().unwrap();
98
99 // can receive regular fifo contents
100 assert_eq!(read(&mut uart).await, Ok([42; 16]));
101 assert_eq!(read(&mut uart).await, Ok([42; 16]));
102 // receiving the rest fails with overrun
103 assert_eq!(read::<16>(&mut uart).await, Err(Error::Overrun));
104 // new data is accepted, latest overrunning byte first
105 assert_eq!(read(&mut uart).await, Ok([3]));
106 uart.blocking_write(&[8, 9]).unwrap();
107 Timer::after(Duration::from_millis(1)).await;
108 assert_eq!(read(&mut uart).await, Ok([8, 9]));
109 }
110
111 info!("test break detection");
112 {
113 let config = Config::default();
114 let (mut tx, mut rx) = Uart::new(
115 &mut uart,
116 &mut tx,
117 &mut rx,
118 &mut irq,
119 &mut p.DMA_CH0,
120 &mut p.DMA_CH1,
121 config,
122 )
123 .split();
124
125 // break before read
126 tx.send_break(20).await;
127 tx.write(&[64]).await.unwrap();
128 assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break);
129 assert_eq!(read1(&mut rx).await.unwrap(), [64]);
130
131 // break during read
132 {
133 let r = read1::<2>(&mut rx);
134 tx.write(&[2]).await.unwrap();
135 tx.send_break(20).await;
136 tx.write(&[3]).await.unwrap();
137 assert_eq!(r.await.unwrap_err(), Error::Break);
138 assert_eq!(read1(&mut rx).await.unwrap(), [3]);
139 }
140
141 // break after read
142 {
143 let r = read1(&mut rx);
144 tx.write(&[2]).await.unwrap();
145 tx.send_break(20).await;
146 tx.write(&[3]).await.unwrap();
147 assert_eq!(r.await.unwrap(), [2]);
148 assert_eq!(read1::<1>(&mut rx).await.unwrap_err(), Error::Break);
149 assert_eq!(read1(&mut rx).await.unwrap(), [3]);
150 }
151 }
152
153 // parity detection. here we bitbang to not require two uarts.
154 info!("test parity error detection");
155 {
156 let mut pin = Output::new(&mut tx, Level::High);
157 // choose a very slow baud rate to make tests reliable even with O0
158 let mut config = Config::default();
159 config.baudrate = 1000;
160 config.parity = Parity::ParityEven;
161 let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config);
162
163 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
164 send(pin, v, Some(parity != 0)).await;
165 }
166
167 // first check that we can send correctly
168 chr(&mut pin, 32, 1).await;
169 assert_eq!(read1(&mut uart).await.unwrap(), [32]);
170
171 // parity error before read
172 chr(&mut pin, 32, 0).await;
173 chr(&mut pin, 31, 1).await;
174 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
175 assert_eq!(read1(&mut uart).await.unwrap(), [31]);
176
177 // parity error during read
178 {
179 let r = read1::<2>(&mut uart);
180 chr(&mut pin, 2, 1).await;
181 chr(&mut pin, 32, 0).await;
182 chr(&mut pin, 3, 0).await;
183 assert_eq!(r.await.unwrap_err(), Error::Parity);
184 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
185 }
186
187 // parity error after read
188 {
189 let r = read1(&mut uart);
190 chr(&mut pin, 2, 1).await;
191 chr(&mut pin, 32, 0).await;
192 chr(&mut pin, 3, 0).await;
193 assert_eq!(r.await.unwrap(), [2]);
194 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Parity);
195 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
196 }
197 }
198
199 // framing error detection. here we bitbang because there's no other way.
200 info!("test framing error detection");
201 {
202 let mut pin = Output::new(&mut tx, Level::High);
203 // choose a very slow baud rate to make tests reliable even with O0
204 let mut config = Config::default();
205 config.baudrate = 1000;
206 let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config);
207
208 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
209 if good {
210 send(pin, v, None).await;
211 } else {
212 send(pin, v, Some(false)).await;
213 }
214 }
215
216 // first check that we can send correctly
217 chr(&mut pin, 32, true).await;
218 assert_eq!(read1(&mut uart).await.unwrap(), [32]);
219
220 // parity error before read
221 chr(&mut pin, 32, false).await;
222 chr(&mut pin, 31, true).await;
223 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
224 assert_eq!(read1(&mut uart).await.unwrap(), [31]);
22 225
23 let data = [0xC0, 0xDE]; 226 // parity error during read
24 uart.write(&data).await.unwrap(); 227 {
228 let r = read1::<2>(&mut uart);
229 chr(&mut pin, 2, true).await;
230 chr(&mut pin, 32, false).await;
231 chr(&mut pin, 3, true).await;
232 assert_eq!(r.await.unwrap_err(), Error::Framing);
233 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
234 }
25 235
26 let mut buf = [0; 2]; 236 // parity error after read
27 uart.read(&mut buf).await.unwrap(); 237 {
28 assert_eq!(buf, data); 238 let r = read1(&mut uart);
239 chr(&mut pin, 2, true).await;
240 chr(&mut pin, 32, false).await;
241 chr(&mut pin, 3, true).await;
242 assert_eq!(r.await.unwrap(), [2]);
243 assert_eq!(read1::<1>(&mut uart).await.unwrap_err(), Error::Framing);
244 assert_eq!(read1(&mut uart).await.unwrap(), [3]);
245 }
246 }
29 247
30 info!("Test OK"); 248 info!("Test OK");
31 cortex_m::asm::bkpt(); 249 cortex_m::asm::bkpt();