aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-07-28 01:16:48 +0000
committerGitHub <[email protected]>2023-07-28 01:16:48 +0000
commit44c8db2911f0f9d82e6517e31944777454c4e459 (patch)
tree603cdf99f82170a34695ee1aeaf799efeae135be
parentbbd2563e138ce83314ea008547940428617a5798 (diff)
parent4883fdd1549e8d43290b39d72c3b311d300010ea (diff)
Merge pull request #1681 from alexferro/feature/stm32-dma-read-exact
Add a STM32/DMARingBuffer::read_exact helper
-rw-r--r--embassy-stm32/src/dma/bdma.rs44
-rw-r--r--embassy-stm32/src/dma/dma.rs44
-rw-r--r--embassy-stm32/src/dma/ringbuffer.rs18
3 files changed, 91 insertions, 15 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 5a87888b7..68c78123d 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -466,15 +466,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
466 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 466 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
467 } 467 }
468 468
469 /// Read bytes from the ring buffer 469 /// Read elements from the ring buffer
470 /// Return a tuple of the length read and the length remaining in the buffer 470 /// Return a tuple of the length read and the length remaining in the buffer
471 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 471 /// If not all of the elements were read, then there will be some elements in the buffer remaining
472 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 472 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
473 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 473 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
474 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 474 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
475 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 475 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
476 } 476 }
477 477
478 /// Read an exact number of elements from the ringbuffer.
479 ///
480 /// Returns the remaining number of elements available for immediate reading.
481 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
482 ///
483 /// Async/Wake Behavior:
484 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
485 /// and when it wraps around. This means that when called with a buffer of length 'M', when this
486 /// ring buffer was created with a buffer of size 'N':
487 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
488 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
489 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
490 use core::future::poll_fn;
491 use core::sync::atomic::compiler_fence;
492
493 let mut read_data = 0;
494 let buffer_len = buffer.len();
495
496 poll_fn(|cx| {
497 self.set_waker(cx.waker());
498
499 compiler_fence(Ordering::SeqCst);
500
501 match self.read(&mut buffer[read_data..buffer_len]) {
502 Ok((len, remaining)) => {
503 read_data += len;
504 if read_data == buffer_len {
505 Poll::Ready(Ok(remaining))
506 } else {
507 Poll::Pending
508 }
509 }
510 Err(e) => Poll::Ready(Err(e)),
511 }
512 })
513 .await
514 }
515
478 /// The capacity of the ringbuffer 516 /// The capacity of the ringbuffer
479 pub fn cap(&self) -> usize { 517 pub fn cap(&self) -> usize {
480 self.ringbuf.cap() 518 self.ringbuf.cap()
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index f14084599..c27ec7bd9 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -711,15 +711,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
711 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 711 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow()));
712 } 712 }
713 713
714 /// Read bytes from the ring buffer 714 /// Read elements from the ring buffer
715 /// Return a tuple of the length read and the length remaining in the buffer 715 /// Return a tuple of the length read and the length remaining in the buffer
716 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 716 /// If not all of the elements were read, then there will be some elements in the buffer remaining
717 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 717 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
718 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 718 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
719 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 719 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
720 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 720 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf)
721 } 721 }
722 722
723 /// Read an exact number of elements from the ringbuffer.
724 ///
725 /// Returns the remaining number of elements available for immediate reading.
726 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
727 ///
728 /// Async/Wake Behavior:
729 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
730 /// and when it wraps around. This means that when called with a buffer of length 'M', when this
731 /// ring buffer was created with a buffer of size 'N':
732 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
733 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
734 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
735 use core::future::poll_fn;
736 use core::sync::atomic::compiler_fence;
737
738 let mut read_data = 0;
739 let buffer_len = buffer.len();
740
741 poll_fn(|cx| {
742 self.set_waker(cx.waker());
743
744 compiler_fence(Ordering::SeqCst);
745
746 match self.read(&mut buffer[read_data..buffer_len]) {
747 Ok((len, remaining)) => {
748 read_data += len;
749 if read_data == buffer_len {
750 Poll::Ready(Ok(remaining))
751 } else {
752 Poll::Pending
753 }
754 }
755 Err(e) => Poll::Ready(Err(e)),
756 }
757 })
758 .await
759 }
760
723 // The capacity of the ringbuffer 761 // The capacity of the ringbuffer
724 pub fn cap(&self) -> usize { 762 pub fn cap(&self) -> usize {
725 self.ringbuf.cap() 763 self.ringbuf.cap()
diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs
index a2bde986f..190793974 100644
--- a/embassy-stm32/src/dma/ringbuffer.rs
+++ b/embassy-stm32/src/dma/ringbuffer.rs
@@ -72,10 +72,10 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
72 self.cap() - remaining_transfers 72 self.cap() - remaining_transfers
73 } 73 }
74 74
75 /// Read bytes from the ring buffer 75 /// Read elements from the ring buffer
76 /// Return a tuple of the length read and the length remaining in the buffer 76 /// Return a tuple of the length read and the length remaining in the buffer
77 /// If not all of the bytes were read, then there will be some bytes in the buffer remaining 77 /// If not all of the elements were read, then there will be some elements in the buffer remaining
78 /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read 78 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
79 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 79 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
80 pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 80 pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
81 /* 81 /*
@@ -95,11 +95,11 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
95 */ 95 */
96 let end = self.pos(dma.get_remaining_transfers()); 96 let end = self.pos(dma.get_remaining_transfers());
97 if self.start == end && dma.get_complete_count() == 0 { 97 if self.start == end && dma.get_complete_count() == 0 {
98 // No bytes are available in the buffer 98 // No elements are available in the buffer
99 Ok((0, self.cap())) 99 Ok((0, self.cap()))
100 } else if self.start < end { 100 } else if self.start < end {
101 // The available, unread portion in the ring buffer DOES NOT wrap 101 // The available, unread portion in the ring buffer DOES NOT wrap
102 // Copy out the bytes from the dma buffer 102 // Copy out the elements from the dma buffer
103 let len = self.copy_to(buf, self.start..end); 103 let len = self.copy_to(buf, self.start..end);
104 104
105 compiler_fence(Ordering::SeqCst); 105 compiler_fence(Ordering::SeqCst);
@@ -128,7 +128,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
128 // The DMA writer has wrapped since we last read and is currently 128 // The DMA writer has wrapped since we last read and is currently
129 // writing (or the next byte added will be) in the beginning of the ring buffer. 129 // writing (or the next byte added will be) in the beginning of the ring buffer.
130 130
131 // The provided read buffer is not large enough to include all bytes from the tail of the dma buffer. 131 // The provided read buffer is not large enough to include all elements from the tail of the dma buffer.
132 132
133 // Copy out from the dma buffer 133 // Copy out from the dma buffer
134 let len = self.copy_to(buf, self.start..self.cap()); 134 let len = self.copy_to(buf, self.start..self.cap());
@@ -154,8 +154,8 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
154 // The DMA writer has wrapped since we last read and is currently 154 // The DMA writer has wrapped since we last read and is currently
155 // writing (or the next byte added will be) in the beginning of the ring buffer. 155 // writing (or the next byte added will be) in the beginning of the ring buffer.
156 156
157 // The provided read buffer is large enough to include all bytes from the tail of the dma buffer, 157 // The provided read buffer is large enough to include all elements from the tail of the dma buffer,
158 // so the next read will not have any unread tail bytes in the ring buffer. 158 // so the next read will not have any unread tail elements in the ring buffer.
159 159
160 // Copy out from the dma buffer 160 // Copy out from the dma buffer
161 let tail = self.copy_to(buf, self.start..self.cap()); 161 let tail = self.copy_to(buf, self.start..self.cap());
@@ -180,7 +180,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> {
180 } 180 }
181 /// Copy from the dma buffer at `data_range` into `buf` 181 /// Copy from the dma buffer at `data_range` into `buf`
182 fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize { 182 fn copy_to(&mut self, buf: &mut [W], data_range: Range<usize>) -> usize {
183 // Limit the number of bytes that can be copied 183 // Limit the number of elements that can be copied
184 let length = usize::min(data_range.len(), buf.len()); 184 let length = usize::min(data_range.len(), buf.len());
185 185
186 // Copy from dma buffer into read buffer 186 // Copy from dma buffer into read buffer