Merge pull request #2757 from tyler-gilbert/add-async-stop-stm32-dma_bdma
Add async stop() function to stm32 bdma_dma
This commit is contained in:
commit
e0f0430e2c
1 changed files with 62 additions and 1 deletions
|
@ -1,4 +1,4 @@
|
|||
use core::future::Future;
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::pin::Pin;
|
||||
use core::sync::atomic::{fence, AtomicUsize, Ordering};
|
||||
use core::task::{Context, Poll, Waker};
|
||||
|
@ -510,6 +510,31 @@ impl AnyChannel {
|
|||
DmaInfo::Bdma(r) => r.ch(info.num).ndtr().read().ndt(),
|
||||
}
|
||||
}
|
||||
|
||||
fn disable_circular_mode(&self) {
|
||||
let info = self.info();
|
||||
match self.info().dma {
|
||||
#[cfg(dma)]
|
||||
DmaInfo::Dma(regs) => regs.st(info.num).cr().modify(|w| {
|
||||
w.set_circ(false);
|
||||
}),
|
||||
#[cfg(bdma)]
|
||||
DmaInfo::Bdma(regs) => regs.ch(info.num).cr().modify(|w| {
|
||||
w.set_circ(false);
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_stop(&self) -> Poll<()> {
|
||||
use core::sync::atomic::compiler_fence;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
if !self.is_running() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA transfer.
|
||||
|
@ -829,6 +854,25 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
|
|||
pub fn is_running(&mut self) -> bool {
|
||||
self.channel.is_running()
|
||||
}
|
||||
|
||||
/// Stop the DMA transfer and await until the buffer is full.
|
||||
///
|
||||
/// This disables the DMA transfer's circular mode so that the transfer
|
||||
/// stops when the buffer is full.
|
||||
///
|
||||
/// This is designed to be used with streaming input data such as the
|
||||
/// I2S/SAI or ADC.
|
||||
///
|
||||
/// When using the UART, you probably want `request_stop()`.
|
||||
pub async fn stop(&mut self) {
|
||||
self.channel.disable_circular_mode();
|
||||
//wait until cr.susp reads as true
|
||||
poll_fn(|cx| {
|
||||
self.set_waker(cx.waker());
|
||||
self.channel.poll_stop()
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> {
|
||||
|
@ -940,6 +984,23 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
|
|||
pub fn is_running(&mut self) -> bool {
|
||||
self.channel.is_running()
|
||||
}
|
||||
|
||||
/// Stop the DMA transfer and await until the buffer is empty.
|
||||
///
|
||||
/// This disables the DMA transfer's circular mode so that the transfer
|
||||
/// stops when all available data has been written.
|
||||
///
|
||||
/// This is designed to be used with streaming output data such as the
|
||||
/// I2S/SAI or DAC.
|
||||
pub async fn stop(&mut self) {
|
||||
self.channel.disable_circular_mode();
|
||||
//wait until cr.susp reads as true
|
||||
poll_fn(|cx| {
|
||||
self.set_waker(cx.waker());
|
||||
self.channel.poll_stop()
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> {
|
||||
|
|
Loading…
Add table
Reference in a new issue