implement mwe of a DMA write() method for DAC
This commit is contained in:
		
							parent
							
								
									ec36225f8a
								
							
						
					
					
						commit
						f5d084552d
					
				@ -699,6 +699,8 @@ fn main() {
 | 
				
			|||||||
        // SDMMCv1 uses the same channel for both directions, so just implement for RX
 | 
					        // SDMMCv1 uses the same channel for both directions, so just implement for RX
 | 
				
			||||||
        (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)),
 | 
					        (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)),
 | 
				
			||||||
        (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
 | 
					        (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
 | 
				
			||||||
 | 
					        (("dac", "CH1"), quote!(crate::dac::Dma)),
 | 
				
			||||||
 | 
					        (("dac", "CH2"), quote!(crate::dac::Dma)),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
    .into();
 | 
					    .into();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use embassy_hal_common::{into_ref, PeripheralRef};
 | 
					use embassy_hal_common::{into_ref, PeripheralRef};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::dma::{slice_ptr_parts, word, Transfer};
 | 
				
			||||||
use crate::pac::dac;
 | 
					use crate::pac::dac;
 | 
				
			||||||
use crate::rcc::RccPeripheral;
 | 
					use crate::rcc::RccPeripheral;
 | 
				
			||||||
use crate::{peripherals, Peripheral};
 | 
					use crate::{peripherals, Peripheral};
 | 
				
			||||||
@ -97,39 +98,58 @@ pub enum Value {
 | 
				
			|||||||
    Bit12(u16, Alignment),
 | 
					    Bit12(u16, Alignment),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Dac<'d, T: Instance> {
 | 
					pub struct Dac<'d, T: Instance, Tx> {
 | 
				
			||||||
    channels: u8,
 | 
					    channels: u8,
 | 
				
			||||||
 | 
					    txdma: PeripheralRef<'d, Tx>,
 | 
				
			||||||
    _peri: PeripheralRef<'d, T>,
 | 
					    _peri: PeripheralRef<'d, T>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'d, T: Instance> Dac<'d, T> {
 | 
					impl<'d, T: Instance, Tx> Dac<'d, T, Tx> {
 | 
				
			||||||
    pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self {
 | 
					    pub fn new_1ch(
 | 
				
			||||||
 | 
					        peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
 | 
					        txdma: impl Peripheral<P = Tx> + 'd,
 | 
				
			||||||
 | 
					        _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
 | 
				
			||||||
 | 
					    ) -> Self {
 | 
				
			||||||
        into_ref!(peri);
 | 
					        into_ref!(peri);
 | 
				
			||||||
        Self::new_inner(peri, 1)
 | 
					        Self::new_inner(peri, 1, txdma)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_2ch(
 | 
					    pub fn new_2ch(
 | 
				
			||||||
        peri: impl Peripheral<P = T> + 'd,
 | 
					        peri: impl Peripheral<P = T> + 'd,
 | 
				
			||||||
 | 
					        txdma: impl Peripheral<P = Tx> + 'd,
 | 
				
			||||||
        _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
 | 
					        _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
 | 
				
			||||||
        _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
 | 
					        _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
 | 
				
			||||||
    ) -> Self {
 | 
					    ) -> Self {
 | 
				
			||||||
        into_ref!(peri);
 | 
					        into_ref!(peri);
 | 
				
			||||||
        Self::new_inner(peri, 2)
 | 
					        Self::new_inner(peri, 2, txdma)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self {
 | 
					    fn new_inner(peri: PeripheralRef<'d, T>, channels: u8, txdma: impl Peripheral<P = Tx> + 'd) -> Self {
 | 
				
			||||||
 | 
					        into_ref!(txdma);
 | 
				
			||||||
        T::enable();
 | 
					        T::enable();
 | 
				
			||||||
        T::reset();
 | 
					        T::reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsafe {
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            T::regs().mcr().modify(|reg| {
 | 
				
			||||||
 | 
					                for ch in 0..channels {
 | 
				
			||||||
 | 
					                    reg.set_mode(ch as usize, 0);
 | 
				
			||||||
 | 
					                    reg.set_mode(ch as usize, 0);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            T::regs().cr().modify(|reg| {
 | 
					            T::regs().cr().modify(|reg| {
 | 
				
			||||||
                for ch in 0..channels {
 | 
					                for ch in 0..channels {
 | 
				
			||||||
                    reg.set_en(ch as usize, true);
 | 
					                    reg.set_en(ch as usize, true);
 | 
				
			||||||
 | 
					                    reg.set_ten(ch as usize, true);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self { channels, _peri: peri }
 | 
					        Self {
 | 
				
			||||||
 | 
					            channels,
 | 
				
			||||||
 | 
					            txdma,
 | 
				
			||||||
 | 
					            _peri: peri,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Check the channel is configured
 | 
					    /// Check the channel is configured
 | 
				
			||||||
@ -215,6 +235,47 @@ impl<'d, T: Instance> Dac<'d, T> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// TODO: Allow an array of Value instead of only u16, right-aligned
 | 
				
			||||||
 | 
					    pub async fn write(&mut self, data: &[u16]) -> Result<(), Error>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Tx: Dma<T>,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // TODO: Make this a parameter or get it from the struct or so...
 | 
				
			||||||
 | 
					        const CHANNEL: usize = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //debug!("Starting DAC");
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            T::regs().cr().modify(|w| {
 | 
				
			||||||
 | 
					                w.set_en(CHANNEL, true);
 | 
				
			||||||
 | 
					                w.set_dmaen(CHANNEL, true);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let tx_request = self.txdma.request();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Use the 12 bit right-aligned register for now. TODO: distinguish values
 | 
				
			||||||
 | 
					        let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //debug!("Awaiting tx_f");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tx_f.await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // finish dma
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            // TODO: Do we need to check any status registers here?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            T::regs().cr().modify(|w| {
 | 
				
			||||||
 | 
					                // Disable the dac peripheral
 | 
				
			||||||
 | 
					                //w.set_en(CHANNEL, false);
 | 
				
			||||||
 | 
					                // Disable the DMA. TODO: Is this necessary?
 | 
				
			||||||
 | 
					                //w.set_dmaen(CHANNEL, false);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(crate) mod sealed {
 | 
					pub(crate) mod sealed {
 | 
				
			||||||
@ -224,6 +285,7 @@ pub(crate) mod sealed {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
 | 
					pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
 | 
				
			||||||
 | 
					dma_trait!(Dma, Instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
 | 
					pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user