aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-10-29 09:31:41 +0000
committerGitHub <[email protected]>2025-10-29 09:31:41 +0000
commit07602b31f0d7dc8ae06b32197162990bb575a7a8 (patch)
treee159d0cac3e1eeb4b202786c856bdb4941f52d77
parenta0d7c087a2bd4a370d24097e022a812f7119dd78 (diff)
parent126a630075eb548a641423b1eb816ba7ad9a741e (diff)
Merge pull request #4775 from diondokter/nrf-buffered-uart-fix
[nRF] Make empty definition consistent on BufferedUarte
-rw-r--r--embassy-nrf/CHANGELOG.md1
-rw-r--r--embassy-nrf/src/buffered_uarte/v1.rs49
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
20- changed: updated to nrf-pac with nrf52/nrf53/nrf91 register layout more similar to nrf54 20- changed: updated to nrf-pac with nrf52/nrf53/nrf91 register layout more similar to nrf54
21- added: support for nrf54l peripherals: uart, gpiote, twim, twis, spim, spis, dppi, pwm, saadc 21- added: support for nrf54l peripherals: uart, gpiote, twim, twis, spim, spis, dppi, pwm, saadc
22- bugfix: Do not write to UICR from non-secure code on nrf53 22- bugfix: Do not write to UICR from non-secure code on nrf53
23- changed: `BufferedUarte::read_ready` now uses the same definition for 'empty' so following read calls will not block when true is returned
23 24
24## 0.8.0 - 2025-09-30 25## 0.8.0 - 2025-09-30
25 26
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> {
748 } 748 }
749 } 749 }
750 750
751 fn get_rxdrdy_counter(&self) -> usize {
752 let s = self.buffered_state;
753 let timer = &self.timer;
754
755 // Read the RXDRDY counter.
756 timer.cc(0).capture();
757 let mut rxdrdy = timer.cc(0).read() as usize;
758 //trace!(" rxdrdy count = {:?}", rxdrdy);
759
760 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
761 // However, it's unclear if that's instant, or there's a small window where you can
762 // still read `len()*2`.
763 // This could happen if in one clock cycle the counter is updated, and in the next the
764 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
765 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
766 // clock cycle of the PCLK16M." :shrug:
767 // So, we wrap the counter ourselves, just in case.
768 if rxdrdy > s.rx_buf.len() * 2 {
769 rxdrdy = 0;
770 }
771
772 rxdrdy
773 }
774
751 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read. 775 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
752 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 776 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
753 let data = self.fill_buf().await?; 777 let data = self.fill_buf().await?;
@@ -762,7 +786,7 @@ impl<'d> BufferedUarteRx<'d> {
762 let r = self.r; 786 let r = self.r;
763 let s = self.buffered_state; 787 let s = self.buffered_state;
764 let ss = self.state; 788 let ss = self.state;
765 let timer = &self.timer; 789
766 poll_fn(move |cx| { 790 poll_fn(move |cx| {
767 compiler_fence(Ordering::SeqCst); 791 compiler_fence(Ordering::SeqCst);
768 //trace!("poll_read"); 792 //trace!("poll_read");
@@ -771,22 +795,7 @@ impl<'d> BufferedUarteRx<'d> {
771 return Poll::Ready(Err(Error::Overrun)); 795 return Poll::Ready(Err(Error::Overrun));
772 } 796 }
773 797
774 // Read the RXDRDY counter. 798 let mut end = self.get_rxdrdy_counter();
775 timer.cc(0).capture();
776 let mut end = timer.cc(0).read() as usize;
777 //trace!(" rxdrdy count = {:?}", end);
778
779 // We've set a compare channel that resets the counter to 0 when it reaches `len*2`.
780 // However, it's unclear if that's instant, or there's a small window where you can
781 // still read `len()*2`.
782 // This could happen if in one clock cycle the counter is updated, and in the next the
783 // clear takes effect. The docs are very sparse, they just say "Task delays: After TIMER
784 // is started, the CLEAR, COUNT, and STOP tasks are guaranteed to take effect within one
785 // clock cycle of the PCLK16M." :shrug:
786 // So, we wrap the counter ourselves, just in case.
787 if end > s.rx_buf.len() * 2 {
788 end = 0
789 }
790 799
791 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()` 800 // This logic mirrors `atomic_ring_buffer::Reader::pop_buf()`
792 let mut start = s.rx_buf.start.load(Ordering::Relaxed); 801 let mut start = s.rx_buf.start.load(Ordering::Relaxed);
@@ -832,7 +841,11 @@ impl<'d> BufferedUarteRx<'d> {
832 if state.rx_overrun.swap(false, Ordering::Acquire) { 841 if state.rx_overrun.swap(false, Ordering::Acquire) {
833 return Err(Error::Overrun); 842 return Err(Error::Overrun);
834 } 843 }
835 Ok(!state.rx_buf.is_empty()) 844
845 let start = state.rx_buf.start.load(Ordering::Relaxed);
846 let end = self.get_rxdrdy_counter();
847
848 Ok(start != end)
836 } 849 }
837} 850}
838 851