aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-03-25 21:31:28 +0100
committerDario Nieuwenhuis <[email protected]>2025-03-25 21:31:28 +0100
commit73ec3a7506f48bc76bc462a83213992436b55eb7 (patch)
tree59ccd69076e0a302f777c06291351a9b182b2b87
parentf007b53db3b850e1186f9cde26160951b14ba2e7 (diff)
stm32/dac: remove DMA generic params.
-rw-r--r--embassy-stm32/src/dac/mod.rs330
-rw-r--r--examples/stm32f4/src/bin/dac.rs3
-rw-r--r--examples/stm32h7/src/bin/dac.rs3
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs7
-rw-r--r--examples/stm32l4/src/bin/dac.rs3
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs7
-rw-r--r--examples/stm32u0/src/bin/dac.rs3
-rw-r--r--tests/stm32/src/bin/dac.rs3
-rw-r--r--tests/stm32/src/bin/dac_l1.rs3
9 files changed, 214 insertions, 148 deletions
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 4406f2960..7a63dc5fc 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -3,9 +3,10 @@
3 3
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5 5
6use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::into_ref;
7 7
8use crate::dma::NoDma; 8use crate::dma::ChannelAndRequest;
9use crate::mode::{Async, Blocking, Mode as PeriMode};
9#[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] 10#[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
10use crate::pac::dac; 11use crate::pac::dac;
11use crate::rcc::{self, RccPeripheral}; 12use crate::rcc::{self, RccPeripheral};
@@ -100,22 +101,20 @@ pub enum ValueArray<'a> {
100/// 101///
101/// If you want to use both channels, either together or independently, 102/// If you want to use both channels, either together or independently,
102/// create a [`Dac`] first and use it to access each channel. 103/// create a [`Dac`] first and use it to access each channel.
103pub struct DacChannel<'d, T: Instance, C: Channel, DMA = NoDma> { 104pub struct DacChannel<'d, T: Instance, C: Channel, M: PeriMode> {
104 phantom: PhantomData<&'d mut (T, C)>, 105 phantom: PhantomData<&'d mut (T, C, M)>,
105 #[allow(unused)] 106 #[allow(unused)]
106 dma: PeripheralRef<'d, DMA>, 107 dma: Option<ChannelAndRequest<'d>>,
107} 108}
108 109
109/// DAC channel 1 type alias. 110/// DAC channel 1 type alias.
110pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch1, DMA>; 111pub type DacCh1<'d, T, M> = DacChannel<'d, T, Ch1, M>;
111/// DAC channel 2 type alias. 112/// DAC channel 2 type alias.
112pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch2, DMA>; 113pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>;
113 114
114impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> { 115impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Async> {
115 /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral. 116 /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
116 /// 117 ///
117 /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
118 ///
119 /// The channel is enabled on creation and begin to drive the output pin. 118 /// The channel is enabled on creation and begin to drive the output pin.
120 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will 119 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
121 /// disable the channel; you must re-enable it with `enable()`. 120 /// disable the channel; you must re-enable it with `enable()`.
@@ -123,21 +122,18 @@ impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> {
123 /// By default, triggering is disabled, but it can be enabled using 122 /// By default, triggering is disabled, but it can be enabled using
124 /// [`DacChannel::set_trigger()`]. 123 /// [`DacChannel::set_trigger()`].
125 pub fn new( 124 pub fn new(
126 _peri: impl Peripheral<P = T> + 'd, 125 peri: impl Peripheral<P = T> + 'd,
127 dma: impl Peripheral<P = DMA> + 'd, 126 dma: impl Peripheral<P = impl Dma<T, C>> + 'd,
128 pin: impl Peripheral<P = impl DacPin<T, C> + crate::gpio::Pin> + 'd, 127 pin: impl Peripheral<P = impl DacPin<T, C>> + 'd,
129 ) -> Self { 128 ) -> Self {
130 into_ref!(dma, pin); 129 into_ref!(dma, pin);
131 pin.set_as_analog(); 130 pin.set_as_analog();
132 rcc::enable_and_reset::<T>(); 131 Self::new_inner(
133 let mut dac = Self { 132 peri,
134 phantom: PhantomData, 133 new_dma!(dma),
135 dma, 134 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
136 }; 135 Mode::NormalExternalBuffered,
137 #[cfg(any(dac_v5, dac_v6, dac_v7))] 136 )
138 dac.set_hfsel();
139 dac.enable();
140 dac
141 } 137 }
142 138
143 /// Create a new `DacChannel` instance where the external output pin is not used, 139 /// Create a new `DacChannel` instance where the external output pin is not used,
@@ -148,13 +144,99 @@ impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> {
148 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the 144 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
149 /// channel; you must re-enable it with `enable()`. 145 /// channel; you must re-enable it with `enable()`.
150 /// 146 ///
151 /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
152 ///
153 /// By default, triggering is disabled, but it can be enabled using 147 /// By default, triggering is disabled, but it can be enabled using
154 /// [`DacChannel::set_trigger()`]. 148 /// [`DacChannel::set_trigger()`].
155 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] 149 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))]
156 pub fn new_internal(_peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = DMA> + 'd) -> Self { 150 pub fn new_internal(peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Dma<T, C>> + 'd) -> Self {
157 into_ref!(dma); 151 into_ref!(dma);
152 Self::new_inner(peri, new_dma!(dma), Mode::NormalInternalUnbuffered)
153 }
154
155 /// Write `data` to this channel via DMA.
156 ///
157 /// To prevent delays or glitches when outputing a periodic waveform, the `circular`
158 /// flag can be set. This configures a circular DMA transfer that continually outputs
159 /// `data`. Note that for performance reasons in circular mode the transfer-complete
160 /// interrupt is disabled.
161 #[cfg(not(gpdma))]
162 pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) {
163 // Enable DAC and DMA
164 T::regs().cr().modify(|w| {
165 w.set_en(C::IDX, true);
166 w.set_dmaen(C::IDX, true);
167 });
168
169 let dma = self.dma.as_mut().unwrap();
170
171 let tx_options = crate::dma::TransferOptions {
172 circular,
173 half_transfer_ir: false,
174 complete_transfer_ir: !circular,
175 ..Default::default()
176 };
177
178 // Initiate the correct type of DMA transfer depending on what data is passed
179 let tx_f = match data {
180 ValueArray::Bit8(buf) => unsafe { dma.write(buf, T::regs().dhr8r(C::IDX).as_ptr() as *mut u8, tx_options) },
181 ValueArray::Bit12Left(buf) => unsafe {
182 dma.write(buf, T::regs().dhr12l(C::IDX).as_ptr() as *mut u16, tx_options)
183 },
184 ValueArray::Bit12Right(buf) => unsafe {
185 dma.write(buf, T::regs().dhr12r(C::IDX).as_ptr() as *mut u16, tx_options)
186 },
187 };
188
189 tx_f.await;
190
191 T::regs().cr().modify(|w| {
192 w.set_en(C::IDX, false);
193 w.set_dmaen(C::IDX, false);
194 });
195 }
196}
197
198impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Blocking> {
199 /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
200 ///
201 /// The channel is enabled on creation and begin to drive the output pin.
202 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
203 /// disable the channel; you must re-enable it with `enable()`.
204 ///
205 /// By default, triggering is disabled, but it can be enabled using
206 /// [`DacChannel::set_trigger()`].
207 pub fn new_blocking(peri: impl Peripheral<P = T> + 'd, pin: impl Peripheral<P = impl DacPin<T, C>> + 'd) -> Self {
208 into_ref!(pin);
209 pin.set_as_analog();
210 Self::new_inner(
211 peri,
212 None,
213 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
214 Mode::NormalExternalBuffered,
215 )
216 }
217
218 /// Create a new `DacChannel` instance where the external output pin is not used,
219 /// so the DAC can only be used to generate internal signals.
220 /// The GPIO pin is therefore available to be used for other functions.
221 ///
222 /// The channel is set to [`Mode::NormalInternalUnbuffered`] and enabled on creation.
223 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
224 /// channel; you must re-enable it with `enable()`.
225 ///
226 /// By default, triggering is disabled, but it can be enabled using
227 /// [`DacChannel::set_trigger()`].
228 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))]
229 pub fn new_internal_blocking(peri: impl Peripheral<P = T> + 'd) -> Self {
230 Self::new_inner(peri, None, Mode::NormalInternalUnbuffered)
231 }
232}
233
234impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> {
235 fn new_inner(
236 _peri: impl Peripheral<P = T> + 'd,
237 dma: Option<ChannelAndRequest<'d>>,
238 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode,
239 ) -> Self {
158 rcc::enable_and_reset::<T>(); 240 rcc::enable_and_reset::<T>();
159 let mut dac = Self { 241 let mut dac = Self {
160 phantom: PhantomData, 242 phantom: PhantomData,
@@ -162,7 +244,8 @@ impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> {
162 }; 244 };
163 #[cfg(any(dac_v5, dac_v6, dac_v7))] 245 #[cfg(any(dac_v5, dac_v6, dac_v7))]
164 dac.set_hfsel(); 246 dac.set_hfsel();
165 dac.set_mode(Mode::NormalInternalUnbuffered); 247 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
248 dac.set_mode(mode);
166 dac.enable(); 249 dac.enable();
167 dac 250 dac
168 } 251 }
@@ -275,75 +358,9 @@ impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> {
275 }); 358 });
276 } 359 }
277 } 360 }
278
279 /// Write `data` to this channel via DMA.
280 ///
281 /// To prevent delays or glitches when outputing a periodic waveform, the `circular`
282 /// flag can be set. This configures a circular DMA transfer that continually outputs
283 /// `data`. Note that for performance reasons in circular mode the transfer-complete
284 /// interrupt is disabled.
285 #[cfg(not(gpdma))]
286 pub async fn write(&mut self, data: ValueArray<'_>, circular: bool)
287 where
288 DMA: Dma<T, C>,
289 {
290 // Enable DAC and DMA
291 T::regs().cr().modify(|w| {
292 w.set_en(C::IDX, true);
293 w.set_dmaen(C::IDX, true);
294 });
295
296 let tx_request = self.dma.request();
297 let dma_channel = &mut self.dma;
298
299 let tx_options = crate::dma::TransferOptions {
300 circular,
301 half_transfer_ir: false,
302 complete_transfer_ir: !circular,
303 ..Default::default()
304 };
305
306 // Initiate the correct type of DMA transfer depending on what data is passed
307 let tx_f = match data {
308 ValueArray::Bit8(buf) => unsafe {
309 crate::dma::Transfer::new_write(
310 dma_channel,
311 tx_request,
312 buf,
313 T::regs().dhr8r(C::IDX).as_ptr() as *mut u8,
314 tx_options,
315 )
316 },
317 ValueArray::Bit12Left(buf) => unsafe {
318 crate::dma::Transfer::new_write(
319 dma_channel,
320 tx_request,
321 buf,
322 T::regs().dhr12l(C::IDX).as_ptr() as *mut u16,
323 tx_options,
324 )
325 },
326 ValueArray::Bit12Right(buf) => unsafe {
327 crate::dma::Transfer::new_write(
328 dma_channel,
329 tx_request,
330 buf,
331 T::regs().dhr12r(C::IDX).as_ptr() as *mut u16,
332 tx_options,
333 )
334 },
335 };
336
337 tx_f.await;
338
339 T::regs().cr().modify(|w| {
340 w.set_en(C::IDX, false);
341 w.set_dmaen(C::IDX, false);
342 });
343 }
344} 361}
345 362
346impl<'d, T: Instance, C: Channel, DMA> Drop for DacChannel<'d, T, C, DMA> { 363impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> {
347 fn drop(&mut self) { 364 fn drop(&mut self) {
348 rcc::disable::<T>(); 365 rcc::disable::<T>();
349 } 366 }
@@ -357,14 +374,14 @@ impl<'d, T: Instance, C: Channel, DMA> Drop for DacChannel<'d, T, C, DMA> {
357/// 374///
358/// ```ignore 375/// ```ignore
359/// // Pins may need to be changed for your specific device. 376/// // Pins may need to be changed for your specific device.
360/// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, NoDma, NoDma, p.PA4, p.PA5).split(); 377/// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new_blocking(p.DAC1, p.PA4, p.PA5).split();
361/// ``` 378/// ```
362pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> { 379pub struct Dac<'d, T: Instance, M: PeriMode> {
363 ch1: DacChannel<'d, T, Ch1, DMACh1>, 380 ch1: DacChannel<'d, T, Ch1, M>,
364 ch2: DacChannel<'d, T, Ch2, DMACh2>, 381 ch2: DacChannel<'d, T, Ch2, M>,
365} 382}
366 383
367impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { 384impl<'d, T: Instance> Dac<'d, T, Async> {
368 /// Create a new `Dac` instance, consuming the underlying DAC peripheral. 385 /// Create a new `Dac` instance, consuming the underlying DAC peripheral.
369 /// 386 ///
370 /// This struct allows you to access both channels of the DAC, where available. You can either 387 /// This struct allows you to access both channels of the DAC, where available. You can either
@@ -378,37 +395,82 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
378 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` 395 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
379 /// method on the underlying channels. 396 /// method on the underlying channels.
380 pub fn new( 397 pub fn new(
381 _peri: impl Peripheral<P = T> + 'd, 398 peri: impl Peripheral<P = T> + 'd,
382 dma_ch1: impl Peripheral<P = DMACh1> + 'd, 399 dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd,
383 dma_ch2: impl Peripheral<P = DMACh2> + 'd, 400 dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd,
384 pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd, 401 pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd,
385 pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd, 402 pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd,
386 ) -> Self { 403 ) -> Self {
387 into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); 404 into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2);
388 pin_ch1.set_as_analog(); 405 pin_ch1.set_as_analog();
389 pin_ch2.set_as_analog(); 406 pin_ch2.set_as_analog();
407 Self::new_inner(
408 peri,
409 new_dma!(dma_ch1),
410 new_dma!(dma_ch2),
411 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
412 Mode::NormalExternalBuffered,
413 )
414 }
390 415
391 // Enable twice to increment the DAC refcount for each channel. 416 /// Create a new `Dac` instance where the external output pins are not used,
392 rcc::enable_and_reset::<T>(); 417 /// so the DAC can only be used to generate internal signals but the GPIO
393 rcc::enable_and_reset::<T>(); 418 /// pins remain available for other functions.
394 419 ///
395 let mut ch1 = DacCh1 { 420 /// This struct allows you to access both channels of the DAC, where available. You can either
396 phantom: PhantomData, 421 /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use the two
397 dma: dma_ch1, 422 /// channels together.
398 }; 423 ///
399 #[cfg(any(dac_v5, dac_v6, dac_v7))] 424 /// The channels are set to [`Mode::NormalInternalUnbuffered`] and enabled on creation.
400 ch1.set_hfsel(); 425 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
401 ch1.enable(); 426 /// channel; you must re-enable them with `enable()`.
402 427 ///
403 let mut ch2 = DacCh2 { 428 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
404 phantom: PhantomData, 429 /// method on the underlying channels.
405 dma: dma_ch2, 430 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))]
406 }; 431 pub fn new_internal(
407 #[cfg(any(dac_v5, dac_v6, dac_v7))] 432 peri: impl Peripheral<P = T> + 'd,
408 ch2.set_hfsel(); 433 dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd,
409 ch2.enable(); 434 dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd,
435 ) -> Self {
436 into_ref!(dma_ch1, dma_ch2);
437 Self::new_inner(
438 peri,
439 new_dma!(dma_ch1),
440 new_dma!(dma_ch2),
441 Mode::NormalInternalUnbuffered,
442 )
443 }
444}
410 445
411 Self { ch1, ch2 } 446impl<'d, T: Instance> Dac<'d, T, Blocking> {
447 /// Create a new `Dac` instance, consuming the underlying DAC peripheral.
448 ///
449 /// This struct allows you to access both channels of the DAC, where available. You can either
450 /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use
451 /// the two channels together.
452 ///
453 /// The channels are enabled on creation and begin to drive their output pins.
454 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
455 /// disable the channel; you must re-enable them with `enable()`.
456 ///
457 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
458 /// method on the underlying channels.
459 pub fn new_blocking(
460 peri: impl Peripheral<P = T> + 'd,
461 pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd,
462 pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd,
463 ) -> Self {
464 into_ref!(pin_ch1, pin_ch2);
465 pin_ch1.set_as_analog();
466 pin_ch2.set_as_analog();
467 Self::new_inner(
468 peri,
469 None,
470 None,
471 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
472 Mode::NormalExternalBuffered,
473 )
412 } 474 }
413 475
414 /// Create a new `Dac` instance where the external output pins are not used, 476 /// Create a new `Dac` instance where the external output pins are not used,
@@ -426,12 +488,18 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
426 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` 488 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
427 /// method on the underlying channels. 489 /// method on the underlying channels.
428 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] 490 #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))]
429 pub fn new_internal( 491 pub fn new_internal(peri: impl Peripheral<P = T> + 'd) -> Self {
492 Self::new_inner(peri, None, None, Mode::NormalInternalUnbuffered)
493 }
494}
495
496impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> {
497 fn new_inner(
430 _peri: impl Peripheral<P = T> + 'd, 498 _peri: impl Peripheral<P = T> + 'd,
431 dma_ch1: impl Peripheral<P = DMACh1> + 'd, 499 dma_ch1: Option<ChannelAndRequest<'d>>,
432 dma_ch2: impl Peripheral<P = DMACh2> + 'd, 500 dma_ch2: Option<ChannelAndRequest<'d>>,
501 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode,
433 ) -> Self { 502 ) -> Self {
434 into_ref!(dma_ch1, dma_ch2);
435 // Enable twice to increment the DAC refcount for each channel. 503 // Enable twice to increment the DAC refcount for each channel.
436 rcc::enable_and_reset::<T>(); 504 rcc::enable_and_reset::<T>();
437 rcc::enable_and_reset::<T>(); 505 rcc::enable_and_reset::<T>();
@@ -442,7 +510,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
442 }; 510 };
443 #[cfg(any(dac_v5, dac_v6, dac_v7))] 511 #[cfg(any(dac_v5, dac_v6, dac_v7))]
444 ch1.set_hfsel(); 512 ch1.set_hfsel();
445 ch1.set_mode(Mode::NormalInternalUnbuffered); 513 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
514 ch1.set_mode(mode);
446 ch1.enable(); 515 ch1.enable();
447 516
448 let mut ch2 = DacCh2 { 517 let mut ch2 = DacCh2 {
@@ -451,7 +520,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
451 }; 520 };
452 #[cfg(any(dac_v5, dac_v6, dac_v7))] 521 #[cfg(any(dac_v5, dac_v6, dac_v7))]
453 ch2.set_hfsel(); 522 ch2.set_hfsel();
454 ch2.set_mode(Mode::NormalInternalUnbuffered); 523 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
524 ch2.set_mode(mode);
455 ch2.enable(); 525 ch2.enable();
456 526
457 Self { ch1, ch2 } 527 Self { ch1, ch2 }
@@ -460,17 +530,17 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
460 /// Split this `Dac` into separate channels. 530 /// Split this `Dac` into separate channels.
461 /// 531 ///
462 /// You can access and move the channels around separately after splitting. 532 /// You can access and move the channels around separately after splitting.
463 pub fn split(self) -> (DacCh1<'d, T, DMACh1>, DacCh2<'d, T, DMACh2>) { 533 pub fn split(self) -> (DacCh1<'d, T, M>, DacCh2<'d, T, M>) {
464 (self.ch1, self.ch2) 534 (self.ch1, self.ch2)
465 } 535 }
466 536
467 /// Temporarily access channel 1. 537 /// Temporarily access channel 1.
468 pub fn ch1(&mut self) -> &mut DacCh1<'d, T, DMACh1> { 538 pub fn ch1(&mut self) -> &mut DacCh1<'d, T, M> {
469 &mut self.ch1 539 &mut self.ch1
470 } 540 }
471 541
472 /// Temporarily access channel 2. 542 /// Temporarily access channel 2.
473 pub fn ch2(&mut self) -> &mut DacCh2<'d, T, DMACh2> { 543 pub fn ch2(&mut self) -> &mut DacCh2<'d, T, M> {
474 &mut self.ch2 544 &mut self.ch2
475 } 545 }
476 546
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs
index dd2a45718..68fe6cabd 100644
--- a/examples/stm32f4/src/bin/dac.rs
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, Value}; 6use embassy_stm32::dac::{DacCh1, Value};
7use embassy_stm32::dma::NoDma;
8use {defmt_rtt as _, panic_probe as _}; 7use {defmt_rtt as _, panic_probe as _};
9 8
10#[embassy_executor::main] 9#[embassy_executor::main]
@@ -12,7 +11,7 @@ async fn main(_spawner: Spawner) -> ! {
12 let p = embassy_stm32::init(Default::default()); 11 let p = embassy_stm32::init(Default::default());
13 info!("Hello World, dude!"); 12 info!("Hello World, dude!");
14 13
15 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); 14 let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4);
16 15
17 loop { 16 loop {
18 for v in 0..=255 { 17 for v in 0..=255 {
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index a6f969aba..27df80336 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -4,7 +4,6 @@
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dac::{DacCh1, Value}; 6use embassy_stm32::dac::{DacCh1, Value};
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::Config; 7use embassy_stm32::Config;
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
@@ -44,7 +43,7 @@ fn main() -> ! {
44 } 43 }
45 let p = embassy_stm32::init(config); 44 let p = embassy_stm32::init(config);
46 45
47 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); 46 let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4);
48 47
49 loop { 48 loop {
50 for v in 0..=255 { 49 for v in 0..=255 {
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index 3a9887e3c..98c9f1e90 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -4,8 +4,9 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async;
7use embassy_stm32::pac::timer::vals::Mms; 8use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 9use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
9use embassy_stm32::rcc::frequency; 10use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::Timer; 12use embassy_stm32::timer::low_level::Timer;
@@ -56,7 +57,7 @@ async fn main(spawner: Spawner) {
56} 57}
57 58
58#[embassy_executor::task] 59#[embassy_executor::task]
59async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 60async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) {
60 let data: &[u8; 256] = &calculate_array::<256>(); 61 let data: &[u8; 256] = &calculate_array::<256>();
61 62
62 info!("TIM6 frequency is {}", frequency::<TIM6>()); 63 info!("TIM6 frequency is {}", frequency::<TIM6>());
@@ -99,7 +100,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
99} 100}
100 101
101#[embassy_executor::task] 102#[embassy_executor::task]
102async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 103async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) {
103 let data: &[u8; 256] = &calculate_array::<256>(); 104 let data: &[u8; 256] = &calculate_array::<256>();
104 105
105 info!("TIM7 frequency is {}", frequency::<TIM6>()); 106 info!("TIM7 frequency is {}", frequency::<TIM6>());
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index fdbf1d374..50db0e082 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -3,7 +3,6 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::dac::{DacCh1, Value}; 5use embassy_stm32::dac::{DacCh1, Value};
6use embassy_stm32::dma::NoDma;
7use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
8 7
9#[cortex_m_rt::entry] 8#[cortex_m_rt::entry]
@@ -11,7 +10,7 @@ fn main() -> ! {
11 let p = embassy_stm32::init(Default::default()); 10 let p = embassy_stm32::init(Default::default());
12 info!("Hello World!"); 11 info!("Hello World!");
13 12
14 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); 13 let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4);
15 14
16 loop { 15 loop {
17 for v in 0..=255 { 16 for v in 0..=255 {
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
index d01b016c0..6c9219080 100644
--- a/examples/stm32l4/src/bin/dac_dma.rs
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -4,8 +4,9 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async;
7use embassy_stm32::pac::timer::vals::Mms; 8use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 9use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
9use embassy_stm32::rcc::frequency; 10use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::Timer; 12use embassy_stm32::timer::low_level::Timer;
@@ -27,7 +28,7 @@ async fn main(spawner: Spawner) {
27} 28}
28 29
29#[embassy_executor::task] 30#[embassy_executor::task]
30async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 31async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) {
31 let data: &[u8; 256] = &calculate_array::<256>(); 32 let data: &[u8; 256] = &calculate_array::<256>();
32 33
33 info!("TIM6 frequency is {}", frequency::<TIM6>()); 34 info!("TIM6 frequency is {}", frequency::<TIM6>());
@@ -70,7 +71,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) {
70} 71}
71 72
72#[embassy_executor::task] 73#[embassy_executor::task]
73async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 74async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) {
74 let data: &[u8; 256] = &calculate_array::<256>(); 75 let data: &[u8; 256] = &calculate_array::<256>();
75 76
76 info!("TIM7 frequency is {}", frequency::<TIM7>()); 77 info!("TIM7 frequency is {}", frequency::<TIM7>());
diff --git a/examples/stm32u0/src/bin/dac.rs b/examples/stm32u0/src/bin/dac.rs
index fdbf1d374..50db0e082 100644
--- a/examples/stm32u0/src/bin/dac.rs
+++ b/examples/stm32u0/src/bin/dac.rs
@@ -3,7 +3,6 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::dac::{DacCh1, Value}; 5use embassy_stm32::dac::{DacCh1, Value};
6use embassy_stm32::dma::NoDma;
7use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
8 7
9#[cortex_m_rt::entry] 8#[cortex_m_rt::entry]
@@ -11,7 +10,7 @@ fn main() -> ! {
11 let p = embassy_stm32::init(Default::default()); 10 let p = embassy_stm32::init(Default::default());
12 info!("Hello World!"); 11 info!("Hello World!");
13 12
14 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); 13 let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4);
15 14
16 loop { 15 loop {
17 for v in 0..=255 { 16 for v in 0..=255 {
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs
index 88e661525..d34bbb255 100644
--- a/tests/stm32/src/bin/dac.rs
+++ b/tests/stm32/src/bin/dac.rs
@@ -12,7 +12,6 @@ use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::Adc;
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::dma::NoDma;
16use embassy_time::Timer; 15use embassy_time::Timer;
17use micromath::F32Ext; 16use micromath::F32Ext;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
@@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) {
27 let dac_pin = peri!(p, DAC_PIN); 26 let dac_pin = peri!(p, DAC_PIN);
28 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; 27 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) };
29 28
30 let mut dac = DacCh1::new(dac, NoDma, dac_pin); 29 let mut dac = DacCh1::new_blocking(dac, dac_pin);
31 let mut adc = Adc::new(adc); 30 let mut adc = Adc::new(adc);
32 31
33 #[cfg(feature = "stm32h755zi")] 32 #[cfg(feature = "stm32h755zi")]
diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs
index 925db617d..e6400f28e 100644
--- a/tests/stm32/src/bin/dac_l1.rs
+++ b/tests/stm32/src/bin/dac_l1.rs
@@ -12,7 +12,6 @@ use defmt::assert;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::Adc;
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::dma::NoDma;
16use embassy_stm32::{bind_interrupts, peripherals}; 15use embassy_stm32::{bind_interrupts, peripherals};
17use embassy_time::Timer; 16use embassy_time::Timer;
18use micromath::F32Ext; 17use micromath::F32Ext;
@@ -32,7 +31,7 @@ async fn main(_spawner: Spawner) {
32 let dac_pin = peri!(p, DAC_PIN); 31 let dac_pin = peri!(p, DAC_PIN);
33 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; 32 let mut adc_pin = unsafe { core::ptr::read(&dac_pin) };
34 33
35 let mut dac = DacCh1::new(dac, NoDma, dac_pin); 34 let mut dac = DacCh1::new_blocking(dac, dac_pin);
36 let mut adc = Adc::new(adc, Irqs); 35 let mut adc = Adc::new(adc, Irqs);
37 36
38 #[cfg(feature = "stm32h755zi")] 37 #[cfg(feature = "stm32h755zi")]