Add embedded_hal_nb::serial::Read impl for RingBufferedUartRx

This commit is contained in:
Tobias Naumann 2025-03-21 11:18:16 +01:00
parent fecb7a2b2b
commit 1e6192ffa5

View File

@ -133,6 +133,20 @@ impl<'d> RingBufferedUartRx<'d> {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
/// (Re-)start DMA and Uart if it is not running (has not been started yet or has failed), and
/// check for errors in status register. Error flags are cleared in `start_uart()` so they need
/// to be read first without returning yet.
fn start_dma_or_check_errors(&mut self) -> Result<(), Error> {
let r = self.info.regs;
let sr = clear_idle_flag(r);
let res = check_for_errors(sr);
if !r.cr3().read().dmar() {
self.start_uart();
}
res
}
/// Read bytes that are readily available in the ring buffer. /// Read bytes that are readily available in the ring buffer.
/// If no bytes are currently available in the buffer the call waits until the some /// If no bytes are currently available in the buffer the call waits until the some
/// bytes are available (at least one byte and at most half the buffer size) /// bytes are available (at least one byte and at most half the buffer size)
@ -142,17 +156,7 @@ impl<'d> RingBufferedUartRx<'d> {
/// Receive in the background is terminated if an error is returned. /// Receive in the background is terminated if an error is returned.
/// It must then manually be started again by calling `start()` or by re-calling `read()`. /// It must then manually be started again by calling `start()` or by re-calling `read()`.
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let r = self.info.regs; self.start_dma_or_check_errors()?;
// (Re-)start DMA and Uart if it is not running (has not been started yet or has failed),
// and check for errors in status register. Error flags are cleared in `start_uart()` so
// they need to be read first without returning yet.
let sr = clear_idle_flag(r);
let res = check_for_errors(sr);
if !r.cr3().read().dmar() {
self.start_uart();
}
res?;
loop { loop {
match self.ring_buf.read(buf) { match self.ring_buf.read(buf) {
@ -281,6 +285,29 @@ impl embedded_io_async::Read for RingBufferedUartRx<'_> {
} }
} }
impl embedded_hal_nb::serial::Read for RingBufferedUartRx<'_> {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self.start_dma_or_check_errors()?;
let mut buf = [0u8; 1];
match self.ring_buf.read(&mut buf) {
Ok((0, _)) => Err(nb::Error::WouldBlock),
Ok((len, _)) => {
assert!(len == 1);
Ok(buf[0])
}
Err(_) => {
self.stop_uart();
Err(nb::Error::Other(Error::Overrun))
}
}
}
}
impl embedded_hal_nb::serial::ErrorType for RingBufferedUartRx<'_> {
type Error = Error;
}
impl ReadReady for RingBufferedUartRx<'_> { impl ReadReady for RingBufferedUartRx<'_> {
fn read_ready(&mut self) -> Result<bool, Self::Error> { fn read_ready(&mut self) -> Result<bool, Self::Error> {
let len = self.ring_buf.len().map_err(|e| match e { let len = self.ring_buf.len().map_err(|e| match e {