From 02f9d39e85a701ee5d92fca2d2b4b4ac3d2719b9 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Thu, 2 Jul 2026 17:47:03 -0300 Subject: [PATCH 01/15] Initial commit --- embassy-rp/src/uart/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index ca9ed15df2..b5b04025d1 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -336,6 +336,12 @@ impl<'d, M: Mode> UartRx<'d, M> { } Ok(buffer.len()) } + // Returns True if the UART FIFO is not empty + fn has_rx_data(&mut self) -> bool + { + !self.info.regs.uartfr().read().rxfe() + } + } impl<'d, M: Mode> Drop for UartRx<'d, M> { From f9a82b1f228908cd1ff353ec3bdb93950cbc2d8e Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Thu, 2 Jul 2026 17:53:19 -0300 Subject: [PATCH 02/15] Fix formatting --- embassy-rp/src/uart/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index b5b04025d1..be2caf24c3 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -337,11 +337,9 @@ impl<'d, M: Mode> UartRx<'d, M> { Ok(buffer.len()) } // Returns True if the UART FIFO is not empty - fn has_rx_data(&mut self) -> bool - { - !self.info.regs.uartfr().read().rxfe() + fn has_rx_data(&mut self) -> bool { + !self.info.regs.uartfr().read().rxfe() } - } impl<'d, M: Mode> Drop for UartRx<'d, M> { From d3afd103642b497874a9ddc034ecac02a43d0044 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Thu, 2 Jul 2026 22:19:37 -0300 Subject: [PATCH 03/15] Add the read until function to Uart on embassy rp --- embassy-rp/src/uart/mod.rs | 40 +++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index be2caf24c3..32f03c2c64 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -7,7 +7,7 @@ use core::task::Poll; use embassy_futures::select::{Either, select}; use embassy_hal_internal::{Peri, PeripheralType}; use embassy_sync::waitqueue::AtomicWaker; -use embassy_time::{Delay, Timer}; +use embassy_time::{Delay, Instant, Timer}; use pac::uart::regs::Uartris; use crate::clocks::clk_peri_freq; @@ -116,6 +116,10 @@ pub enum Error { Parity, /// Triggered when the received character didn't have a valid stop bit. Framing, + /// Triggered when the timeout is hit. + Timeout, + /// Triggered when buffer passed by the buffer is smaller then the byte amount received + BufferOverflow, } impl core::fmt::Display for Error { @@ -336,10 +340,38 @@ impl<'d, M: Mode> UartRx<'d, M> { } Ok(buffer.len()) } - // Returns True if the UART FIFO is not empty - fn has_rx_data(&mut self) -> bool { + /// Returns True if the UART FIFO is not empty + pub fn has_rx_data(&mut self) -> bool { !self.info.regs.uartfr().read().rxfe() } + /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. + pub fn read_until(&mut self, buffer: &mut [u8], target_byte: u8, timeout_micros: u64) -> Result { + let r = self.info.regs; + let start_time = Instant::now(); + let mut bytes_copied = 0; + + loop { + while r.uartfr().read().rxfe() { + if start_time.elapsed().as_micros() > timeout_micros { + return Err(Error::Timeout); + } + } + + let byte = r.uartdr().read().data(); + + if bytes_copied >= buffer.len() { + return Err(Error::BufferOverflow); + } + + buffer[bytes_copied] = byte; + bytes_copied += 1; + + if byte == target_byte { + return Ok(bytes_copied); + } + } + } } impl<'d, M: Mode> Drop for UartRx<'d, M> { @@ -1249,6 +1281,8 @@ impl embedded_hal_nb::serial::Error for Error { Self::Break => embedded_hal_nb::serial::ErrorKind::Other, Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity, + Self::Timeout => embedded_hal_nb::serial::ErrorKind::Other, + Self::BufferOverflow => embedded_hal_nb::serial::ErrorKind::Other, } } } From d83deef43b74b951aed477305ff700de7f4b3481 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 16:12:20 -0300 Subject: [PATCH 04/15] Improve method name and fix some code errors --- embassy-rp/src/uart/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 32f03c2c64..61ae420049 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -346,7 +346,7 @@ impl<'d, M: Mode> UartRx<'d, M> { } /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. - pub fn read_until(&mut self, buffer: &mut [u8], target_byte: u8, timeout_micros: u64) -> Result { + pub fn read_until_character_with_timeout(&mut self, buffer: &mut [u8], target_byte: &[u8;1], timeout_micros: u64) -> Result { let r = self.info.regs; let start_time = Instant::now(); let mut bytes_copied = 0; @@ -367,7 +367,7 @@ impl<'d, M: Mode> UartRx<'d, M> { buffer[bytes_copied] = byte; bytes_copied += 1; - if byte == target_byte { + if byte == target_byte[0] { return Ok(bytes_copied); } } From 3d2b7c269f2beddca5ce070f791e50f08aada47b Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 16:12:45 -0300 Subject: [PATCH 05/15] Fix formatting --- embassy-rp/src/uart/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 61ae420049..bcaf7ed478 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -346,7 +346,12 @@ impl<'d, M: Mode> UartRx<'d, M> { } /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. - pub fn read_until_character_with_timeout(&mut self, buffer: &mut [u8], target_byte: &[u8;1], timeout_micros: u64) -> Result { + pub fn read_until_character_with_timeout( + &mut self, + buffer: &mut [u8], + target_byte: &[u8; 1], + timeout_micros: u64, + ) -> Result { let r = self.info.regs; let start_time = Instant::now(); let mut bytes_copied = 0; From bebede5a3d6b7ff1e8245f4a8dbca5dcb74e198d Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 18:57:20 -0300 Subject: [PATCH 06/15] Add methods to Uart struct --- embassy-rp/src/uart/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index bcaf7ed478..0afd952c74 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -349,7 +349,7 @@ impl<'d, M: Mode> UartRx<'d, M> { pub fn read_until_character_with_timeout( &mut self, buffer: &mut [u8], - target_byte: &[u8; 1], + target_byte: [u8; 1], timeout_micros: u64, ) -> Result { let r = self.info.regs; @@ -1145,6 +1145,21 @@ impl<'d, M: Mode> Uart<'d, M> { self.tx.send_break(bits).await } + /// Returns True if the UART FIFO is not empty + pub fn has_rx_data(&mut self) -> bool { + self.rx.has_rx_data() + } + /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. + pub fn read_until_character_with_timeout( + &mut self, + buffer: &mut [u8], + target_byte: [u8; 1], + timeout_micros: u64, + ) -> Result { + self.rx + .read_until_character_with_timeout(buffer, target_byte, timeout_micros) + } /// Split the Uart into a transmitter and receiver, which is particularly /// useful when having two tasks correlating to transmitting and receiving. pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { From 67a75cdaa51a698535040adb3b13314e55bedbb6 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 19:54:59 -0300 Subject: [PATCH 07/15] Change function name to be more specific --- embassy-rp/src/uart/mod.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 0afd952c74..d1772b094b 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -345,8 +345,8 @@ impl<'d, M: Mode> UartRx<'d, M> { !self.info.regs.uartfr().read().rxfe() } /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned - /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. - pub fn read_until_character_with_timeout( + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. + pub fn blocking_read_until( &mut self, buffer: &mut [u8], target_byte: [u8; 1], @@ -1150,15 +1150,14 @@ impl<'d, M: Mode> Uart<'d, M> { self.rx.has_rx_data() } /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned - /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned. - pub fn read_until_character_with_timeout( + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. + pub fn blocking_read_until( &mut self, buffer: &mut [u8], target_byte: [u8; 1], timeout_micros: u64, ) -> Result { - self.rx - .read_until_character_with_timeout(buffer, target_byte, timeout_micros) + self.rx.blocking_read_until(buffer, target_byte, timeout_micros) } /// Split the Uart into a transmitter and receiver, which is particularly /// useful when having two tasks correlating to transmitting and receiving. From 248840c07abd115b1f4f229476a75a997e305dc3 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 21:37:10 -0300 Subject: [PATCH 08/15] Fix location of blocking call and add tests --- embassy-rp/src/uart/mod.rs | 28 +++++++++---------- tests/rp/src/bin/uart.rs | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index d1772b094b..588639e01b 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -839,6 +839,20 @@ impl<'d> Uart<'d, Blocking> { }, } } + /// Returns True if the UART FIFO is not empty + pub fn has_rx_data(&mut self) -> bool { + self.rx.has_rx_data() + } + /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. + pub fn blocking_read_until( + &mut self, + buffer: &mut [u8], + target_byte: [u8; 1], + timeout_micros: u64, + ) -> Result { + self.rx.blocking_read_until(buffer, target_byte, timeout_micros) + } } impl<'d> Uart<'d, Async> { @@ -1145,20 +1159,6 @@ impl<'d, M: Mode> Uart<'d, M> { self.tx.send_break(bits).await } - /// Returns True if the UART FIFO is not empty - pub fn has_rx_data(&mut self) -> bool { - self.rx.has_rx_data() - } - /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned - /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. - pub fn blocking_read_until( - &mut self, - buffer: &mut [u8], - target_byte: [u8; 1], - timeout_micros: u64, - ) -> Result { - self.rx.blocking_read_until(buffer, target_byte, timeout_micros) - } /// Split the Uart into a transmitter and receiver, which is particularly /// useful when having two tasks correlating to transmitting and receiving. pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index 80230f3fe5..94b0c84bfd 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs @@ -167,6 +167,63 @@ async fn main(_spawner: Spawner) { assert_eq!(read1(&mut uart).unwrap(), [5]); } + info!("test has_rx_data"); + { + let config = Config::default(); + let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); + + // No byte was sent to the FIFO should return False + assert_eq!(!uart.has_rx_data(),false); + + // We can't send too many bytes, they have to fit in the FIFO. + // This is because we aren't sending+receiving at the same time. + + let data = [0xC0, 0xDE]; + uart.blocking_write(&data).unwrap(); + assert_eq!(uart.has_rx_data(), true); + } + + info!("Test blocking_read_until "); + { + + let config = Config::default(); + let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); + let mut buf = [0u8; 4]; + + let data = [0xC0, 0xDE, 0xAA, 0xBB]; + + uart.blocking_write(&data).unwrap(); + assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap(),3); + assert_eq!(buf,[0xC0, 0xDE, 0xAA, 0x00]) + + } + info!("Test blocking_read_until buffer overflow"); + { + let config = Config::default(); + + let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); + let mut buf = [0u8; 4]; + + let data = [0xC0, 0xDE, 0xAA, 0xBB]; + + uart.blocking_write(&data).unwrap(); + assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap_err(),Error::BufferOverflow); + + } + info!("Test blocking_read_until timeout"); + { + let config = Config::default(); + + let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); + let mut buf = [0u8; 4]; + + let data = [0xC0, 0xDE, 0xAA, 0xBB]; + + uart.blocking_write(&data).unwrap(); + assert_eq!(uart.blocking_read_until(&mut buf, [0x00], 1000).unwrap_err(),Error::Timeout); + assert_eq!(buf, data) + + } info!("Test OK"); cortex_m::asm::bkpt(); } From e50bbc1615ac765060fa6dda116075a4081ff4bf Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Fri, 3 Jul 2026 21:45:42 -0300 Subject: [PATCH 09/15] Fix formatting --- tests/rp/src/bin/uart.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index 94b0c84bfd..336f603d5c 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs @@ -173,7 +173,7 @@ async fn main(_spawner: Spawner) { let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); // No byte was sent to the FIFO should return False - assert_eq!(!uart.has_rx_data(),false); + assert_eq!(!uart.has_rx_data(), false); // We can't send too many bytes, they have to fit in the FIFO. // This is because we aren't sending+receiving at the same time. @@ -185,17 +185,15 @@ async fn main(_spawner: Spawner) { info!("Test blocking_read_until "); { - let config = Config::default(); let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); let mut buf = [0u8; 4]; let data = [0xC0, 0xDE, 0xAA, 0xBB]; - - uart.blocking_write(&data).unwrap(); - assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap(),3); - assert_eq!(buf,[0xC0, 0xDE, 0xAA, 0x00]) + uart.blocking_write(&data).unwrap(); + assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap(), 3); + assert_eq!(buf, [0xC0, 0xDE, 0xAA, 0x00]) } info!("Test blocking_read_until buffer overflow"); { @@ -205,10 +203,12 @@ async fn main(_spawner: Spawner) { let mut buf = [0u8; 4]; let data = [0xC0, 0xDE, 0xAA, 0xBB]; - - uart.blocking_write(&data).unwrap(); - assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap_err(),Error::BufferOverflow); + uart.blocking_write(&data).unwrap(); + assert_eq!( + uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap_err(), + Error::BufferOverflow + ); } info!("Test blocking_read_until timeout"); { @@ -218,11 +218,13 @@ async fn main(_spawner: Spawner) { let mut buf = [0u8; 4]; let data = [0xC0, 0xDE, 0xAA, 0xBB]; - + uart.blocking_write(&data).unwrap(); - assert_eq!(uart.blocking_read_until(&mut buf, [0x00], 1000).unwrap_err(),Error::Timeout); + assert_eq!( + uart.blocking_read_until(&mut buf, [0x00], 1000).unwrap_err(), + Error::Timeout + ); assert_eq!(buf, data) - } info!("Test OK"); cortex_m::asm::bkpt(); From b15bdaf42882ba39d35d9374c72219e5898a934a Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sat, 4 Jul 2026 16:13:48 -0300 Subject: [PATCH 10/15] Improve funtion call, change tests and add an example --- embassy-rp/src/uart/mod.rs | 14 +++---- .../rp/src/bin/uart_blocking_read_until.rs | 39 +++++++++++++++++++ tests/rp/src/bin/uart.rs | 12 +++--- 3 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 examples/rp/src/bin/uart_blocking_read_until.rs diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 588639e01b..67c4f96baf 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -117,8 +117,8 @@ pub enum Error { /// Triggered when the received character didn't have a valid stop bit. Framing, /// Triggered when the timeout is hit. - Timeout, - /// Triggered when buffer passed by the buffer is smaller then the byte amount received + Timeout(usize), + /// Triggered when buffer passed by the user is smaller then the byte amount received BufferOverflow, } @@ -349,7 +349,7 @@ impl<'d, M: Mode> UartRx<'d, M> { pub fn blocking_read_until( &mut self, buffer: &mut [u8], - target_byte: [u8; 1], + target_byte: u8, timeout_micros: u64, ) -> Result { let r = self.info.regs; @@ -359,7 +359,7 @@ impl<'d, M: Mode> UartRx<'d, M> { loop { while r.uartfr().read().rxfe() { if start_time.elapsed().as_micros() > timeout_micros { - return Err(Error::Timeout); + return Err(Error::Timeout(bytes_copied)); } } @@ -372,7 +372,7 @@ impl<'d, M: Mode> UartRx<'d, M> { buffer[bytes_copied] = byte; bytes_copied += 1; - if byte == target_byte[0] { + if byte == target_byte { return Ok(bytes_copied); } } @@ -848,7 +848,7 @@ impl<'d> Uart<'d, Blocking> { pub fn blocking_read_until( &mut self, buffer: &mut [u8], - target_byte: [u8; 1], + target_byte: u8, timeout_micros: u64, ) -> Result { self.rx.blocking_read_until(buffer, target_byte, timeout_micros) @@ -1300,7 +1300,7 @@ impl embedded_hal_nb::serial::Error for Error { Self::Break => embedded_hal_nb::serial::ErrorKind::Other, Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity, - Self::Timeout => embedded_hal_nb::serial::ErrorKind::Other, + Self::Timeout(_) => embedded_hal_nb::serial::ErrorKind::Other, Self::BufferOverflow => embedded_hal_nb::serial::ErrorKind::Other, } } diff --git a/examples/rp/src/bin/uart_blocking_read_until.rs b/examples/rp/src/bin/uart_blocking_read_until.rs new file mode 100644 index 0000000000..ae4d5d2d07 --- /dev/null +++ b/examples/rp/src/bin/uart_blocking_read_until.rs @@ -0,0 +1,39 @@ +//! UART read until example for RP2040 + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use embassy_executor::Spawner; +use embassy_rp::uart; +use panic_probe as _; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let config = uart::Config::default(); + let mut uart = uart::Uart::new_blocking( + p.UART0, p.PIN_0, // TX + p.PIN_1, // RX + config, + ); + let mut buf = [0u8; 100]; + loop { + match uart.blocking_read_until(&mut buf, b'\r', 5_000_000) { + Ok(n) => { + defmt::info!("Received {} bytes", n); + uart.blocking_write(&buf[..n]).unwrap(); + } + Err(embassy_rp::uart::Error::Timeout(n)) => { + defmt::warn!("Timeout after {} bytes", n); + uart.blocking_write(&buf[..n]).unwrap(); + } + Err(embassy_rp::uart::Error::BufferOverflow) => { + defmt::warn!("Buffer overflow"); + } + Err(e) => { + defmt::error!("UART error: {:?}", e); + } + } + } +} diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index 336f603d5c..efa78ee5a6 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs @@ -192,7 +192,7 @@ async fn main(_spawner: Spawner) { let data = [0xC0, 0xDE, 0xAA, 0xBB]; uart.blocking_write(&data).unwrap(); - assert_eq!(uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap(), 3); + assert_eq!(uart.blocking_read_until(&mut buf, 0xAA, 10_000_000).unwrap(), 3); assert_eq!(buf, [0xC0, 0xDE, 0xAA, 0x00]) } info!("Test blocking_read_until buffer overflow"); @@ -206,7 +206,7 @@ async fn main(_spawner: Spawner) { uart.blocking_write(&data).unwrap(); assert_eq!( - uart.blocking_read_until(&mut buf, [0xAA], 10_000_000).unwrap_err(), + uart.blocking_read_until(&mut buf, 0xAA, 10_000_000).unwrap_err(), Error::BufferOverflow ); } @@ -220,10 +220,10 @@ async fn main(_spawner: Spawner) { let data = [0xC0, 0xDE, 0xAA, 0xBB]; uart.blocking_write(&data).unwrap(); - assert_eq!( - uart.blocking_read_until(&mut buf, [0x00], 1000).unwrap_err(), - Error::Timeout - ); + assert!(matches!( + uart.blocking_read_until(&mut buf, 0x00, 1000), + Err(Error::Timeout(4)) + )); assert_eq!(buf, data) } info!("Test OK"); From b05820ec1ccdb8557500a3ea1d9f6c60e555ad38 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sat, 4 Jul 2026 16:18:10 -0300 Subject: [PATCH 11/15] fix formatting --- examples/rp/src/bin/uart_blocking_read_until.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/rp/src/bin/uart_blocking_read_until.rs b/examples/rp/src/bin/uart_blocking_read_until.rs index ae4d5d2d07..01800c733d 100644 --- a/examples/rp/src/bin/uart_blocking_read_until.rs +++ b/examples/rp/src/bin/uart_blocking_read_until.rs @@ -3,10 +3,9 @@ #![no_std] #![no_main] -use defmt_rtt as _; use embassy_executor::Spawner; use embassy_rp::uart; -use panic_probe as _; +use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { From 0c36bbcfc864ab17f66095b39ea74d31f9da2970 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sat, 4 Jul 2026 16:43:24 -0300 Subject: [PATCH 12/15] Fix asserter call on test --- tests/rp/src/bin/uart.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index efa78ee5a6..172bbaa8f5 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs @@ -220,7 +220,7 @@ async fn main(_spawner: Spawner) { let data = [0xC0, 0xDE, 0xAA, 0xBB]; uart.blocking_write(&data).unwrap(); - assert!(matches!( + defmt::assert!(matches!( uart.blocking_read_until(&mut buf, 0x00, 1000), Err(Error::Timeout(4)) )); From c7827e21822b3f326c04bc585c286f60a481b5e3 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sat, 4 Jul 2026 20:23:17 -0300 Subject: [PATCH 13/15] Fix tests improve documentation --- embassy-rp/src/uart/mod.rs | 13 ++++---- tests/rp/src/bin/uart.rs | 65 +++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 67c4f96baf..5eecb25cbe 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -344,8 +344,9 @@ impl<'d, M: Mode> UartRx<'d, M> { pub fn has_rx_data(&mut self) -> bool { !self.info.regs.uartfr().read().rxfe() } - /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned - /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. + /// Returns Ok(len) if no errors occured, in case the target byte is not found on timeout Error::Timeout(len) is returned + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned + /// These method does not clean the fifo they read the fifo until the target is reached or until timeout is reached. pub fn blocking_read_until( &mut self, buffer: &mut [u8], @@ -355,8 +356,10 @@ impl<'d, M: Mode> UartRx<'d, M> { let r = self.info.regs; let start_time = Instant::now(); let mut bytes_copied = 0; - loop { + if bytes_copied >= buffer.len() { + return Err(Error::BufferOverflow); + } while r.uartfr().read().rxfe() { if start_time.elapsed().as_micros() > timeout_micros { return Err(Error::Timeout(bytes_copied)); @@ -365,10 +368,6 @@ impl<'d, M: Mode> UartRx<'d, M> { let byte = r.uartdr().read().data(); - if bytes_copied >= buffer.len() { - return Err(Error::BufferOverflow); - } - buffer[bytes_copied] = byte; bytes_copied += 1; diff --git a/tests/rp/src/bin/uart.rs b/tests/rp/src/bin/uart.rs index 172bbaa8f5..493022363d 100644 --- a/tests/rp/src/bin/uart.rs +++ b/tests/rp/src/bin/uart.rs @@ -173,14 +173,16 @@ async fn main(_spawner: Spawner) { let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); // No byte was sent to the FIFO should return False - assert_eq!(!uart.has_rx_data(), false); + assert_eq!(uart.has_rx_data(), false); // We can't send too many bytes, they have to fit in the FIFO. // This is because we aren't sending+receiving at the same time. - - let data = [0xC0, 0xDE]; + let data = [0xC0]; uart.blocking_write(&data).unwrap(); + while uart.busy() {} assert_eq!(uart.has_rx_data(), true); + // Cleaning fifo for the next test + read::<1>(&mut uart).unwrap(); } info!("Test blocking_read_until "); @@ -193,38 +195,65 @@ async fn main(_spawner: Spawner) { uart.blocking_write(&data).unwrap(); assert_eq!(uart.blocking_read_until(&mut buf, 0xAA, 10_000_000).unwrap(), 3); - assert_eq!(buf, [0xC0, 0xDE, 0xAA, 0x00]) + assert_eq!(buf, [0xC0, 0xDE, 0xAA, 0x00]); + //Cleaning fifo for the next test + read::<1>(&mut uart).unwrap(); } - info!("Test blocking_read_until buffer overflow"); + info!("Test blocking_read_until buffer overflow buffer smaller than data"); { let config = Config::default(); let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); - let mut buf = [0u8; 4]; + let mut buf = [0u8; 1]; - let data = [0xC0, 0xDE, 0xAA, 0xBB]; + let data = [0xC0, 0xDE, 0xAA, 0xBB, 0xDD]; uart.blocking_write(&data).unwrap(); - assert_eq!( - uart.blocking_read_until(&mut buf, 0xAA, 10_000_000).unwrap_err(), - Error::BufferOverflow - ); + match uart.blocking_read_until(&mut buf, 0x00, 10_000_000) { + Ok(n) => defmt::panic!("Expected BufferOverflow, got Ok({})", n), + Err(e) => { + assert_eq!(e, Error::BufferOverflow); + } + } + //Cleaning fifo for the next test + read::<4>(&mut uart).unwrap(); } - info!("Test blocking_read_until timeout"); + info!("Test blocking_read_until buffer overflow buffer same size"); { let config = Config::default(); let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); - let mut buf = [0u8; 4]; + let mut buf = [0u8; 5]; + + let data = [0xC0, 0xDE, 0xAA, 0xBB, 0xDD]; + + uart.blocking_write(&data).unwrap(); + match uart.blocking_read_until(&mut buf, 0x00, 10_000_000) { + Ok(n) => defmt::panic!("Expected BufferOverflow, got Ok({})", n), + Err(e) => { + assert_eq!(e, Error::BufferOverflow); + } + } + } + info!("Test blocking_read_until timeout"); + { + let config = Config::default(); + let mut uart = Uart::new_blocking(uart.reborrow(), tx.reborrow(), rx.reborrow(), config); + let mut buf = [0u8; 5]; let data = [0xC0, 0xDE, 0xAA, 0xBB]; uart.blocking_write(&data).unwrap(); - defmt::assert!(matches!( - uart.blocking_read_until(&mut buf, 0x00, 1000), - Err(Error::Timeout(4)) - )); - assert_eq!(buf, data) + match uart.blocking_read_until(&mut buf, 0x00, 1000) { + Ok(_) => defmt::panic!("Expected Timeout error"), + Err(Error::Timeout(n)) => { + defmt::assert_eq!(n, 4); + assert_eq!(buf[..4], data); + } + Err(e) => { + defmt::panic!("Expected Timeout error, got {:?}", e); + } + } } info!("Test OK"); cortex_m::asm::bkpt(); From ebc13a29e963c5fe17f86687f0688d940c7dc589 Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sat, 4 Jul 2026 20:36:09 -0300 Subject: [PATCH 14/15] Fix formatting again --- embassy-rp/src/uart/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 5eecb25cbe..a44fcfbf6f 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -344,9 +344,9 @@ impl<'d, M: Mode> UartRx<'d, M> { pub fn has_rx_data(&mut self) -> bool { !self.info.regs.uartfr().read().rxfe() } - /// Returns Ok(len) if no errors occured, in case the target byte is not found on timeout Error::Timeout(len) is returned + /// Returns Ok(len) if no errors occured, in case the target byte is not found on timeout Error::Timeout(len) is returned /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned - /// These method does not clean the fifo they read the fifo until the target is reached or until timeout is reached. + /// These method does not clean the fifo they read the fifo until the target is reached or until timeout is reached. pub fn blocking_read_until( &mut self, buffer: &mut [u8], From 571989212631bd4cd64251b35dd80c5c5c92526a Mon Sep 17 00:00:00 2001 From: Henrique Domiciano Date: Sun, 5 Jul 2026 12:33:57 -0300 Subject: [PATCH 15/15] Fix docs on Uart call --- embassy-rp/src/uart/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index a44fcfbf6f..49516b9148 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -842,8 +842,9 @@ impl<'d> Uart<'d, Blocking> { pub fn has_rx_data(&mut self) -> bool { self.rx.has_rx_data() } - /// Returns Ok(len) if no errors occured, and the bytes are passed to the buffer, in case the target byte is not found on the timeout Error::Timeout is returned - /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned in both cases all bytes sent are allocated to the buffer. + /// Returns Ok(len) if no errors occured, in case the target byte is not found on timeout Error::Timeout(len) is returned + /// if the bytes read are bigger than the size of the buffer the Error::BufferOverflow is returned + /// These method does not clean the fifo they read the fifo until the target is reached or until timeout is reached. pub fn blocking_read_until( &mut self, buffer: &mut [u8],