aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Gilbert <[email protected]>2024-03-31 16:31:47 -0500
committerTyler Gilbert <[email protected]>2024-03-31 16:31:47 -0500
commitcb01d0383523af4b9f80c4bdc4410791eba1173e (patch)
tree4e3212be4282da8dcd25e85d5a5f52fd7f90cf3f
parent6634cc90bcd3eb25b64712688920f383584b2964 (diff)
Add async stop() function to stm32 bdma_dma
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs63
1 files changed, 62 insertions, 1 deletions
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index 7b5b3cf58..a6344cf06 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -1,4 +1,4 @@
1use core::future::Future; 1use core::future::{poll_fn, Future};
2use core::pin::Pin; 2use core::pin::Pin;
3use core::sync::atomic::{fence, AtomicUsize, Ordering}; 3use core::sync::atomic::{fence, AtomicUsize, Ordering};
4use core::task::{Context, Poll, Waker}; 4use core::task::{Context, Poll, Waker};
@@ -510,6 +510,31 @@ impl AnyChannel {
510 DmaInfo::Bdma(r) => r.ch(info.num).ndtr().read().ndt(), 510 DmaInfo::Bdma(r) => r.ch(info.num).ndtr().read().ndt(),
511 } 511 }
512 } 512 }
513
514 fn disable_circular_mode(&self) {
515 let info = self.info();
516 match self.info().dma {
517 #[cfg(dma)]
518 DmaInfo::Dma(regs) => regs.st(info.num).cr().modify(|w| {
519 w.set_circ(false);
520 }),
521 #[cfg(bdma)]
522 DmaInfo::Bdma(regs) => regs.ch(info.num).cr().modify(|w| {
523 w.set_circ(false);
524 }),
525 }
526 }
527
528 fn poll_stop(&self) -> Poll<()> {
529 use core::sync::atomic::compiler_fence;
530 compiler_fence(Ordering::SeqCst);
531
532 if !self.is_running() {
533 Poll::Ready(())
534 } else {
535 Poll::Pending
536 }
537 }
513} 538}
514 539
515/// DMA transfer. 540/// DMA transfer.
@@ -829,6 +854,25 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
829 pub fn is_running(&mut self) -> bool { 854 pub fn is_running(&mut self) -> bool {
830 self.channel.is_running() 855 self.channel.is_running()
831 } 856 }
857
858 /// Stop the DMA transfer and await until the buffer is full.
859 ///
860 /// This disables the DMA transfer's circular mode so that the transfer
861 /// stops when the buffer is full.
862 ///
863 /// This is designed to be used with streaming input data such as the
864 /// I2S/SAI or ADC.
865 ///
866 /// When using the UART, you probably want `request_stop()`.
867 pub async fn stop(&mut self) {
868 self.channel.disable_circular_mode();
869 //wait until cr.susp reads as true
870 poll_fn(|cx| {
871 self.set_waker(cx.waker());
872 self.channel.poll_stop()
873 })
874 .await
875 }
832} 876}
833 877
834impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { 878impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> {
@@ -940,6 +984,23 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
940 pub fn is_running(&mut self) -> bool { 984 pub fn is_running(&mut self) -> bool {
941 self.channel.is_running() 985 self.channel.is_running()
942 } 986 }
987
988 /// Stop the DMA transfer and await until the buffer is empty.
989 ///
990 /// This disables the DMA transfer's circular mode so that the transfer
991 /// stops when all available data has been written.
992 ///
993 /// This is designed to be used with streaming output data such as the
994 /// I2S/SAI or DAC.
995 pub async fn stop(&mut self) {
996 self.channel.disable_circular_mode();
997 //wait until cr.susp reads as true
998 poll_fn(|cx| {
999 self.set_waker(cx.waker());
1000 self.channel.poll_stop()
1001 })
1002 .await
1003 }
943} 1004}
944 1005
945impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { 1006impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> {