From 84b1753b4ed87ef65c5df77b2de73f8d0e6b3642 Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Sat, 24 Aug 2024 17:51:33 +0000 Subject: [PATCH] Port UART updates to rp235x-hal The updates from #798, #837 and #838 were only applied to rp2040-hal. This patch ports them to rp235x-hal. --- rp235x-hal/src/uart/peripheral.rs | 40 ++++++++++++++++++++++++++++++- rp235x-hal/src/uart/reader.rs | 23 +++++++++++++++++- rp235x-hal/src/uart/writer.rs | 10 ++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/rp235x-hal/src/uart/peripheral.rs b/rp235x-hal/src/uart/peripheral.rs index 89fb74000..b0783084c 100644 --- a/rp235x-hal/src/uart/peripheral.rs +++ b/rp235x-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, }) } } @@ -250,6 +254,7 @@ impl> UartPeripheral { device: reader.device, _state: Enabled, pins: reader.pins, + read_error: reader.read_error, } } } @@ -260,6 +265,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 }; @@ -278,6 +284,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 }; @@ -469,9 +476,32 @@ 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::ReadReady + for UartPeripheral +{ + fn read_ready(&mut self) -> Result { + Ok(self.uart_is_readable()) } } + impl> embedded_io::Write for UartPeripheral { fn write(&mut self, buf: &[u8]) -> Result { self.write_full_blocking(buf); @@ -482,3 +512,11 @@ impl> embedded_io::Write for UartPeripheral Ok(()) } } + +impl> embedded_io::WriteReady + for UartPeripheral +{ + fn write_ready(&mut self) -> Result { + Ok(self.uart_is_writable()) + } +} diff --git a/rp235x-hal/src/uart/reader.rs b/rp235x-hal/src/uart/reader.rs index 6126a4fcd..8df37e13c 100644 --- a/rp235x-hal/src/uart/reader.rs +++ b/rp235x-hal/src/uart/reader.rs @@ -190,6 +190,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 { @@ -228,7 +229,27 @@ 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), + } + } +} + +impl> embedded_io::ReadReady for Reader { + fn read_ready(&mut self) -> Result { + Ok(is_readable(&self.device)) } } diff --git a/rp235x-hal/src/uart/writer.rs b/rp235x-hal/src/uart/writer.rs index 941fc9398..ac9c4779c 100644 --- a/rp235x-hal/src/uart/writer.rs +++ b/rp235x-hal/src/uart/writer.rs @@ -215,8 +215,8 @@ impl> embedded_io::ErrorType for Writer> embedded_io::Write for Writer { fn write(&mut self, buf: &[u8]) -> Result { - self.write_full_blocking(buf); - Ok(buf.len()) + let remaining = nb::block!(write_raw(&self.device, buf)).unwrap(); // Infallible + Ok(buf.len() - remaining.len()) } fn flush(&mut self) -> Result<(), Self::Error> { nb::block!(transmit_flushed(&self.device)).unwrap(); // Infallible @@ -224,6 +224,12 @@ impl> embedded_io::Write for Writer { } } +impl> embedded_io::WriteReady for Writer { + fn write_ready(&mut self) -> Result { + Ok(uart_is_writable(&self.device)) + } +} + impl> Write02 for Writer { type Error = Infallible;