use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_util::waitqueue::AtomicWaker; use futures::Future; use pac::dma::vals::DataSize; use crate::pac::dma::vals; use crate::{interrupt, pac, peripherals}; #[interrupt] unsafe fn DMA_IRQ_0() { let ints0 = pac::DMA.ints0().read().ints0(); critical_section::with(|_| { for channel in 0..CHANNEL_COUNT { if ints0 & (1 << channel) == 1 { CHANNEL_WAKERS[channel].wake(); } } pac::DMA.ints0().write(|w| w.set_ints0(ints0)); }); } pub fn read<'a, C: Channel, W: Word>(ch: impl Peripheral
+ 'a, from: *const W, to: &mut [W]) -> Transfer<'a, C> { let (ptr, len) = crate::dma::slice_ptr_parts_mut(to); copy_inner(ch, from as *const u32, ptr as *mut u32, len, W::size(), false, true) } pub fn write<'a, C: Channel, W: Word>(ch: impl Peripheral
+ 'a, from: &[W], to: *mut W) -> Transfer<'a, C> { let (from_ptr, len) = crate::dma::slice_ptr_parts(from); copy_inner(ch, from_ptr as *const u32, to as *mut u32, len, W::size(), true, false) } pub fn copy<'a, C: Channel, W: Word>(ch: impl Peripheral
+ 'a, from: &[W], to: &mut [W]) -> Transfer<'a, C> { let (from_ptr, from_len) = crate::dma::slice_ptr_parts(from); let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(to); assert_eq!(from_len, to_len); copy_inner( ch, from_ptr as *const u32, to_ptr as *mut u32, from_len, W::size(), true, true, ) } fn copy_inner<'a, C: Channel>( ch: impl Peripheral
+ 'a, from: *const u32, to: *mut u32, len: usize, data_size: DataSize, incr_read: bool, incr_write: bool, ) -> Transfer<'a, C> { into_ref!(ch); unsafe { let p = ch.regs(); p.read_addr().write_value(from as u32); p.write_addr().write_value(to as u32); p.trans_count().write_value(len as u32); compiler_fence(Ordering::SeqCst); p.ctrl_trig().write(|w| { w.set_data_size(data_size); w.set_incr_read(incr_read); w.set_incr_write(incr_write); w.set_chain_to(ch.number()); w.set_en(true); }); compiler_fence(Ordering::SeqCst); } Transfer::new(ch) } pub struct Transfer<'a, C: Channel> { channel: PeripheralRef<'a, C>, } impl<'a, C: Channel> Transfer<'a, C> { pub(crate) fn new(channel: impl Peripheral
+ 'a) -> Self {
into_ref!(channel);
unsafe {
let irq = interrupt::DMA_IRQ_0::steal();
irq.disable();
irq.set_priority(interrupt::Priority::P6);
pac::DMA.inte0().write(|w| w.set_inte0(1 << channel.number()));
irq.enable();
}
Self { channel }
}
}
impl<'a, C: Channel> Drop for Transfer<'a, C> {
fn drop(&mut self) {
let p = self.channel.regs();
unsafe {
p.ctrl_trig().write(|w| w.set_en(false));
while p.ctrl_trig().read().busy() {}
}
}
}
impl<'a, C: Channel> Unpin for Transfer<'a, C> {}
impl<'a, C: Channel> Future for Transfer<'a, C> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll + sealed::Channel + Into