diff --git a/rp2040-hal/src/uart/peripheral.rs b/rp2040-hal/src/uart/peripheral.rs index 11a6add7a..20b5f555a 100644 --- a/rp2040-hal/src/uart/peripheral.rs +++ b/rp2040-hal/src/uart/peripheral.rs @@ -21,6 +21,7 @@ pub struct UartPeripheral> { device: D, _state: S, pins: P, + read_error: Option, } impl> UartPeripheral { @@ -29,6 +30,7 @@ impl> UartPeripheral { device: self.device, pins: self.pins, _state: state, + read_error: None, } } @@ -48,6 +50,7 @@ impl> UartPeripheral { device, _state: Disabled, pins, + read_error: None, } } @@ -88,6 +91,7 @@ impl> UartPeripheral { device, pins, _state: Enabled, + read_error: None, }) } } @@ -247,6 +251,7 @@ impl> UartPeripheral { device: reader.device, _state: Enabled, pins: reader.pins, + read_error: reader.read_error, } } } @@ -257,6 +262,7 @@ impl> UartPeripheral { let reader = Reader { device: self.device, pins: self.pins, + read_error: self.read_error, }; // Safety: reader and writer will never write to the same address let device_copy = unsafe { Peripherals::steal().UART0 }; @@ -275,6 +281,7 @@ impl> UartPeripheral { let reader = Reader { device: self.device, pins: self.pins, + read_error: self.read_error, }; // Safety: reader and writer will never write to the same address let device_copy = unsafe { Peripherals::steal().UART1 }; @@ -466,7 +473,21 @@ impl> embedded_io::ErrorType } impl> embedded_io::Read for UartPeripheral { fn read(&mut self, buf: &mut [u8]) -> Result { - nb::block!(self.read_raw(buf)).map_err(|e| e.err_type) + // If the last read stored an error, report it now + if let Some(err) = self.read_error.take() { + return Err(err); + } + match nb::block!(self.read_raw(buf)) { + Ok(bytes_read) => Ok(bytes_read), + Err(err) if !err.discarded.is_empty() => { + // If an error was reported but some bytes were already read, + // return the data now and store the error for the next + // invocation. + self.read_error = Some(err.err_type); + Ok(err.discarded.len()) + } + Err(err) => Err(err.err_type), + } } } impl> embedded_io::Write for UartPeripheral { diff --git a/rp2040-hal/src/uart/reader.rs b/rp2040-hal/src/uart/reader.rs index 35c8f931c..11829f90d 100644 --- a/rp2040-hal/src/uart/reader.rs +++ b/rp2040-hal/src/uart/reader.rs @@ -187,6 +187,7 @@ pub(crate) fn read_full_blocking( pub struct Reader> { pub(super) device: D, pub(super) pins: P, + pub(super) read_error: Option, } impl> Reader { @@ -225,7 +226,21 @@ impl> embedded_io::ErrorType for Reader> embedded_io::Read for Reader { fn read(&mut self, buf: &mut [u8]) -> Result { - nb::block!(self.read_raw(buf)).map_err(|e| e.err_type) + // If the last read stored an error, report it now + if let Some(err) = self.read_error.take() { + return Err(err); + } + match nb::block!(self.read_raw(buf)) { + Ok(bytes_read) => Ok(bytes_read), + Err(err) if !err.discarded.is_empty() => { + // If an error was reported but some bytes were already read, + // return the data now and store the error for the next + // invocation. + self.read_error = Some(err.err_type); + Ok(err.discarded.len()) + } + Err(err) => Err(err.err_type), + } } }