diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-10 15:21:31 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-10 15:21:31 +0000 |
| commit | 95262ad5593bd421fc0a79f55bd48f7beb4bb1c9 (patch) | |
| tree | ee97ce163935a147f59659fd6bff55d488dc0a80 | |
| parent | 43e2edfbda6dbd0f9ae008a386ff5003dc5bd062 (diff) | |
| parent | e80db420610cc1bf2619bb64688f87712c1eee1c (diff) | |
Merge pull request #1743 from xoviat/dma-2
stm32/dma: consolidate ringbuf
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 74 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 74 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/ringbuffer.rs | 103 |
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 | ||
| 398 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | 402 | pub 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 | ||
| 628 | pub struct ReadableRingBuffer<'a, C: Channel, W: Word> { | 632 | pub 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 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::ops::Range; | 4 | use core::ops::Range; |
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 5 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use core::task::{Poll, Waker}; | ||
| 5 | 7 | ||
| 6 | use super::word::Word; | 8 | use 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 | ||
| 54 | impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> { | 59 | impl<'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 { |
