aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Kröger <[email protected]>2023-05-14 20:34:57 +0200
committerTimo Kröger <[email protected]>2023-05-14 21:10:37 +0200
commit977a7906e47ed8b05388e8cdea0403a08a00b962 (patch)
tree41f6393621cb7dd57e91db1225aee6a3683c87ed
parent82f7e104d90a6628d1873017ea5ef6a7afb3b3f7 (diff)
stm32 uart: Fix error flag handling for blocking operations
Clear and report the error flags one by one and pop the data byte only after all error flags were handled. For v1/v2 we emulate the v3/v4 behaviour by buffering the status register because a read to the data register clears all flags at once which means we might loose all but the first error.
-rw-r--r--embassy-stm32/src/usart/mod.rs93
1 files changed, 61 insertions, 32 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 }