aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-08-10 15:21:31 +0000
committerGitHub <[email protected]>2023-08-10 15:21:31 +0000
commit95262ad5593bd421fc0a79f55bd48f7beb4bb1c9 (patch)
treeee97ce163935a147f59659fd6bff55d488dc0a80
parent43e2edfbda6dbd0f9ae008a386ff5003dc5bd062 (diff)
parente80db420610cc1bf2619bb64688f87712c1eee1c (diff)
Merge pull request #1743 from xoviat/dma-2
stm32/dma: consolidate ringbuf
-rw-r--r--embassy-stm32/src/dma/bdma.rs74
-rw-r--r--embassy-stm32/src/dma/dma.rs74
-rw-r--r--embassy-stm32/src/dma/ringbuffer.rs103
3 files changed, 120 insertions, 131 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index 60f4fbd09..20ff29bef 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -393,6 +393,10 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
393 fn reset_complete_count(&mut self) -> usize { 393 fn reset_complete_count(&mut self) -> usize {
394 STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel) 394 STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
395 } 395 }
396
397 fn set_waker(&mut self, waker: &Waker) {
398 STATE.ch_wakers[self.0.index()].register(waker);
399 }
396} 400}
397 401
398pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { 402pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
@@ -463,7 +467,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
463 } 467 }
464 468
465 pub fn clear(&mut self) { 469 pub fn clear(&mut self) {
466 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 470 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
467 } 471 }
468 472
469 /// Read elements from the ring buffer 473 /// Read elements from the ring buffer
@@ -472,7 +476,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
472 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read 476 /// 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. 477 /// 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> { 478 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
475 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 479 self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
476 } 480 }
477 481
478 /// Read an exact number of elements from the ringbuffer. 482 /// Read an exact number of elements from the ringbuffer.
@@ -487,39 +491,18 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
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. 491 /// - 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. 492 /// - 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> { 493 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
490 use core::future::poll_fn; 494 self.ringbuf
491 use core::sync::atomic::compiler_fence; 495 .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
492 496 .await
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 } 497 }
515 498
516 /// The capacity of the ringbuffer. 499 /// The capacity of the ringbuffer.
517 pub fn cap(&self) -> usize { 500 pub const fn cap(&self) -> usize {
518 self.ringbuf.cap() 501 self.ringbuf.cap()
519 } 502 }
520 503
521 pub fn set_waker(&mut self, waker: &Waker) { 504 pub fn set_waker(&mut self, waker: &Waker) {
522 STATE.ch_wakers[self.channel.index()].register(waker); 505 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
523 } 506 }
524 507
525 fn clear_irqs(&mut self) { 508 fn clear_irqs(&mut self) {
@@ -628,50 +611,29 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
628 } 611 }
629 612
630 pub fn clear(&mut self) { 613 pub fn clear(&mut self) {
631 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 614 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
632 } 615 }
633 616
634 /// Write elements to the ring buffer 617 /// Write elements to the ring buffer
635 /// Return a tuple of the length written and the length remaining in the buffer 618 /// Return a tuple of the length written and the length remaining in the buffer
636 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { 619 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
637 self.ringbuf.write(DmaCtrlImpl(self.channel.reborrow()), buf) 620 self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
638 } 621 }
639 622
640 /// Write an exact number of elements to the ringbuffer. 623 /// Write an exact number of elements to the ringbuffer.
641 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> { 624 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
642 use core::future::poll_fn; 625 self.ringbuf
643 use core::sync::atomic::compiler_fence; 626 .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
644 627 .await
645 let mut written_data = 0;
646 let buffer_len = buffer.len();
647
648 poll_fn(|cx| {
649 self.set_waker(cx.waker());
650
651 compiler_fence(Ordering::SeqCst);
652
653 match self.write(&buffer[written_data..buffer_len]) {
654 Ok((len, remaining)) => {
655 written_data += len;
656 if written_data == buffer_len {
657 Poll::Ready(Ok(remaining))
658 } else {
659 Poll::Pending
660 }
661 }
662 Err(e) => Poll::Ready(Err(e)),
663 }
664 })
665 .await
666 } 628 }
667 629
668 /// The capacity of the ringbuffer. 630 /// The capacity of the ringbuffer.
669 pub fn cap(&self) -> usize { 631 pub const fn cap(&self) -> usize {
670 self.ringbuf.cap() 632 self.ringbuf.cap()
671 } 633 }
672 634
673 pub fn set_waker(&mut self, waker: &Waker) { 635 pub fn set_waker(&mut self, waker: &Waker) {
674 STATE.ch_wakers[self.channel.index()].register(waker); 636 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
675 } 637 }
676 638
677 fn clear_irqs(&mut self) { 639 fn clear_irqs(&mut self) {
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 9cd7aa8d5..5033ae477 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -623,6 +623,10 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> {
623 fn reset_complete_count(&mut self) -> usize { 623 fn reset_complete_count(&mut self) -> usize {
624 STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel) 624 STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel)
625 } 625 }
626
627 fn set_waker(&mut self, waker: &Waker) {
628 STATE.ch_wakers[self.0.index()].register(waker);
629 }
626} 630}
627 631
628pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { 632pub struct ReadableRingBuffer<'a, C: Channel, W: Word> {
@@ -708,7 +712,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
708 } 712 }
709 713
710 pub fn clear(&mut self) { 714 pub fn clear(&mut self) {
711 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 715 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
712 } 716 }
713 717
714 /// Read elements from the ring buffer 718 /// Read elements from the ring buffer
@@ -717,7 +721,7 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
717 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read 721 /// 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. 722 /// 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> { 723 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
720 self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) 724 self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
721 } 725 }
722 726
723 /// Read an exact number of elements from the ringbuffer. 727 /// Read an exact number of elements from the ringbuffer.
@@ -732,39 +736,18 @@ impl<'a, C: Channel, W: Word> ReadableRingBuffer<'a, C, W> {
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. 736 /// - 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. 737 /// - 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> { 738 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> {
735 use core::future::poll_fn; 739 self.ringbuf
736 use core::sync::atomic::compiler_fence; 740 .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
737 741 .await
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 } 742 }
760 743
761 // The capacity of the ringbuffer 744 // The capacity of the ringbuffer
762 pub fn cap(&self) -> usize { 745 pub const fn cap(&self) -> usize {
763 self.ringbuf.cap() 746 self.ringbuf.cap()
764 } 747 }
765 748
766 pub fn set_waker(&mut self, waker: &Waker) { 749 pub fn set_waker(&mut self, waker: &Waker) {
767 STATE.ch_wakers[self.channel.index()].register(waker); 750 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
768 } 751 }
769 752
770 fn clear_irqs(&mut self) { 753 fn clear_irqs(&mut self) {
@@ -890,50 +873,29 @@ impl<'a, C: Channel, W: Word> WritableRingBuffer<'a, C, W> {
890 } 873 }
891 874
892 pub fn clear(&mut self) { 875 pub fn clear(&mut self) {
893 self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); 876 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow()));
894 } 877 }
895 878
896 /// Write elements from the ring buffer 879 /// Write elements from the ring buffer
897 /// Return a tuple of the length written and the length remaining in the buffer 880 /// Return a tuple of the length written and the length remaining in the buffer
898 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { 881 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> {
899 self.ringbuf.write(DmaCtrlImpl(self.channel.reborrow()), buf) 882 self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
900 } 883 }
901 884
902 /// Write an exact number of elements to the ringbuffer. 885 /// Write an exact number of elements to the ringbuffer.
903 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> { 886 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> {
904 use core::future::poll_fn; 887 self.ringbuf
905 use core::sync::atomic::compiler_fence; 888 .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
906 889 .await
907 let mut written_data = 0;
908 let buffer_len = buffer.len();
909
910 poll_fn(|cx| {
911 self.set_waker(cx.waker());
912
913 compiler_fence(Ordering::SeqCst);
914
915 match self.write(&buffer[written_data..buffer_len]) {
916 Ok((len, remaining)) => {
917 written_data += len;
918 if written_data == buffer_len {
919 Poll::Ready(Ok(remaining))
920 } else {
921 Poll::Pending
922 }
923 }
924 Err(e) => Poll::Ready(Err(e)),
925 }
926 })
927 .await
928 } 890 }
929 891
930 // The capacity of the ringbuffer 892 // The capacity of the ringbuffer
931 pub fn cap(&self) -> usize { 893 pub const fn cap(&self) -> usize {
932 self.ringbuf.cap() 894 self.ringbuf.cap()
933 } 895 }
934 896
935 pub fn set_waker(&mut self, waker: &Waker) { 897 pub fn set_waker(&mut self, waker: &Waker) {
936 STATE.ch_wakers[self.channel.index()].register(waker); 898 DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
937 } 899 }
938 900
939 fn clear_irqs(&mut self) { 901 fn clear_irqs(&mut self) {
diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs
index 6ce59e455..c9f7a3026 100644
--- a/embassy-stm32/src/dma/ringbuffer.rs
+++ b/embassy-stm32/src/dma/ringbuffer.rs
@@ -1,7 +1,9 @@
1#![cfg_attr(gpdma, allow(unused))] 1#![cfg_attr(gpdma, allow(unused))]
2 2
3use core::future::poll_fn;
3use core::ops::Range; 4use core::ops::Range;
4use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::{Poll, Waker};
5 7
6use super::word::Word; 8use super::word::Word;
7 9
@@ -49,6 +51,9 @@ pub trait DmaCtrl {
49 51
50 /// Reset the transfer completed counter to 0 and return the value just prior to the reset. 52 /// Reset the transfer completed counter to 0 and return the value just prior to the reset.
51 fn reset_complete_count(&mut self) -> usize; 53 fn reset_complete_count(&mut self) -> usize;
54
55 /// Set the waker for a running poll_fn
56 fn set_waker(&mut self, waker: &Waker);
52} 57}
53 58
54impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> { 59impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
@@ -57,7 +62,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
57 } 62 }
58 63
59 /// Reset the ring buffer to its initial state 64 /// Reset the ring buffer to its initial state
60 pub fn clear(&mut self, mut dma: impl DmaCtrl) { 65 pub fn clear(&mut self, dma: &mut impl DmaCtrl) {
61 self.start = 0; 66 self.start = 0;
62 dma.reset_complete_count(); 67 dma.reset_complete_count();
63 } 68 }
@@ -68,8 +73,43 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
68 } 73 }
69 74
70 /// The current position of the ringbuffer 75 /// The current position of the ringbuffer
71 fn pos(&self, remaining_transfers: usize) -> usize { 76 fn pos(&self, dma: &mut impl DmaCtrl) -> usize {
72 self.cap() - remaining_transfers 77 self.cap() - dma.get_remaining_transfers()
78 }
79
80 /// Read an exact number of elements from the ringbuffer.
81 ///
82 /// Returns the remaining number of elements available for immediate reading.
83 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller.
84 ///
85 /// Async/Wake Behavior:
86 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
87 /// and when it wraps around. This means that when called with a buffer of length 'M', when this
88 /// ring buffer was created with a buffer of size 'N':
89 /// - 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.
90 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
91 pub async fn read_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &mut [W]) -> Result<usize, OverrunError> {
92 let mut read_data = 0;
93 let buffer_len = buffer.len();
94
95 poll_fn(|cx| {
96 dma.set_waker(cx.waker());
97
98 compiler_fence(Ordering::SeqCst);
99
100 match self.read(dma, &mut buffer[read_data..buffer_len]) {
101 Ok((len, remaining)) => {
102 read_data += len;
103 if read_data == buffer_len {
104 Poll::Ready(Ok(remaining))
105 } else {
106 Poll::Pending
107 }
108 }
109 Err(e) => Poll::Ready(Err(e)),
110 }
111 })
112 .await
73 } 113 }
74 114
75 /// Read elements from the ring buffer 115 /// Read elements from the ring buffer
@@ -77,7 +117,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
77 /// If not all of the elements were read, then there will be some elements in the buffer remaining 117 /// 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 elements remaining after the read 118 /// 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. 119 /// 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> { 120 pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
81 /* 121 /*
82 This algorithm is optimistic: we assume we haven't overrun more than a full buffer and then check 122 This algorithm is optimistic: we assume we haven't overrun more than a full buffer and then check
83 after we've done our work to see we have. This is because on stm32, an interrupt is not guaranteed 123 after we've done our work to see we have. This is because on stm32, an interrupt is not guaranteed
@@ -93,7 +133,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
93 rather than the data we actually copied because it costs nothing and confirms an error condition 133 rather than the data we actually copied because it costs nothing and confirms an error condition
94 earlier. 134 earlier.
95 */ 135 */
96 let end = self.pos(dma.get_remaining_transfers()); 136 let end = self.pos(dma);
97 if self.start == end && dma.get_complete_count() == 0 { 137 if self.start == end && dma.get_complete_count() == 0 {
98 // No elements are available in the buffer 138 // No elements are available in the buffer
99 Ok((0, self.cap())) 139 Ok((0, self.cap()))
@@ -114,8 +154,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
114 then, get the current position of of the dma write and check 154 then, get the current position of of the dma write and check
115 if it's inside data we could have copied 155 if it's inside data we could have copied
116 */ 156 */
117 let (pos, complete_count) = 157 let (pos, complete_count) = critical_section::with(|_| (self.pos(dma), dma.get_complete_count()));
118 critical_section::with(|_| (self.pos(dma.get_remaining_transfers()), dma.get_complete_count()));
119 if (pos >= self.start && pos < end) || (complete_count > 0 && pos >= end) || complete_count > 1 { 158 if (pos >= self.start && pos < end) || (complete_count > 0 && pos >= end) || complete_count > 1 {
120 Err(OverrunError) 159 Err(OverrunError)
121 } else { 160 } else {
@@ -141,7 +180,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
141 then, get the current position of of the dma write and check 180 then, get the current position of of the dma write and check
142 if it's inside data we could have copied 181 if it's inside data we could have copied
143 */ 182 */
144 let pos = self.pos(dma.get_remaining_transfers()); 183 let pos = self.pos(dma);
145 if pos > self.start || pos < end || dma.get_complete_count() > 1 { 184 if pos > self.start || pos < end || dma.get_complete_count() > 1 {
146 Err(OverrunError) 185 Err(OverrunError)
147 } else { 186 } else {
@@ -169,7 +208,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
169 then, get the current position of of the dma write and check 208 then, get the current position of of the dma write and check
170 if it's inside data we could have copied 209 if it's inside data we could have copied
171 */ 210 */
172 let pos = self.pos(dma.get_remaining_transfers()); 211 let pos = self.pos(dma);
173 if pos > self.start || pos < end || dma.reset_complete_count() > 1 { 212 if pos > self.start || pos < end || dma.reset_complete_count() > 1 {
174 Err(OverrunError) 213 Err(OverrunError)
175 } else { 214 } else {
@@ -209,7 +248,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
209 } 248 }
210 249
211 /// Reset the ring buffer to its initial state 250 /// Reset the ring buffer to its initial state
212 pub fn clear(&mut self, mut dma: impl DmaCtrl) { 251 pub fn clear(&mut self, dma: &mut impl DmaCtrl) {
213 self.end = 0; 252 self.end = 0;
214 dma.reset_complete_count(); 253 dma.reset_complete_count();
215 } 254 }
@@ -220,14 +259,39 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
220 } 259 }
221 260
222 /// The current position of the ringbuffer 261 /// The current position of the ringbuffer
223 fn pos(&self, remaining_transfers: usize) -> usize { 262 fn pos(&self, dma: &mut impl DmaCtrl) -> usize {
224 self.cap() - remaining_transfers 263 self.cap() - dma.get_remaining_transfers()
264 }
265
266 /// Write an exact number of elements to the ringbuffer.
267 pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, OverrunError> {
268 let mut written_data = 0;
269 let buffer_len = buffer.len();
270
271 poll_fn(|cx| {
272 dma.set_waker(cx.waker());
273
274 compiler_fence(Ordering::SeqCst);
275
276 match self.write(dma, &buffer[written_data..buffer_len]) {
277 Ok((len, remaining)) => {
278 written_data += len;
279 if written_data == buffer_len {
280 Poll::Ready(Ok(remaining))
281 } else {
282 Poll::Pending
283 }
284 }
285 Err(e) => Poll::Ready(Err(e)),
286 }
287 })
288 .await
225 } 289 }
226 290
227 /// Write elements from the ring buffer 291 /// Write elements from the ring buffer
228 /// Return a tuple of the length written and the capacity remaining to be written in the buffer 292 /// Return a tuple of the length written and the capacity remaining to be written in the buffer
229 pub fn write(&mut self, mut dma: impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> { 293 pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> {
230 let start = self.pos(dma.get_remaining_transfers()); 294 let start = self.pos(dma);
231 if start > self.end { 295 if start > self.end {
232 // The occupied portion in the ring buffer DOES wrap 296 // The occupied portion in the ring buffer DOES wrap
233 let len = self.copy_from(buf, self.end..start); 297 let len = self.copy_from(buf, self.end..start);
@@ -235,8 +299,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
235 compiler_fence(Ordering::SeqCst); 299 compiler_fence(Ordering::SeqCst);
236 300
237 // Confirm that the DMA is not inside data we could have written 301 // Confirm that the DMA is not inside data we could have written
238 let (pos, complete_count) = 302 let (pos, complete_count) = critical_section::with(|_| (self.pos(dma), dma.get_complete_count()));
239 critical_section::with(|_| (self.pos(dma.get_remaining_transfers()), dma.get_complete_count()));
240 if (pos >= self.end && pos < start) || (complete_count > 0 && pos >= start) || complete_count > 1 { 303 if (pos >= self.end && pos < start) || (complete_count > 0 && pos >= start) || complete_count > 1 {
241 Err(OverrunError) 304 Err(OverrunError)
242 } else { 305 } else {
@@ -256,7 +319,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
256 compiler_fence(Ordering::SeqCst); 319 compiler_fence(Ordering::SeqCst);
257 320
258 // Confirm that the DMA is not inside data we could have written 321 // Confirm that the DMA is not inside data we could have written
259 let pos = self.pos(dma.get_remaining_transfers()); 322 let pos = self.pos(dma);
260 if pos > self.end || pos < start || dma.get_complete_count() > 1 { 323 if pos > self.end || pos < start || dma.get_complete_count() > 1 {
261 Err(OverrunError) 324 Err(OverrunError)
262 } else { 325 } else {
@@ -274,7 +337,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
274 compiler_fence(Ordering::SeqCst); 337 compiler_fence(Ordering::SeqCst);
275 338
276 // Confirm that the DMA is not inside data we could have written 339 // Confirm that the DMA is not inside data we could have written
277 let pos = self.pos(dma.get_remaining_transfers()); 340 let pos = self.pos(dma);
278 if pos > self.end || pos < start || dma.reset_complete_count() > 1 { 341 if pos > self.end || pos < start || dma.reset_complete_count() > 1 {
279 Err(OverrunError) 342 Err(OverrunError)
280 } else { 343 } else {
@@ -323,7 +386,7 @@ mod tests {
323 requests: cell::RefCell<vec::Vec<TestCircularTransferRequest>>, 386 requests: cell::RefCell<vec::Vec<TestCircularTransferRequest>>,
324 } 387 }
325 388
326 impl DmaCtrl for &mut TestCircularTransfer { 389 impl DmaCtrl for TestCircularTransfer {
327 fn get_remaining_transfers(&self) -> usize { 390 fn get_remaining_transfers(&self) -> usize {
328 match self.requests.borrow_mut().pop().unwrap() { 391 match self.requests.borrow_mut().pop().unwrap() {
329 TestCircularTransferRequest::PositionRequest(pos) => { 392 TestCircularTransferRequest::PositionRequest(pos) => {
@@ -350,6 +413,8 @@ mod tests {
350 _ => unreachable!(), 413 _ => unreachable!(),
351 } 414 }
352 } 415 }
416
417 fn set_waker(&mut self, waker: &Waker) {}
353 } 418 }
354 419
355 impl TestCircularTransfer { 420 impl TestCircularTransfer {