From 6aa0777f448674df0316b4e1f6a0910079757fda Mon Sep 17 00:00:00 2001 From: Anthony Rocha Date: Fri, 11 Jul 2025 12:14:28 -0700 Subject: [PATCH] feat : Add async-io feature and embedded-io-async dependency Added the async-io feature to Cargo.toml, enabling async support for UART and other modules. Added embedded-io-async as an optional dependency, activated by the async-io feature. Updated code to use feature gating for async implementations. --- Cargo.lock | 10 +++++++++ Cargo.toml | 5 +++++ src/lib.rs | 3 +++ src/uart.rs | 27 ++++++++++++++++++++++- src/uart_async.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/uart_async.rs diff --git a/Cargo.lock b/Cargo.lock index 023e974..573f244 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,6 +68,7 @@ dependencies = [ "embedded-hal 1.0.0", "embedded-hal 1.0.0-alpha.1", "embedded-io", + "embedded-io-async", "fugit", "hex-literal", "panic-halt", @@ -219,6 +220,15 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io", +] + [[package]] name = "embedded-storage" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 95fcb91..9b85b9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ test-rsa = [] test-ecdsa = [] test-hmac = [] test-hash = [] +async-io = ["embedded-io-async"] [dependencies] ast1060-pac = { git = "https://github.com/rusty1968/ast1060-pac.git", features = ["rt"] } @@ -35,3 +36,7 @@ cortex-m = { version = "0.7.5" } cortex-m-rt = { version = "0.6.5", features = ["device"] } panic-halt = "1.0.0" +[dependencies.embedded-io-async] +version = "0.6" +optional = true + diff --git a/src/lib.rs b/src/lib.rs index 83396a2..abc47f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,4 +9,7 @@ pub mod rsa; pub mod syscon; pub mod tests; pub mod uart; +#[cfg(feature = "async-io")] +pub mod uart_async; + pub mod watchdog; diff --git a/src/uart.rs b/src/uart.rs index dc5dbdf..0e12852 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -137,10 +137,16 @@ impl UartController<'_> { // Additional configurations can be added here } + /// Returns true if the Transmitter Holding Register (THR) is empty. + #[must_use] + pub fn is_thr_empty(&self) -> bool { + self.uart.uartlsr().read().thre().bit_is_set() + } + /// Sends a byte using the FIFO. pub fn send_byte_fifo(&mut self, data: u8) { // Wait until the Transmitter Holding Register (THR) is empty - while self.uart.uartlsr().read().thre().bit_is_clear() {} + while !self.is_thr_empty() {} // Write the byte to the Transmit Holding Register (THR) self.uart @@ -166,6 +172,25 @@ impl UartController<'_> { } impl<'a> UartController<'a> { + /// Reads a byte from the UART receiver buffer register (UARTRBR). + #[must_use] + pub fn read_rbr(&self) -> u8 { + self.uart.uartrbr().read().uartrbr().bits() + } + + /// Returns true if data is available in the UART receiver buffer (DR bit is set). + #[must_use] + pub fn is_data_ready(&self) -> bool { + self.uart.uartlsr().read().dr().bit_is_set() + } + + /// Writes a byte to the UART transmit holding register (THR). + pub fn write_thr(&mut self, byte: u8) { + self.uart + .uartthr() + .write(|w| unsafe { w.bits(u32::from(byte)) }); + } + // Wait until the Transmitter Holding Register (THR) is empty pub fn new(uart: Uart, delay: &'a mut dyn DelayNs) -> Self { Self { uart, delay } diff --git a/src/uart_async.rs b/src/uart_async.rs new file mode 100644 index 0000000..ddcffed --- /dev/null +++ b/src/uart_async.rs @@ -0,0 +1,55 @@ +// Licensed under the Apache-2.0 license + +use ast1060_pac::Uart; + +use crate::uart::UartController; + +use core::future::poll_fn; +use core::task::{Context, Poll}; +use embedded_io_async::{Read, Write}; + +/// Async implementation of embedded_io_async::Read for UartController. +/// +/// Reads bytes asynchronously from the UART receiver buffer. +/// Waits until data is available before reading each byte. +impl embedded_io_async::Read for UartController<'_> { + async fn read(&mut self, buf: &mut [u8]) -> Result { + let mut count = 0; + for byte in buf.iter_mut() { + poll_fn(|cx| { + if self.is_data_ready() { + *byte = self.read_rbr(); + Poll::Ready(Ok(())) + } else { + cx.waker().wake_by_ref(); + Poll::Pending + } + }) + .await?; + count += 1; + } + Ok(count) + } +} + +/// Async implementation of embedded_io_async::Write for UartController. +/// +/// Writes bytes asynchronously to the UART transmit holding register. +/// Waits until the transmitter is ready before sending each byte. +impl embedded_io_async::Write for UartController<'_> { + async fn write(&mut self, buf: &[u8]) -> Result { + for &byte in buf { + poll_fn(|cx| { + if self.is_thr_empty() { + self.write_thr(byte); + Poll::Ready(Ok(())) + } else { + cx.waker().wake_by_ref(); + Poll::Pending + } + }) + .await?; + } + Ok(buf.len()) + } +}