From 126a630075eb548a641423b1eb816ba7ad9a741e Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Wed, 22 Oct 2025 15:28:16 +0200 Subject: Make empty definition consistent --- embassy-nrf/CHANGELOG.md | 1 + embassy-nrf/src/buffered_uarte/v1.rs | 49 +++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md index 94a5f4e4a..3aa8446a1 100644 --- a/embassy-nrf/CHANGELOG.md +++ b/embassy-nrf/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - changed: updated to nrf-pac with nrf52/nrf53/nrf91 register layout more similar to nrf54 - added: support for nrf54l peripherals: uart, gpiote, twim, twis, spim, spis, dppi, pwm, saadc - bugfix: Do not write to UICR from non-secure code on nrf53 +- changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned ## 0.8.0 - 2025-09-30 diff --git a/embassy-nrf/src/buffered_uarte/v1.rs b/embassy-nrf/src/buffered_uarte/v1.rs index 07de22717..ec360f7d0 100644 --- a/embassy-nrf/src/buffered_uarte/v1.rs +++ b/embassy-nrf/src/buffered_uarte/v1.rs @@ -748,6 +748,30 @@ impl<'d> BufferedUarteRx<'d> { } } + fn get_rxdrdy_counter(&self) -> usize { + let s = self.buffered_state; + let timer = &self.timer; + + // Read the RXDRDY counter. + timer.cc(0).capture(); + let mut rxdrdy = timer.cc(0).read() as usize; + //trace!(" rxdrdy count = {:?}", rxdrdy); + + // We've set a compare channel that resets the counter to 0 when it reaches `len*2`. + // However, it's unclear if that's instant, or there's a small window where you can + // still read `len()*2`. + // This could happen if in one clock cycle the counter is updated, and in the next the + // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER + // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one + // clock cycle of the PCLK16M." :shrug: + // So, we wrap the counter ourselves, just in case. + if rxdrdy > s.rx_buf.len() * 2 { + rxdrdy = 0; + } + + rxdrdy + } + /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. pub async fn read(&mut self, buf: &mut [u8]) -> Result { let data = self.fill_buf().await?; @@ -762,7 +786,7 @@ impl<'d> BufferedUarteRx<'d> { let r = self.r; let s = self.buffered_state; let ss = self.state; - let timer = &self.timer; + poll_fn(move |cx| { compiler_fence(Ordering::SeqCst); //trace!("poll_read"); @@ -771,22 +795,7 @@ impl<'d> BufferedUarteRx<'d> { return Poll::Ready(Err(Error::Overrun)); } - // Read the RXDRDY counter. - timer.cc(0).capture(); - let mut end = timer.cc(0).read() as usize; - //trace!(" rxdrdy count = {:?}", end); - - // We've set a compare channel that resets the counter to 0 when it reaches `len*2`. - // However, it's unclear if that's instant, or there's a small window where you can - // still read `len()*2`. - // This could happen if in one clock cycle the counter is updated, and in the next the - // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER - // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one - // clock cycle of the PCLK16M." :shrug: - // So, we wrap the counter ourselves, just in case. - if end > s.rx_buf.len() * 2 { - end = 0 - } + let mut end = self.get_rxdrdy_counter(); // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()` let mut start = s.rx_buf.start.load(Ordering::Relaxed); @@ -832,7 +841,11 @@ impl<'d> BufferedUarteRx<'d> { if state.rx_overrun.swap(false, Ordering::Acquire) { return Err(Error::Overrun); } - Ok(!state.rx_buf.is_empty()) + + let start = state.rx_buf.start.load(Ordering::Relaxed); + let end = self.get_rxdrdy_counter(); + + Ok(start != end) } } -- cgit