diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-04-01 16:29:53 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-04-01 16:29:53 +0000 |
| commit | e0f0430e2cb04f373f3e93e7abd27eba39d3eb7f (patch) | |
| tree | 1c6d7a6dca21c0095e586b2f9eec6970b2d031b8 | |
| parent | 0549dd5fd7d874f4f071047db12702f58009931b (diff) | |
| parent | cb01d0383523af4b9f80c4bdc4410791eba1173e (diff) | |
Merge pull request #2757 from tyler-gilbert/add-async-stop-stm32-dma_bdma
Add async stop() function to stm32 bdma_dma
| -rw-r--r-- | embassy-stm32/src/dma/dma_bdma.rs | 63 |
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 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::{poll_fn, Future}; |
| 2 | use core::pin::Pin; | 2 | use core::pin::Pin; |
| 3 | use core::sync::atomic::{fence, AtomicUsize, Ordering}; | 3 | use core::sync::atomic::{fence, AtomicUsize, Ordering}; |
| 4 | use core::task::{Context, Poll, Waker}; | 4 | use 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 | ||
| 834 | impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { | 878 | impl<'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 | ||
| 945 | impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { | 1006 | impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { |
