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
|
||||
(("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)),
|
||||
(("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
|
||||
(("dac", "CH1"), quote!(crate::dac::Dma)),
|
||||
(("dac", "CH2"), quote!(crate::dac::Dma)),
|
||||
]
|
||||
.into();
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||
|
||||
use crate::dma::{slice_ptr_parts, word, Transfer};
|
||||
use crate::pac::dac;
|
||||
use crate::rcc::RccPeripheral;
|
||||
use crate::{peripherals, Peripheral};
|
||||
@ -97,39 +98,58 @@ pub enum Value {
|
||||
Bit12(u16, Alignment),
|
||||
}
|
||||
|
||||
pub struct Dac<'d, T: Instance> {
|
||||
pub struct Dac<'d, T: Instance, Tx> {
|
||||
channels: u8,
|
||||
txdma: PeripheralRef<'d, Tx>,
|
||||
_peri: PeripheralRef<'d, T>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Dac<'d, T> {
|
||||
pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self {
|
||||
impl<'d, T: Instance, Tx> Dac<'d, T, Tx> {
|
||||
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);
|
||||
Self::new_inner(peri, 1)
|
||||
Self::new_inner(peri, 1, txdma)
|
||||
}
|
||||
|
||||
pub fn new_2ch(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
txdma: impl Peripheral<P = Tx> + 'd,
|
||||
_ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
|
||||
_ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
|
||||
) -> Self {
|
||||
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::reset();
|
||||
|
||||
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| {
|
||||
for ch in 0..channels {
|
||||
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
|
||||
@ -215,6 +235,47 @@ impl<'d, T: Instance> Dac<'d, T> {
|
||||
}
|
||||
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 {
|
||||
@ -224,6 +285,7 @@ pub(crate) mod sealed {
|
||||
}
|
||||
|
||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
|
||||
dma_trait!(Dma, Instance);
|
||||
|
||||
pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
|
||||
|
Loading…
Reference in New Issue
Block a user