88 lines
1.9 KiB
Rust
88 lines
1.9 KiB
Rust
use core::sync::atomic::{compiler_fence, Ordering};
|
|
|
|
use defmt::{assert, *};
|
|
|
|
use crate::{pac, peripherals};
|
|
use pac::dma::vals;
|
|
|
|
pub struct Dma<T: Channel> {
|
|
inner: T,
|
|
}
|
|
|
|
impl<T: Channel> Dma<T> {
|
|
pub fn copy(inner: T, from: &[u32], to: &mut [u32]) {
|
|
assert!(from.len() == to.len());
|
|
|
|
unsafe {
|
|
let p = inner.regs();
|
|
|
|
p.read_addr().write_value(from.as_ptr() as u32);
|
|
p.write_addr().write_value(to.as_mut_ptr() as u32);
|
|
p.trans_count().write_value(from.len() as u32);
|
|
|
|
compiler_fence(Ordering::SeqCst);
|
|
|
|
p.ctrl_trig().write(|w| {
|
|
w.set_data_size(vals::DataSize::SIZE_WORD);
|
|
w.set_incr_read(true);
|
|
w.set_incr_write(true);
|
|
w.set_chain_to(inner.number());
|
|
w.set_en(true);
|
|
});
|
|
|
|
while p.ctrl_trig().read().busy() {}
|
|
|
|
compiler_fence(Ordering::SeqCst);
|
|
}
|
|
}
|
|
}
|
|
|
|
mod sealed {
|
|
use super::*;
|
|
|
|
pub trait Channel {
|
|
fn number(&self) -> u8;
|
|
|
|
fn regs(&self) -> pac::dma::Channel {
|
|
pac::DMA.ch(self.number() as _)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait Channel: sealed::Channel {}
|
|
|
|
pub struct AnyChannel {
|
|
number: u8,
|
|
}
|
|
|
|
impl Channel for AnyChannel {}
|
|
impl sealed::Channel for AnyChannel {
|
|
fn number(&self) -> u8 {
|
|
self.number
|
|
}
|
|
}
|
|
|
|
macro_rules! channel {
|
|
($type:ident, $num:expr) => {
|
|
impl Channel for peripherals::$type {}
|
|
impl sealed::Channel for peripherals::$type {
|
|
fn number(&self) -> u8 {
|
|
$num
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
channel!(DMA_CH0, 0);
|
|
channel!(DMA_CH1, 1);
|
|
channel!(DMA_CH2, 2);
|
|
channel!(DMA_CH3, 3);
|
|
channel!(DMA_CH4, 4);
|
|
channel!(DMA_CH5, 5);
|
|
channel!(DMA_CH6, 6);
|
|
channel!(DMA_CH7, 7);
|
|
channel!(DMA_CH8, 8);
|
|
channel!(DMA_CH9, 9);
|
|
channel!(DMA_CH10, 10);
|
|
channel!(DMA_CH11, 11);
|