Skip to content

Commit

Permalink
feat: add support for aborting DMA transfers
Browse files Browse the repository at this point in the history
  • Loading branch information
EliseZeroTwo committed May 18, 2024
1 parent dfbdb9a commit ac616d2
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
31 changes: 31 additions & 0 deletions rp2040-hal/src/dma/single_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,35 @@ where

(self.ch, self.from, self.to)
}

/// Aborts the current transfer, returning the channel and targets
pub fn abort(mut self) -> (CH, FROM, TO) {
let irq0_was_enabled = self.ch.is_enabled_irq0();
let irq1_was_enabled = self.ch.is_enabled_irq1();
self.ch.disable_irq0();
self.ch.disable_irq1();

unsafe { &*crate::pac::DMA::ptr() }.chan_abort().write(|w| unsafe { w.bits(1 << self.ch.id() as u32)});

while unsafe { &*crate::pac::DMA::ptr() }.chan_abort().read().bits() != 0 {}

while !self.is_done() {};

self.ch.check_irq0();
self.ch.check_irq1();

if irq0_was_enabled {
self.ch.enable_irq0();
}

if irq1_was_enabled {
self.ch.enable_irq1();
}

// Make sure that memory contents reflect what the user intended.
cortex_m::asm::dsb();
compiler_fence(Ordering::SeqCst);

(self.ch, self.from, self.to)
}
}
16 changes: 16 additions & 0 deletions rp2040-hal/src/dma/single_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ pub trait SingleChannel: Sealed {
}
}

/// Check if the DMA_IRQ_0 signal for this channel is enabled.
fn is_enabled_irq0(&mut self) -> bool {
// Safety: We only use the atomic alias of the register.
unsafe {
(*DMA::ptr()).inte0().read().bits() & 1 << self.id() != 0
}
}

#[deprecated(note = "Renamed to disable_irq0")]
/// Disables the DMA_IRQ_0 signal for this channel.
fn unlisten_irq0(&mut self) {
Expand Down Expand Up @@ -75,6 +83,14 @@ pub trait SingleChannel: Sealed {
}
}

/// Check if the DMA_IRQ_1 signal for this channel is enabled.
fn is_enabled_irq1(&mut self) -> bool {
// Safety: We only use the atomic alias of the register.
unsafe {
(*DMA::ptr()).inte1().read().bits() & 1 << self.id() != 0
}
}

#[deprecated(note = "Renamed to disable_irq1")]
/// Disables the DMA_IRQ_1 signal for this channel.
fn unlisten_irq1(&mut self) {
Expand Down

0 comments on commit ac616d2

Please sign in to comment.