From 2bce28b02834a2d0fb9772c1227bc6cb3672a9c7 Mon Sep 17 00:00:00 2001 From: Finomnis Date: Mon, 4 Mar 2024 16:23:56 +0100 Subject: [PATCH 1/4] Add embedded-io 0.6 implementations for lpuart --- Cargo.toml | 4 +++ src/common/lpuart.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 25cf58bf..77c9dd02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,10 @@ version = "0.2" package = "embedded-hal" version = "1.0.0" +[dependencies.eio06] +package = "embedded-io" +version = "0.6.1" + [dependencies.rand_core] version = "0.5" default-features = false diff --git a/src/common/lpuart.rs b/src/common/lpuart.rs index 337029a2..d780d20b 100644 --- a/src/common/lpuart.rs +++ b/src/common/lpuart.rs @@ -930,6 +930,88 @@ impl eh02::blocking::serial::Write for Lpuart { } } +impl eio06::Error for ReadFlags { + fn kind(&self) -> eio06::ErrorKind { + eio06::ErrorKind::Other + } +} + +impl eio06::ErrorType for Lpuart { + type Error = ReadFlags; +} + +impl eio06::WriteReady for Lpuart { + fn write_ready(&mut self) -> Result { + Ok(self.status().contains(Status::TRANSMIT_EMPTY)) + } +} + +impl eio06::Write for Lpuart { + fn write(&mut self, buf: &[u8]) -> Result { + use eio06::WriteReady; + + // Block until we can write. + // In combination with `WriteReady` this call can be non-blocking. + while !self.write_ready()? {} + + let mut num_written = 0; + for word in buf { + self.write_byte(*word); + num_written += 1; + + if !self.write_ready()? { + break; + } + } + + Ok(num_written) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + while !self.status().contains(Status::TRANSMIT_COMPLETE) {} + + Ok(()) + } +} + +impl eio06::ReadReady for Lpuart { + fn read_ready(&mut self) -> Result { + Ok(self.status().contains(Status::RECEIVE_FULL)) + } +} + +impl eio06::Read for Lpuart { + fn read(&mut self, buf: &mut [u8]) -> Result { + use eio06::ReadReady; + + // Block until we can read. + // In combination with `ReadReady` this call can be non-blocking. + while !self.read_ready()? {} + + let mut num_read = 0; + for word in buf { + let data = self.read_data(); + self.clear_status(Status::W1C); + + if data.flags().contains(ReadFlags::RXEMPT) { + break; + } + + if data + .flags() + .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY) + { + return Err(data.flags()); + } + + *word = data.into(); + num_read += 1; + } + + Ok(num_read) + } +} + #[cfg(test)] mod tests { use super::{Baud, ReadData, ReadFlags, Status}; From b3da85300983d5dd1de3b4925f0f7f01c815af9e Mon Sep 17 00:00:00 2001 From: Finomnis Date: Fri, 8 Mar 2024 10:15:04 +0100 Subject: [PATCH 2/4] Fill/empty Fifo completely on read/write, not just until watermark --- src/common/lpuart.rs | 86 +++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/src/common/lpuart.rs b/src/common/lpuart.rs index d780d20b..d5ba58b2 100644 --- a/src/common/lpuart.rs +++ b/src/common/lpuart.rs @@ -349,6 +349,27 @@ impl Lpuart { ral::modify_reg!(ral::lpuart, self.lpuart, BAUD, RDMAE: 0); } } + + /// Attempts to write a single byte to the bus. + /// + /// Returns `false` if the fifo was already full. + fn try_write(&mut self, byte: u8) -> bool { + ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, TXOF: TXOF_1); + self.write_byte(byte); + ral::read_reg!(ral::lpuart, self.lpuart, FIFO, TXOF == TXOF_0) + } + + /// Attempts to read a single byte from the bus. + /// + /// Returns `None` if the read FIFO was empty. + fn try_read(&mut self) -> Option { + let data = self.read_data(); + if data.flags().contains(ReadFlags::RXEMPT) { + None + } else { + Some(data) + } + } } fn flush_fifo(lpuart: &Instance, direction: Direction) { @@ -946,22 +967,29 @@ impl eio06::WriteReady for Lpuart { } } +impl eio06::ReadReady for Lpuart { + fn read_ready(&mut self) -> Result { + Ok(self.status().contains(Status::RECEIVE_FULL)) + } +} + impl eio06::Write for Lpuart { fn write(&mut self, buf: &[u8]) -> Result { - use eio06::WriteReady; - - // Block until we can write. - // In combination with `WriteReady` this call can be non-blocking. - while !self.write_ready()? {} - let mut num_written = 0; for word in buf { - self.write_byte(*word); - num_written += 1; - - if !self.write_ready()? { - break; + if num_written == 0 { + // For the first word, continue trying until we send. + // This function is supposed to block until at least one word is + // sent. + while !self.try_write(*word) {} + } else { + // If we already sent at least one word, return once + // the buffer is full + if !self.try_write(*word) { + break; + } } + num_written += 1; } Ok(num_written) @@ -974,28 +1002,28 @@ impl eio06::Write for Lpuart { } } -impl eio06::ReadReady for Lpuart { - fn read_ready(&mut self) -> Result { - Ok(self.status().contains(Status::RECEIVE_FULL)) - } -} - impl eio06::Read for Lpuart { fn read(&mut self, buf: &mut [u8]) -> Result { - use eio06::ReadReady; - - // Block until we can read. - // In combination with `ReadReady` this call can be non-blocking. - while !self.read_ready()? {} - let mut num_read = 0; for word in buf { - let data = self.read_data(); - self.clear_status(Status::W1C); - - if data.flags().contains(ReadFlags::RXEMPT) { - break; - } + let data = if num_read == 0 { + // For the first word, continue querying until we receive something. + // This function is supposed to block until at least one word is + // received. + loop { + if let Some(data) = self.try_read() { + break data; + } + } + } else { + // If we already read at least one word, return once + // the buffer is empty + if let Some(data) = self.try_read() { + data + } else { + break; + } + }; if data .flags() From 5f6e78d5ade0d13bbd198342dc3c11aafdf9ea42 Mon Sep 17 00:00:00 2001 From: Finomnis Date: Fri, 8 Mar 2024 10:25:57 +0100 Subject: [PATCH 3/4] Minor rework --- src/common/lpuart.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/common/lpuart.rs b/src/common/lpuart.rs index d5ba58b2..fdb0f6bc 100644 --- a/src/common/lpuart.rs +++ b/src/common/lpuart.rs @@ -353,7 +353,7 @@ impl Lpuart { /// Attempts to write a single byte to the bus. /// /// Returns `false` if the fifo was already full. - fn try_write(&mut self, byte: u8) -> bool { + pub fn try_write(&mut self, byte: u8) -> bool { ral::modify_reg!(ral::lpuart, self.lpuart, FIFO, TXOF: TXOF_1); self.write_byte(byte); ral::read_reg!(ral::lpuart, self.lpuart, FIFO, TXOF == TXOF_0) @@ -361,13 +361,23 @@ impl Lpuart { /// Attempts to read a single byte from the bus. /// - /// Returns `None` if the read FIFO was empty. - fn try_read(&mut self) -> Option { + /// Returns: + /// - `Ok(Some(u8))` if data was read + /// - `Ok(None)` if the fifo was empty + /// - `Err(..)` if a read error happened + pub fn try_read(&mut self) -> Result, ReadFlags> { let data = self.read_data(); if data.flags().contains(ReadFlags::RXEMPT) { - None + Ok(None) } else { - Some(data) + if data + .flags() + .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY) + { + Err(data.flags()) + } else { + Ok(Some(data.into())) + } } } } @@ -1011,28 +1021,21 @@ impl eio06::Read for Lpuart { // This function is supposed to block until at least one word is // received. loop { - if let Some(data) = self.try_read() { + if let Some(data) = self.try_read()? { break data; } } } else { // If we already read at least one word, return once // the buffer is empty - if let Some(data) = self.try_read() { + if let Some(data) = self.try_read()? { data } else { break; } }; - if data - .flags() - .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY) - { - return Err(data.flags()); - } - - *word = data.into(); + *word = data; num_read += 1; } From 7f384d616d25a1e3ff3aa8983ab669f5a26b94bf Mon Sep 17 00:00:00 2001 From: Finomnis Date: Fri, 8 Mar 2024 10:30:37 +0100 Subject: [PATCH 4/4] Fix clippy warning --- src/common/lpuart.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/common/lpuart.rs b/src/common/lpuart.rs index fdb0f6bc..3dffe030 100644 --- a/src/common/lpuart.rs +++ b/src/common/lpuart.rs @@ -369,15 +369,13 @@ impl Lpuart { let data = self.read_data(); if data.flags().contains(ReadFlags::RXEMPT) { Ok(None) + } else if data + .flags() + .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY) + { + Err(data.flags()) } else { - if data - .flags() - .intersects(ReadFlags::PARITY_ERROR | ReadFlags::FRAME_ERROR | ReadFlags::NOISY) - { - Err(data.flags()) - } else { - Ok(Some(data.into())) - } + Ok(Some(data.into())) } } }