Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: BufferedUartRx embedded_hal_nb::serial::Read impl #3915

Merged
merged 3 commits into from
Feb 24, 2025
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions embassy-stm32/src/usart/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,26 +908,16 @@ impl<'d> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d> {
type Error = Error;

fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = self.info.regs;
unsafe {
let sr = sr(r).read();
if sr.pe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Parity))
} else if sr.fe() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Framing))
} else if sr.ne() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Noise))
} else if sr.ore() {
rdr(r).read_volatile();
Err(nb::Error::Other(Error::Overrun))
} else if sr.rxne() {
Ok(rdr(r).read_volatile())
} else {
Err(nb::Error::WouldBlock)
let state = self.state;
let mut rx_reader = unsafe { state.rx_buf.reader() };

if let Some(data) = rx_reader.pop_one() {
Ok(data)
} else {
if state.rx_buf.is_full() {
self.info.interrupt.pend();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why pend if full? this would create an interrupt storm.

it should be the other way: in the Ok branch, if the ringbuffer was full and thanks to this read it stops being full we have to pend the irq to kickstart reading bytes again.

let full = state.rx_buf.is_full();
rx_reader.pop_done(amt);
if full {
self.info.interrupt.pend();
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right, I fixed it. The rx_buf full check is done before marking the byte as read.

}
Err(nb::Error::WouldBlock)
}
}
}
Expand Down