diff options
| -rw-r--r-- | embassy-nrf/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | 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 | |||
| 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 | ||
