aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuliDi <[email protected]>2023-06-17 11:48:21 +0200
committerJuliDi <[email protected]>2023-06-17 11:48:21 +0200
commitf5d084552d9f44d24f020269cc605de0fb4d1041 (patch)
treee7574b0f9e0b20402a330e3e8013ab749c0c9cfe
parentec36225f8ab35fab149971e587ef506aa1c9d1ca (diff)
implement mwe of a DMA write() method for DAC
-rw-r--r--embassy-stm32/build.rs2
-rw-r--r--embassy-stm32/src/dac/mod.rs (renamed from embassy-stm32/src/dac.rs)76
2 files changed, 71 insertions, 7 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 9e597f187..e2bd01d7b 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -699,6 +699,8 @@ fn main() {
699 // SDMMCv1 uses the same channel for both directions, so just implement for RX 699 // SDMMCv1 uses the same channel for both directions, so just implement for RX
700 (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)), 700 (("sdmmc", "RX"), quote!(crate::sdmmc::SdmmcDma)),
701 (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), 701 (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
702 (("dac", "CH1"), quote!(crate::dac::Dma)),
703 (("dac", "CH2"), quote!(crate::dac::Dma)),
702 ] 704 ]
703 .into(); 705 .into();
704 706
diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac/mod.rs
index 60e856c78..348d8bccd 100644
--- a/embassy-stm32/src/dac.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -2,6 +2,7 @@
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
4 4
5use crate::dma::{slice_ptr_parts, word, Transfer};
5use crate::pac::dac; 6use crate::pac::dac;
6use crate::rcc::RccPeripheral; 7use crate::rcc::RccPeripheral;
7use crate::{peripherals, Peripheral}; 8use crate::{peripherals, Peripheral};
@@ -97,39 +98,58 @@ pub enum Value {
97 Bit12(u16, Alignment), 98 Bit12(u16, Alignment),
98} 99}
99 100
100pub struct Dac<'d, T: Instance> { 101pub struct Dac<'d, T: Instance, Tx> {
101 channels: u8, 102 channels: u8,
103 txdma: PeripheralRef<'d, Tx>,
102 _peri: PeripheralRef<'d, T>, 104 _peri: PeripheralRef<'d, T>,
103} 105}
104 106
105impl<'d, T: Instance> Dac<'d, T> { 107impl<'d, T: Instance, Tx> Dac<'d, T, Tx> {
106 pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self { 108 pub fn new_1ch(
109 peri: impl Peripheral<P = T> + 'd,
110 txdma: impl Peripheral<P = Tx> + 'd,
111 _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
112 ) -> Self {
107 into_ref!(peri); 113 into_ref!(peri);
108 Self::new_inner(peri, 1) 114 Self::new_inner(peri, 1, txdma)
109 } 115 }
110 116
111 pub fn new_2ch( 117 pub fn new_2ch(
112 peri: impl Peripheral<P = T> + 'd, 118 peri: impl Peripheral<P = T> + 'd,
119 txdma: impl Peripheral<P = Tx> + 'd,
113 _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, 120 _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
114 _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, 121 _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
115 ) -> Self { 122 ) -> Self {
116 into_ref!(peri); 123 into_ref!(peri);
117 Self::new_inner(peri, 2) 124 Self::new_inner(peri, 2, txdma)
118 } 125 }
119 126
120 fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self { 127 fn new_inner(peri: PeripheralRef<'d, T>, channels: u8, txdma: impl Peripheral<P = Tx> + 'd) -> Self {
128 into_ref!(txdma);
121 T::enable(); 129 T::enable();
122 T::reset(); 130 T::reset();
123 131
124 unsafe { 132 unsafe {
133 T::regs().mcr().modify(|reg| {
134 for ch in 0..channels {
135 reg.set_mode(ch as usize, 0);
136 reg.set_mode(ch as usize, 0);
137 }
138 });
139
125 T::regs().cr().modify(|reg| { 140 T::regs().cr().modify(|reg| {
126 for ch in 0..channels { 141 for ch in 0..channels {
127 reg.set_en(ch as usize, true); 142 reg.set_en(ch as usize, true);
143 reg.set_ten(ch as usize, true);
128 } 144 }
129 }); 145 });
130 } 146 }
131 147
132 Self { channels, _peri: peri } 148 Self {
149 channels,
150 txdma,
151 _peri: peri,
152 }
133 } 153 }
134 154
135 /// Check the channel is configured 155 /// Check the channel is configured
@@ -215,6 +235,47 @@ impl<'d, T: Instance> Dac<'d, T> {
215 } 235 }
216 Ok(()) 236 Ok(())
217 } 237 }
238
239 /// TODO: Allow an array of Value instead of only u16, right-aligned
240 pub async fn write(&mut self, data: &[u16]) -> Result<(), Error>
241 where
242 Tx: Dma<T>,
243 {
244 // TODO: Make this a parameter or get it from the struct or so...
245 const CHANNEL: usize = 0;
246
247 //debug!("Starting DAC");
248 unsafe {
249 T::regs().cr().modify(|w| {
250 w.set_en(CHANNEL, true);
251 w.set_dmaen(CHANNEL, true);
252 });
253 }
254
255 let tx_request = self.txdma.request();
256
257 // Use the 12 bit right-aligned register for now. TODO: distinguish values
258 let tx_dst = T::regs().dhr12r(CHANNEL).ptr() as *mut u16;
259
260 let tx_f = unsafe { Transfer::new_write(&mut self.txdma, tx_request, data, tx_dst, Default::default()) };
261
262 //debug!("Awaiting tx_f");
263
264 tx_f.await;
265
266 // finish dma
267 unsafe {
268 // TODO: Do we need to check any status registers here?
269
270 T::regs().cr().modify(|w| {
271 // Disable the dac peripheral
272 //w.set_en(CHANNEL, false);
273 // Disable the DMA. TODO: Is this necessary?
274 //w.set_dmaen(CHANNEL, false);
275 });
276 }
277 Ok(())
278 }
218} 279}
219 280
220pub(crate) mod sealed { 281pub(crate) mod sealed {
@@ -224,6 +285,7 @@ pub(crate) mod sealed {
224} 285}
225 286
226pub trait Instance: sealed::Instance + RccPeripheral + 'static {} 287pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
288dma_trait!(Dma, Instance);
227 289
228pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} 290pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
229 291