aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/mod.rs93
-rw-r--r--tests/stm32/src/bin/usart.rs22
2 files changed, 82 insertions, 33 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index e946762af..b4373529c 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -109,6 +109,8 @@ pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
109 _peri: PeripheralRef<'d, T>, 109 _peri: PeripheralRef<'d, T>,
110 rx_dma: PeripheralRef<'d, RxDma>, 110 rx_dma: PeripheralRef<'d, RxDma>,
111 detect_previous_overrun: bool, 111 detect_previous_overrun: bool,
112 #[cfg(any(usart_v1, usart_v2))]
113 buffered_sr: stm32_metapac::usart::regs::Sr,
112} 114}
113 115
114impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 116impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
@@ -275,6 +277,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
275 _peri: peri, 277 _peri: peri,
276 rx_dma, 278 rx_dma,
277 detect_previous_overrun: config.detect_previous_overrun, 279 detect_previous_overrun: config.detect_previous_overrun,
280 #[cfg(any(usart_v1, usart_v2))]
281 buffered_sr: stm32_metapac::usart::regs::Sr(0),
278 } 282 }
279 } 283 }
280 284
@@ -335,6 +339,59 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
335 } 339 }
336 } 340 }
337 341
342 #[cfg(any(usart_v1, usart_v2))]
343 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
344 let r = T::regs();
345 loop {
346 // Handle all buffered error flags.
347 if self.buffered_sr.pe() {
348 self.buffered_sr.set_pe(false);
349 return Err(Error::Parity);
350 } else if self.buffered_sr.fe() {
351 self.buffered_sr.set_fe(false);
352 return Err(Error::Framing);
353 } else if self.buffered_sr.ne() {
354 self.buffered_sr.set_ne(false);
355 return Err(Error::Noise);
356 } else if self.buffered_sr.ore() {
357 self.buffered_sr.set_ore(false);
358 return Err(Error::Overrun);
359 } else if self.buffered_sr.rxne() {
360 self.buffered_sr.set_rxne(false);
361 return Ok(true);
362 } else {
363 // No error flags from previous iterations were set: Check the actual status register
364 let sr = r.sr().read();
365 if !sr.rxne() {
366 return Ok(false);
367 }
368
369 // Buffer the status register and let the loop handle the error flags.
370 self.buffered_sr = sr;
371 }
372 }
373 }
374
375 #[cfg(any(usart_v3, usart_v4))]
376 unsafe fn check_rx_flags(&mut self) -> Result<bool, Error> {
377 let r = T::regs();
378 let sr = r.isr().read();
379 if sr.pe() {
380 r.icr().write(|w| w.set_pe(true));
381 return Err(Error::Parity);
382 } else if sr.fe() {
383 r.icr().write(|w| w.set_fe(true));
384 return Err(Error::Framing);
385 } else if sr.ne() {
386 r.icr().write(|w| w.set_ne(true));
387 return Err(Error::Noise);
388 } else if sr.ore() {
389 r.icr().write(|w| w.set_ore(true));
390 return Err(Error::Overrun);
391 }
392 Ok(sr.rxne())
393 }
394
338 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 395 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
339 where 396 where
340 RxDma: crate::usart::RxDma<T>, 397 RxDma: crate::usart::RxDma<T>,
@@ -347,20 +404,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
347 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 404 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
348 let r = T::regs(); 405 let r = T::regs();
349 unsafe { 406 unsafe {
350 let sr = sr(r).read(); 407 if self.check_rx_flags()? {
351 if sr.pe() {
352 rdr(r).read_volatile();
353 Err(nb::Error::Other(Error::Parity))
354 } else if sr.fe() {
355 rdr(r).read_volatile();
356 Err(nb::Error::Other(Error::Framing))
357 } else if sr.ne() {
358 rdr(r).read_volatile();
359 Err(nb::Error::Other(Error::Noise))
360 } else if sr.ore() {
361 rdr(r).read_volatile();
362 Err(nb::Error::Other(Error::Overrun))
363 } else if sr.rxne() {
364 Ok(rdr(r).read_volatile()) 408 Ok(rdr(r).read_volatile())
365 } else { 409 } else {
366 Err(nb::Error::WouldBlock) 410 Err(nb::Error::WouldBlock)
@@ -372,24 +416,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
372 unsafe { 416 unsafe {
373 let r = T::regs(); 417 let r = T::regs();
374 for b in buffer { 418 for b in buffer {
375 loop { 419 while !self.check_rx_flags()? {}
376 let sr = sr(r).read();
377 if sr.pe() {
378 rdr(r).read_volatile();
379 return Err(Error::Parity);
380 } else if sr.fe() {
381 rdr(r).read_volatile();
382 return Err(Error::Framing);
383 } else if sr.ne() {
384 rdr(r).read_volatile();
385 return Err(Error::Noise);
386 } else if sr.ore() {
387 rdr(r).read_volatile();
388 return Err(Error::Overrun);
389 } else if sr.rxne() {
390 break;
391 }
392 }
393 *b = rdr(r).read_volatile(); 420 *b = rdr(r).read_volatile();
394 } 421 }
395 } 422 }
@@ -715,6 +742,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
715 _peri: peri, 742 _peri: peri,
716 rx_dma, 743 rx_dma,
717 detect_previous_overrun: config.detect_previous_overrun, 744 detect_previous_overrun: config.detect_previous_overrun,
745 #[cfg(any(usart_v1, usart_v2))]
746 buffered_sr: stm32_metapac::usart::regs::Sr(0),
718 }, 747 },
719 } 748 }
720 } 749 }
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index bda2ce9c2..0749f8406 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -8,7 +8,7 @@ use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Error, Uart};
12use embassy_time::{Duration, Instant}; 12use embassy_time::{Duration, Instant};
13use example_common::*; 13use example_common::*;
14 14
@@ -53,6 +53,26 @@ async fn main(_spawner: Spawner) {
53 assert_eq!(buf, data); 53 assert_eq!(buf, data);
54 } 54 }
55 55
56 // Test error handling with with an overflow error
57 {
58 let config = Config::default();
59 let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, &mut irq, NoDma, NoDma, config);
60
61 // Send enough bytes to fill the RX FIFOs off all USART versions.
62 let data = [0xC0, 0xDE, 0x12, 0x23, 0x34];
63 usart.blocking_write(&data).unwrap();
64 usart.blocking_flush().unwrap();
65
66 // The error should be reported first.
67 let mut buf = [0; 1];
68 let err = usart.blocking_read(&mut buf);
69 assert_eq!(err, Err(Error::Overrun));
70
71 // At least the first data byte should still be available on all USART versions.
72 usart.blocking_read(&mut buf).unwrap();
73 assert_eq!(buf[0], data[0]);
74 }
75
56 // Test that baudrate divider is calculated correctly. 76 // Test that baudrate divider is calculated correctly.
57 // Do it by comparing the time it takes to send a known number of bytes. 77 // Do it by comparing the time it takes to send a known number of bytes.
58 for baudrate in [ 78 for baudrate in [