aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-01 19:42:03 +0000
committerGitHub <[email protected]>2025-11-01 19:42:03 +0000
commitcf231d461ff4b16cf7d16e4dbc5db909212c2c89 (patch)
tree19e925bb265c20492799ade1d1ef78fbbff8e400
parent9b1add3d83e98c6c9ae9230bf35cd89bba530a20 (diff)
parentac6e75c8887a6d2362cc00dbf246017d2cd1e102 (diff)
Merge pull request #4807 from xoviat/rb-uart
stm32/uart: fix rb uart race
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs34
2 files changed, 14 insertions, 21 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 0c1c97665..99808c233 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
37- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer 37- change: stm32/uart: BufferedUartRx now returns all available bytes from the internal buffer
38- change: timer: added output compare values 38- change: timer: added output compare values
39- feat: timer: add ability to set master mode 39- feat: timer: add ability to set master mode
40- fix: usart: fix race condition in ringbuffered usart
40 41
41## 0.4.0 - 2025-08-26 42## 0.4.0 - 2025-08-26
42 43
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index 20bfefd9e..bac570d27 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -7,7 +7,9 @@ use embassy_embedded_hal::SetConfig;
7use embedded_io_async::ReadReady; 7use embedded_io_async::ReadReady;
8use futures_util::future::{Either, select}; 8use futures_util::future::{Either, select};
9 9
10use super::{Config, ConfigError, Error, Info, State, UartRx, rdr, reconfigure, set_baudrate, sr}; 10use super::{
11 Config, ConfigError, Error, Info, State, UartRx, clear_interrupt_flags, rdr, reconfigure, set_baudrate, sr,
12};
11use crate::Peri; 13use crate::Peri;
12use crate::dma::ReadableRingBuffer; 14use crate::dma::ReadableRingBuffer;
13use crate::gpio::{AnyPin, SealedPin as _}; 15use crate::gpio::{AnyPin, SealedPin as _};
@@ -338,26 +340,16 @@ impl Drop for RingBufferedUartRx<'_> {
338/// For usart_v1 and usart_v2, all status flags must be handled together anyway because all flags 340/// For usart_v1 and usart_v2, all status flags must be handled together anyway because all flags
339/// are cleared by a single read to the RDR register. 341/// are cleared by a single read to the RDR register.
340fn check_idle_and_errors(r: Regs) -> Result<bool, Error> { 342fn check_idle_and_errors(r: Regs) -> Result<bool, Error> {
341 // Critical section is required so that the flags aren't set after read and before clear 343 // SAFETY: read only and we only use Rx related flags
342 let sr = critical_section::with(|_| { 344 let sr = sr(r).read();
343 // SAFETY: read only and we only use Rx related flags 345
344 let sr = sr(r).read(); 346 #[cfg(not(any(usart_v3, usart_v4)))]
345 347 unsafe {
346 #[cfg(any(usart_v3, usart_v4))] 348 // This read also clears the error and idle interrupt flags on v1 (TODO and v2?)
347 r.icr().write(|w| { 349 rdr(r).read_volatile()
348 w.set_idle(true); 350 };
349 w.set_pe(true); 351 clear_interrupt_flags(r, sr);
350 w.set_fe(true); 352
351 w.set_ne(true);
352 w.set_ore(true);
353 });
354 #[cfg(not(any(usart_v3, usart_v4)))]
355 unsafe {
356 // This read also clears the error and idle interrupt flags on v1 (TODO and v2?)
357 rdr(r).read_volatile()
358 };
359 sr
360 });
361 if sr.pe() { 353 if sr.pe() {
362 Err(Error::Parity) 354 Err(Error::Parity)
363 } else if sr.fe() { 355 } else if sr.fe() {