rp: add initial version
This commit is contained in:
		
							
								
								
									
										87
									
								
								embassy-rp/src/dma.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								embassy-rp/src/dma.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
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);
 | 
			
		||||
		Reference in New Issue
	
	Block a user