fix: modified dma channel state management

See
https://github.com/embassy-rs/embassy/pull/3923#discussion_r2094570176
This commit is contained in:
etiennecollin 2025-08-25 21:10:59 +02:00 committed by Dario Nieuwenhuis
parent 7d224d94c4
commit fec14213ea
4 changed files with 80 additions and 46 deletions

View File

@ -341,21 +341,25 @@ impl AnyChannel {
ch.cr().modify(|w| w.set_en(true));
}
fn request_stop(&self) {
fn request_suspend(&self) {
let info = self.info();
let ch = info.dma.ch(info.num);
ch.cr().modify(|w| w.set_susp(true))
}
fn request_pause(&self) {
fn request_resume(&self) {
let info = self.info();
let ch = info.dma.ch(info.num);
// Disable the channel without overwriting the existing configuration
ch.cr().modify(|w| {
w.set_en(false);
});
ch.cr().modify(|w| w.set_susp(false));
}
fn request_reset(&self) {
let info = self.info();
let ch = info.dma.ch(info.num);
ch.cr().modify(|w| w.set_reset(true));
}
fn is_running(&self) -> bool {
@ -406,11 +410,26 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> {
Self { channel }
}
/// Request the transfer to stop.
/// Request the transfer to suspend.
///
/// To resume the transfer, call [`request_resume`](Self::request_resume) again.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) {
self.channel.request_stop()
pub fn request_suspend(&mut self) {
self.channel.request_suspend()
}
/// Request the transfer to resume after being suspended.
pub fn request_resume(&mut self) {
self.channel.request_resume()
}
/// Request the DMA to reset.
///
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead.
pub fn request_reset(&mut self) {
self.channel.request_reset()
}
/// Return whether this transfer is still running.
@ -440,7 +459,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> {
impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> {
fn drop(&mut self) {
self.request_stop();
self.request_suspend();
while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads."
@ -589,21 +608,26 @@ impl<'a> Transfer<'a> {
Self { channel }
}
/// Request the transfer to stop.
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead.
/// Request the transfer to suspend.
///
/// To resume the transfer, call [`request_resume`](Self::request_resume) again.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) {
self.channel.request_stop()
pub fn request_suspend(&mut self) {
self.channel.request_suspend()
}
/// Request the transfer to pause, keeping the existing configuration for this channel.
/// To restart the transfer, call [`start`](Self::start) again.
/// Request the transfer to resume after being suspended.
pub fn request_resume(&mut self) {
self.channel.request_resume()
}
/// Request the DMA to reset.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_pause(&mut self) {
self.channel.request_pause()
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead.
pub fn request_reset(&mut self) {
self.channel.request_reset()
}
/// Return whether this transfer is still running.
@ -633,7 +657,7 @@ impl<'a> Transfer<'a> {
impl<'a> Drop for Transfer<'a> {
fn drop(&mut self) {
self.request_stop();
self.request_suspend();
while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads."

View File

@ -139,21 +139,26 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
/// Request the DMA to stop.
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead.
/// Request the DMA to suspend.
///
/// To resume the transfer, call [`request_resume`](Self::request_resume) again.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) {
self.channel.request_stop()
pub fn request_suspend(&mut self) {
self.channel.request_suspend()
}
/// Request the transfer to pause, keeping the existing configuration for this channel.
/// To restart the transfer, call [`start`](Self::start) again.
/// Request the DMA to resume transfers after being suspended.
pub fn request_resume(&mut self) {
self.channel.request_resume()
}
/// Request the DMA to reset.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_pause(&mut self) {
self.channel.request_pause()
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead.
pub fn request_reset(&mut self) {
self.channel.request_reset()
}
/// Return whether DMA is still running.
@ -185,7 +190,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> {
fn drop(&mut self) {
self.request_stop();
self.request_suspend();
while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads."
@ -285,21 +290,26 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
DmaCtrlImpl(self.channel.reborrow()).set_waker(waker);
}
/// Request the DMA to stop.
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead.
/// Request the DMA to suspend.
///
/// To resume the transfer, call [`request_resume`](Self::request_resume) again.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_stop(&mut self) {
self.channel.request_stop()
pub fn request_suspend(&mut self) {
self.channel.request_suspend()
}
/// Request the transfer to pause, keeping the existing configuration for this channel.
/// To restart the transfer, call [`start`](Self::start) again.
/// Request the DMA to resume transfers after being suspended.
pub fn request_resume(&mut self) {
self.channel.request_resume()
}
/// Request the DMA to reset.
///
/// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false.
pub fn request_pause(&mut self) {
self.channel.request_pause()
/// The configuration for this channel will **not be preserved**. If you need to restart the transfer
/// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead.
pub fn request_reset(&mut self) {
self.channel.request_reset()
}
/// Return whether DMA is still running.
@ -331,7 +341,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> {
fn drop(&mut self) {
self.request_stop();
self.request_suspend();
while self.is_running() {}
// "Subsequent reads and writes cannot be moved ahead of preceding reads."

View File

@ -490,14 +490,14 @@ impl<'d, T: Instance> PdPhy<'d, T> {
let sr = r.sr().read();
if sr.rxhrstdet() {
dma.request_stop();
dma.request_suspend();
// Clean and re-enable hard reset receive interrupt.
r.icr().write(|w| w.set_rxhrstdetcf(true));
r.imr().modify(|w| w.set_rxhrstdetie(true));
Poll::Ready(Err(RxError::HardReset))
} else if sr.rxmsgend() {
dma.request_stop();
dma.request_suspend();
// Should be read immediately on interrupt.
rxpaysz = r.rx_payszr().read().rxpaysz().into();

View File

@ -165,7 +165,7 @@ impl<'d> RingBufferedUartRx<'d> {
/// Stop DMA backed UART receiver
fn stop_uart(&mut self) {
self.ring_buf.request_pause();
self.ring_buf.request_suspend();
let r = self.info.regs;
// clear all interrupts and DMA Rx Request