diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-03-25 21:31:28 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-03-25 21:31:28 +0100 |
| commit | 73ec3a7506f48bc76bc462a83213992436b55eb7 (patch) | |
| tree | 59ccd69076e0a302f777c06291351a9b182b2b87 | |
| parent | f007b53db3b850e1186f9cde26160951b14ba2e7 (diff) | |
stm32/dac: remove DMA generic params.
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 330 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/dac_dma.rs | 7 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/dac_dma.rs | 7 | ||||
| -rw-r--r-- | examples/stm32u0/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/dac_l1.rs | 3 |
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 | ||
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 5 | 5 | ||
| 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 6 | use embassy_hal_internal::into_ref; |
| 7 | 7 | ||
| 8 | use crate::dma::NoDma; | 8 | use crate::dma::ChannelAndRequest; |
| 9 | use 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))] |
| 10 | use crate::pac::dac; | 11 | use crate::pac::dac; |
| 11 | use crate::rcc::{self, RccPeripheral}; | 12 | use 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. |
| 103 | pub struct DacChannel<'d, T: Instance, C: Channel, DMA = NoDma> { | 104 | pub 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. |
| 110 | pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch1, DMA>; | 111 | pub type DacCh1<'d, T, M> = DacChannel<'d, T, Ch1, M>; |
| 111 | /// DAC channel 2 type alias. | 112 | /// DAC channel 2 type alias. |
| 112 | pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch2, DMA>; | 113 | pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>; |
| 113 | 114 | ||
| 114 | impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> { | 115 | impl<'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 | |||
| 198 | impl<'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 | |||
| 234 | impl<'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 | ||
| 346 | impl<'d, T: Instance, C: Channel, DMA> Drop for DacChannel<'d, T, C, DMA> { | 363 | impl<'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 | /// ``` |
| 362 | pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> { | 379 | pub 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 | ||
| 367 | impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | 384 | impl<'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 } | 446 | impl<'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 | |||
| 496 | impl<'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 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, Value}; | 6 | use embassy_stm32::dac::{DacCh1, Value}; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {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 @@ | |||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_stm32::dac::{DacCh1, Value}; | 6 | use embassy_stm32::dac::{DacCh1, Value}; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {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 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | ||
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 8 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 9 | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::frequency; | 10 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::Timer; | 12 | use 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] |
| 59 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 60 | async 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] |
| 102 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 103 | async 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 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::dac::{DacCh1, Value}; | 5 | use embassy_stm32::dac::{DacCh1, Value}; |
| 6 | use embassy_stm32::dma::NoDma; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {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 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | ||
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 8 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 9 | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::frequency; | 10 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::Timer; | 12 | use 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] |
| 30 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 31 | async 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] |
| 73 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 74 | async 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 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::dac::{DacCh1, Value}; | 5 | use embassy_stm32::dac::{DacCh1, Value}; |
| 6 | use embassy_stm32::dma::NoDma; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {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; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::Adc; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_stm32::dma::NoDma; | ||
| 16 | use embassy_time::Timer; | 15 | use embassy_time::Timer; |
| 17 | use micromath::F32Ext; | 16 | use micromath::F32Ext; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {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; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::Adc; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_stm32::dma::NoDma; | ||
| 16 | use embassy_stm32::{bind_interrupts, peripherals}; | 15 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 17 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| 18 | use micromath::F32Ext; | 17 | use 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")] |
