Merge pull request #4005 from embassy-rs/no-nodma
stm32: remove DMA generic params, remove NoDma.
This commit is contained in:
		
						commit
						4f250f3995
					
				| @ -1151,6 +1151,8 @@ fn main() { | |||||||
|         (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), |         (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), | ||||||
|         (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), |         (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), | ||||||
|         (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), |         (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), | ||||||
|  |         (("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)), | ||||||
|  |         (("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)), | ||||||
|     ].into(); |     ].into(); | ||||||
| 
 | 
 | ||||||
|     for p in METADATA.peripherals { |     for p in METADATA.peripherals { | ||||||
| @ -1250,17 +1252,6 @@ fn main() { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // DAC is special
 |  | ||||||
|                 if regs.kind == "dac" { |  | ||||||
|                     let peri = format_ident!("{}", p.name); |  | ||||||
|                     let pin_name = format_ident!("{}", pin.pin); |  | ||||||
|                     let ch: u8 = pin.signal.strip_prefix("OUT").unwrap().parse().unwrap(); |  | ||||||
| 
 |  | ||||||
|                     g.extend(quote! { |  | ||||||
|                     impl_dac_pin!( #peri, #pin_name, #ch); |  | ||||||
|                     }) |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if regs.kind == "spdifrx" { |                 if regs.kind == "spdifrx" { | ||||||
|                     let peri = format_ident!("{}", p.name); |                     let peri = format_ident!("{}", p.name); | ||||||
|                     let pin_name = format_ident!("{}", pin.pin); |                     let pin_name = format_ident!("{}", pin.pin); | ||||||
| @ -1304,8 +1295,8 @@ fn main() { | |||||||
|         (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), |         (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), | ||||||
|         (("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)), |         (("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)), | ||||||
|         (("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)), |         (("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)), | ||||||
|         (("dac", "CH1"), quote!(crate::dac::DacDma1)), |         (("dac", "CH1"), quote!(crate::dac::Dma<Ch1>)), | ||||||
|         (("dac", "CH2"), quote!(crate::dac::DacDma2)), |         (("dac", "CH2"), quote!(crate::dac::Dma<Ch2>)), | ||||||
|         (("timer", "UP"), quote!(crate::timer::UpDma)), |         (("timer", "UP"), quote!(crate::timer::UpDma)), | ||||||
|         (("hash", "IN"), quote!(crate::hash::Dma)), |         (("hash", "IN"), quote!(crate::hash::Dma)), | ||||||
|         (("cryp", "IN"), quote!(crate::cryp::DmaIn)), |         (("cryp", "IN"), quote!(crate::cryp::DmaIn)), | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3,9 +3,10 @@ | |||||||
| 
 | 
 | ||||||
| use core::marker::PhantomData; | use core::marker::PhantomData; | ||||||
| 
 | 
 | ||||||
| use embassy_hal_internal::{into_ref, PeripheralRef}; | use embassy_hal_internal::into_ref; | ||||||
| 
 | 
 | ||||||
| use crate::dma::NoDma; | use crate::dma::ChannelAndRequest; | ||||||
|  | use crate::mode::{Async, Blocking, Mode as PeriMode}; | ||||||
| #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
| use crate::pac::dac; | use crate::pac::dac; | ||||||
| use crate::rcc::{self, RccPeripheral}; | use crate::rcc::{self, RccPeripheral}; | ||||||
| @ -100,24 +101,20 @@ pub enum ValueArray<'a> { | |||||||
| ///
 | ///
 | ||||||
| /// If you want to use both channels, either together or independently,
 | /// If you want to use both channels, either together or independently,
 | ||||||
| /// create a [`Dac`] first and use it to access each channel.
 | /// create a [`Dac`] first and use it to access each channel.
 | ||||||
| pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> { | pub struct DacChannel<'d, T: Instance, C: Channel, M: PeriMode> { | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut (T, C, M)>, | ||||||
|     #[allow(unused)] |     #[allow(unused)] | ||||||
|     dma: PeripheralRef<'d, DMA>, |     dma: Option<ChannelAndRequest<'d>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// DAC channel 1 type alias.
 | /// DAC channel 1 type alias.
 | ||||||
| pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; | pub type DacCh1<'d, T, M> = DacChannel<'d, T, Ch1, M>; | ||||||
| /// DAC channel 2 type alias.
 | /// DAC channel 2 type alias.
 | ||||||
| pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; | pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>; | ||||||
| 
 |  | ||||||
| impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { |  | ||||||
|     const IDX: usize = (N - 1) as usize; |  | ||||||
| 
 | 
 | ||||||
|  | impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Async> { | ||||||
|     /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
 |     /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
 |  | ||||||
|     ///
 |  | ||||||
|     /// The channel is enabled on creation and begin to drive the output pin.
 |     /// The channel is enabled on creation and begin to drive the output pin.
 | ||||||
|     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
 |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
 | ||||||
|     /// disable the channel; you must re-enable it with `enable()`.
 |     /// disable the channel; you must re-enable it with `enable()`.
 | ||||||
| @ -125,21 +122,18 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     /// By default, triggering is disabled, but it can be enabled using
 |     /// By default, triggering is disabled, but it can be enabled using
 | ||||||
|     /// [`DacChannel::set_trigger()`].
 |     /// [`DacChannel::set_trigger()`].
 | ||||||
|     pub fn new( |     pub fn new( | ||||||
|         _peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma: impl Peripheral<P = DMA> + 'd, |         dma: impl Peripheral<P = impl Dma<T, C>> + 'd, | ||||||
|         pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd, |         pin: impl Peripheral<P = impl DacPin<T, C>> + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         into_ref!(dma, pin); |         into_ref!(dma, pin); | ||||||
|         pin.set_as_analog(); |         pin.set_as_analog(); | ||||||
|         rcc::enable_and_reset::<T>(); |         Self::new_inner( | ||||||
|         let mut dac = Self { |             peri, | ||||||
|             phantom: PhantomData, |             new_dma!(dma), | ||||||
|             dma, |             #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|         }; |             Mode::NormalExternalBuffered, | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |         ) | ||||||
|         dac.set_hfsel(); |  | ||||||
|         dac.enable(); |  | ||||||
|         dac |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Create a new `DacChannel` instance where the external output pin is not used,
 |     /// Create a new `DacChannel` instance where the external output pin is not used,
 | ||||||
| @ -150,13 +144,99 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
 |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
 | ||||||
|     /// channel; you must re-enable it with `enable()`.
 |     /// channel; you must re-enable it with `enable()`.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
 |     /// By default, triggering is disabled, but it can be enabled using
 | ||||||
|  |     /// [`DacChannel::set_trigger()`].
 | ||||||
|  |     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | ||||||
|  |     pub fn new_internal(peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Dma<T, C>> + 'd) -> Self { | ||||||
|  |         into_ref!(dma); | ||||||
|  |         Self::new_inner(peri, new_dma!(dma), Mode::NormalInternalUnbuffered) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Write `data` to this channel via DMA.
 | ||||||
|  |     ///
 | ||||||
|  |     /// To prevent delays or glitches when outputing a periodic waveform, the `circular`
 | ||||||
|  |     /// flag can be set. This configures a circular DMA transfer that continually outputs
 | ||||||
|  |     /// `data`. Note that for performance reasons in circular mode the transfer-complete
 | ||||||
|  |     /// interrupt is disabled.
 | ||||||
|  |     #[cfg(not(gpdma))] | ||||||
|  |     pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) { | ||||||
|  |         // Enable DAC and DMA
 | ||||||
|  |         T::regs().cr().modify(|w| { | ||||||
|  |             w.set_en(C::IDX, true); | ||||||
|  |             w.set_dmaen(C::IDX, true); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         let dma = self.dma.as_mut().unwrap(); | ||||||
|  | 
 | ||||||
|  |         let tx_options = crate::dma::TransferOptions { | ||||||
|  |             circular, | ||||||
|  |             half_transfer_ir: false, | ||||||
|  |             complete_transfer_ir: !circular, | ||||||
|  |             ..Default::default() | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // Initiate the correct type of DMA transfer depending on what data is passed
 | ||||||
|  |         let tx_f = match data { | ||||||
|  |             ValueArray::Bit8(buf) => unsafe { dma.write(buf, T::regs().dhr8r(C::IDX).as_ptr() as *mut u8, tx_options) }, | ||||||
|  |             ValueArray::Bit12Left(buf) => unsafe { | ||||||
|  |                 dma.write(buf, T::regs().dhr12l(C::IDX).as_ptr() as *mut u16, tx_options) | ||||||
|  |             }, | ||||||
|  |             ValueArray::Bit12Right(buf) => unsafe { | ||||||
|  |                 dma.write(buf, T::regs().dhr12r(C::IDX).as_ptr() as *mut u16, tx_options) | ||||||
|  |             }, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         tx_f.await; | ||||||
|  | 
 | ||||||
|  |         T::regs().cr().modify(|w| { | ||||||
|  |             w.set_en(C::IDX, false); | ||||||
|  |             w.set_dmaen(C::IDX, false); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Blocking> { | ||||||
|  |     /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The channel is enabled on creation and begin to drive the output pin.
 | ||||||
|  |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
 | ||||||
|  |     /// disable the channel; you must re-enable it with `enable()`.
 | ||||||
|  |     ///
 | ||||||
|  |     /// By default, triggering is disabled, but it can be enabled using
 | ||||||
|  |     /// [`DacChannel::set_trigger()`].
 | ||||||
|  |     pub fn new_blocking(peri: impl Peripheral<P = T> + 'd, pin: impl Peripheral<P = impl DacPin<T, C>> + 'd) -> Self { | ||||||
|  |         into_ref!(pin); | ||||||
|  |         pin.set_as_analog(); | ||||||
|  |         Self::new_inner( | ||||||
|  |             peri, | ||||||
|  |             None, | ||||||
|  |             #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|  |             Mode::NormalExternalBuffered, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Create a new `DacChannel` instance where the external output pin is not used,
 | ||||||
|  |     /// so the DAC can only be used to generate internal signals.
 | ||||||
|  |     /// The GPIO pin is therefore available to be used for other functions.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The channel is set to [`Mode::NormalInternalUnbuffered`] and enabled on creation.
 | ||||||
|  |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
 | ||||||
|  |     /// channel; you must re-enable it with `enable()`.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// By default, triggering is disabled, but it can be enabled using
 |     /// By default, triggering is disabled, but it can be enabled using
 | ||||||
|     /// [`DacChannel::set_trigger()`].
 |     /// [`DacChannel::set_trigger()`].
 | ||||||
|     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] |     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | ||||||
|     pub fn new_internal(_peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = DMA> + 'd) -> Self { |     pub fn new_internal_blocking(peri: impl Peripheral<P = T> + 'd) -> Self { | ||||||
|         into_ref!(dma); |         Self::new_inner(peri, None, Mode::NormalInternalUnbuffered) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> { | ||||||
|  |     fn new_inner( | ||||||
|  |         _peri: impl Peripheral<P = T> + 'd, | ||||||
|  |         dma: Option<ChannelAndRequest<'d>>, | ||||||
|  |         #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode, | ||||||
|  |     ) -> Self { | ||||||
|         rcc::enable_and_reset::<T>(); |         rcc::enable_and_reset::<T>(); | ||||||
|         let mut dac = Self { |         let mut dac = Self { | ||||||
|             phantom: PhantomData, |             phantom: PhantomData, | ||||||
| @ -164,7 +244,8 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|         }; |         }; | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |         #[cfg(any(dac_v5, dac_v6, dac_v7))] | ||||||
|         dac.set_hfsel(); |         dac.set_hfsel(); | ||||||
|         dac.set_mode(Mode::NormalInternalUnbuffered); |         #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|  |         dac.set_mode(mode); | ||||||
|         dac.enable(); |         dac.enable(); | ||||||
|         dac |         dac | ||||||
|     } |     } | ||||||
| @ -173,7 +254,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     pub fn set_enable(&mut self, on: bool) { |     pub fn set_enable(&mut self, on: bool) { | ||||||
|         critical_section::with(|_| { |         critical_section::with(|_| { | ||||||
|             T::regs().cr().modify(|reg| { |             T::regs().cr().modify(|reg| { | ||||||
|                 reg.set_en(Self::IDX, on); |                 reg.set_en(C::IDX, on); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -194,8 +275,8 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     pub fn set_trigger(&mut self, source: TriggerSel) { |     pub fn set_trigger(&mut self, source: TriggerSel) { | ||||||
|         critical_section::with(|_| { |         critical_section::with(|_| { | ||||||
|             T::regs().cr().modify(|reg| { |             T::regs().cr().modify(|reg| { | ||||||
|                 reg.set_en(Self::IDX, false); |                 reg.set_en(C::IDX, false); | ||||||
|                 reg.set_tsel(Self::IDX, source as u8); |                 reg.set_tsel(C::IDX, source as u8); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -204,7 +285,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     pub fn set_triggering(&mut self, on: bool) { |     pub fn set_triggering(&mut self, on: bool) { | ||||||
|         critical_section::with(|_| { |         critical_section::with(|_| { | ||||||
|             T::regs().cr().modify(|reg| { |             T::regs().cr().modify(|reg| { | ||||||
|                 reg.set_ten(Self::IDX, on); |                 reg.set_ten(C::IDX, on); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -212,7 +293,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     /// Software trigger this channel.
 |     /// Software trigger this channel.
 | ||||||
|     pub fn trigger(&mut self) { |     pub fn trigger(&mut self) { | ||||||
|         T::regs().swtrigr().write(|reg| { |         T::regs().swtrigr().write(|reg| { | ||||||
|             reg.set_swtrig(Self::IDX, true); |             reg.set_swtrig(C::IDX, true); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -223,10 +304,10 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     pub fn set_mode(&mut self, mode: Mode) { |     pub fn set_mode(&mut self, mode: Mode) { | ||||||
|         critical_section::with(|_| { |         critical_section::with(|_| { | ||||||
|             T::regs().cr().modify(|reg| { |             T::regs().cr().modify(|reg| { | ||||||
|                 reg.set_en(Self::IDX, false); |                 reg.set_en(C::IDX, false); | ||||||
|             }); |             }); | ||||||
|             T::regs().mcr().modify(|reg| { |             T::regs().mcr().modify(|reg| { | ||||||
|                 reg.set_mode(Self::IDX, mode.mode()); |                 reg.set_mode(C::IDX, mode.mode()); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -237,15 +318,15 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     /// it will be output after the next trigger.
 |     /// it will be output after the next trigger.
 | ||||||
|     pub fn set(&mut self, value: Value) { |     pub fn set(&mut self, value: Value) { | ||||||
|         match value { |         match value { | ||||||
|             Value::Bit8(v) => T::regs().dhr8r(Self::IDX).write(|reg| reg.set_dhr(v)), |             Value::Bit8(v) => T::regs().dhr8r(C::IDX).write(|reg| reg.set_dhr(v)), | ||||||
|             Value::Bit12Left(v) => T::regs().dhr12l(Self::IDX).write(|reg| reg.set_dhr(v)), |             Value::Bit12Left(v) => T::regs().dhr12l(C::IDX).write(|reg| reg.set_dhr(v)), | ||||||
|             Value::Bit12Right(v) => T::regs().dhr12r(Self::IDX).write(|reg| reg.set_dhr(v)), |             Value::Bit12Right(v) => T::regs().dhr12r(C::IDX).write(|reg| reg.set_dhr(v)), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Read the current output value of the DAC.
 |     /// Read the current output value of the DAC.
 | ||||||
|     pub fn read(&self) -> u16 { |     pub fn read(&self) -> u16 { | ||||||
|         T::regs().dor(Self::IDX).read().dor() |         T::regs().dor(C::IDX).read().dor() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Set HFSEL as appropriate for the current peripheral clock frequency.
 |     /// Set HFSEL as appropriate for the current peripheral clock frequency.
 | ||||||
| @ -279,82 +360,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| macro_rules! impl_dma_methods { | impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> { | ||||||
|     ($n:literal, $trait:ident) => { |  | ||||||
|         impl<'d, T: Instance, DMA> DacChannel<'d, T, $n, DMA> |  | ||||||
|         where |  | ||||||
|             DMA: $trait<T>, |  | ||||||
|         { |  | ||||||
|             /// Write `data` to this channel via DMA.
 |  | ||||||
|             ///
 |  | ||||||
|             /// To prevent delays or glitches when outputing a periodic waveform, the `circular`
 |  | ||||||
|             /// flag can be set. This configures a circular DMA transfer that continually outputs
 |  | ||||||
|             /// `data`. Note that for performance reasons in circular mode the transfer-complete
 |  | ||||||
|             /// interrupt is disabled.
 |  | ||||||
|             #[cfg(not(gpdma))] |  | ||||||
|             pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) { |  | ||||||
|                 // Enable DAC and DMA
 |  | ||||||
|                 T::regs().cr().modify(|w| { |  | ||||||
|                     w.set_en(Self::IDX, true); |  | ||||||
|                     w.set_dmaen(Self::IDX, true); |  | ||||||
|                 }); |  | ||||||
| 
 |  | ||||||
|                 let tx_request = self.dma.request(); |  | ||||||
|                 let dma_channel = &mut self.dma; |  | ||||||
| 
 |  | ||||||
|                 let tx_options = crate::dma::TransferOptions { |  | ||||||
|                     circular, |  | ||||||
|                     half_transfer_ir: false, |  | ||||||
|                     complete_transfer_ir: !circular, |  | ||||||
|                     ..Default::default() |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 // Initiate the correct type of DMA transfer depending on what data is passed
 |  | ||||||
|                 let tx_f = match data { |  | ||||||
|                     ValueArray::Bit8(buf) => unsafe { |  | ||||||
|                         crate::dma::Transfer::new_write( |  | ||||||
|                             dma_channel, |  | ||||||
|                             tx_request, |  | ||||||
|                             buf, |  | ||||||
|                             T::regs().dhr8r(Self::IDX).as_ptr() as *mut u8, |  | ||||||
|                             tx_options, |  | ||||||
|                         ) |  | ||||||
|                     }, |  | ||||||
|                     ValueArray::Bit12Left(buf) => unsafe { |  | ||||||
|                         crate::dma::Transfer::new_write( |  | ||||||
|                             dma_channel, |  | ||||||
|                             tx_request, |  | ||||||
|                             buf, |  | ||||||
|                             T::regs().dhr12l(Self::IDX).as_ptr() as *mut u16, |  | ||||||
|                             tx_options, |  | ||||||
|                         ) |  | ||||||
|                     }, |  | ||||||
|                     ValueArray::Bit12Right(buf) => unsafe { |  | ||||||
|                         crate::dma::Transfer::new_write( |  | ||||||
|                             dma_channel, |  | ||||||
|                             tx_request, |  | ||||||
|                             buf, |  | ||||||
|                             T::regs().dhr12r(Self::IDX).as_ptr() as *mut u16, |  | ||||||
|                             tx_options, |  | ||||||
|                         ) |  | ||||||
|                     }, |  | ||||||
|                 }; |  | ||||||
| 
 |  | ||||||
|                 tx_f.await; |  | ||||||
| 
 |  | ||||||
|                 T::regs().cr().modify(|w| { |  | ||||||
|                     w.set_en(Self::IDX, false); |  | ||||||
|                     w.set_dmaen(Self::IDX, false); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl_dma_methods!(1, DacDma1); |  | ||||||
| impl_dma_methods!(2, DacDma2); |  | ||||||
| 
 |  | ||||||
| impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> { |  | ||||||
|     fn drop(&mut self) { |     fn drop(&mut self) { | ||||||
|         rcc::disable::<T>(); |         rcc::disable::<T>(); | ||||||
|     } |     } | ||||||
| @ -368,14 +374,14 @@ impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> { | |||||||
| ///
 | ///
 | ||||||
| /// ```ignore
 | /// ```ignore
 | ||||||
| /// // Pins may need to be changed for your specific device.
 | /// // Pins may need to be changed for your specific device.
 | ||||||
| /// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, NoDma, NoDma, p.PA4, p.PA5).split();
 | /// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new_blocking(p.DAC1, p.PA4, p.PA5).split();
 | ||||||
| /// ```
 | /// ```
 | ||||||
| pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> { | pub struct Dac<'d, T: Instance, M: PeriMode> { | ||||||
|     ch1: DacChannel<'d, T, 1, DMACh1>, |     ch1: DacChannel<'d, T, Ch1, M>, | ||||||
|     ch2: DacChannel<'d, T, 2, DMACh2>, |     ch2: DacChannel<'d, T, Ch2, M>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | impl<'d, T: Instance> Dac<'d, T, Async> { | ||||||
|     /// Create a new `Dac` instance, consuming the underlying DAC peripheral.
 |     /// Create a new `Dac` instance, consuming the underlying DAC peripheral.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// This struct allows you to access both channels of the DAC, where available. You can either
 |     /// This struct allows you to access both channels of the DAC, where available. You can either
 | ||||||
| @ -389,37 +395,22 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||||||
|     /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
 |     /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
 | ||||||
|     /// method on the underlying channels.
 |     /// method on the underlying channels.
 | ||||||
|     pub fn new( |     pub fn new( | ||||||
|         _peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma_ch1: impl Peripheral<P = DMACh1> + 'd, |         dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, | ||||||
|         dma_ch2: impl Peripheral<P = DMACh2> + 'd, |         dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd, | ||||||
|         pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd, |         pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd, | ||||||
|         pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd, |         pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); |         into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); | ||||||
|         pin_ch1.set_as_analog(); |         pin_ch1.set_as_analog(); | ||||||
|         pin_ch2.set_as_analog(); |         pin_ch2.set_as_analog(); | ||||||
| 
 |         Self::new_inner( | ||||||
|         // Enable twice to increment the DAC refcount for each channel.
 |             peri, | ||||||
|         rcc::enable_and_reset::<T>(); |             new_dma!(dma_ch1), | ||||||
|         rcc::enable_and_reset::<T>(); |             new_dma!(dma_ch2), | ||||||
| 
 |             #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|         let mut ch1 = DacCh1 { |             Mode::NormalExternalBuffered, | ||||||
|             phantom: PhantomData, |         ) | ||||||
|             dma: dma_ch1, |  | ||||||
|         }; |  | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |  | ||||||
|         ch1.set_hfsel(); |  | ||||||
|         ch1.enable(); |  | ||||||
| 
 |  | ||||||
|         let mut ch2 = DacCh2 { |  | ||||||
|             phantom: PhantomData, |  | ||||||
|             dma: dma_ch2, |  | ||||||
|         }; |  | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |  | ||||||
|         ch2.set_hfsel(); |  | ||||||
|         ch2.enable(); |  | ||||||
| 
 |  | ||||||
|         Self { ch1, ch2 } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Create a new `Dac` instance where the external output pins are not used,
 |     /// Create a new `Dac` instance where the external output pins are not used,
 | ||||||
| @ -438,11 +429,77 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||||||
|     /// method on the underlying channels.
 |     /// method on the underlying channels.
 | ||||||
|     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] |     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | ||||||
|     pub fn new_internal( |     pub fn new_internal( | ||||||
|         _peri: impl Peripheral<P = T> + 'd, |         peri: impl Peripheral<P = T> + 'd, | ||||||
|         dma_ch1: impl Peripheral<P = DMACh1> + 'd, |         dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, | ||||||
|         dma_ch2: impl Peripheral<P = DMACh2> + 'd, |         dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         into_ref!(dma_ch1, dma_ch2); |         into_ref!(dma_ch1, dma_ch2); | ||||||
|  |         Self::new_inner( | ||||||
|  |             peri, | ||||||
|  |             new_dma!(dma_ch1), | ||||||
|  |             new_dma!(dma_ch2), | ||||||
|  |             Mode::NormalInternalUnbuffered, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance> Dac<'d, T, Blocking> { | ||||||
|  |     /// Create a new `Dac` instance, consuming the underlying DAC peripheral.
 | ||||||
|  |     ///
 | ||||||
|  |     /// This struct allows you to access both channels of the DAC, where available. You can either
 | ||||||
|  |     /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use
 | ||||||
|  |     /// the two channels together.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The channels are enabled on creation and begin to drive their output pins.
 | ||||||
|  |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
 | ||||||
|  |     /// disable the channel; you must re-enable them with `enable()`.
 | ||||||
|  |     ///
 | ||||||
|  |     /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
 | ||||||
|  |     /// method on the underlying channels.
 | ||||||
|  |     pub fn new_blocking( | ||||||
|  |         peri: impl Peripheral<P = T> + 'd, | ||||||
|  |         pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd, | ||||||
|  |         pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd, | ||||||
|  |     ) -> Self { | ||||||
|  |         into_ref!(pin_ch1, pin_ch2); | ||||||
|  |         pin_ch1.set_as_analog(); | ||||||
|  |         pin_ch2.set_as_analog(); | ||||||
|  |         Self::new_inner( | ||||||
|  |             peri, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|  |             Mode::NormalExternalBuffered, | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Create a new `Dac` instance where the external output pins are not used,
 | ||||||
|  |     /// so the DAC can only be used to generate internal signals but the GPIO
 | ||||||
|  |     /// pins remain available for other functions.
 | ||||||
|  |     ///
 | ||||||
|  |     /// This struct allows you to access both channels of the DAC, where available. You can either
 | ||||||
|  |     /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use the two
 | ||||||
|  |     /// channels together.
 | ||||||
|  |     ///
 | ||||||
|  |     /// The channels are set to [`Mode::NormalInternalUnbuffered`] and enabled on creation.
 | ||||||
|  |     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the
 | ||||||
|  |     /// channel; you must re-enable them with `enable()`.
 | ||||||
|  |     ///
 | ||||||
|  |     /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
 | ||||||
|  |     /// method on the underlying channels.
 | ||||||
|  |     #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | ||||||
|  |     pub fn new_internal(peri: impl Peripheral<P = T> + 'd) -> Self { | ||||||
|  |         Self::new_inner(peri, None, None, Mode::NormalInternalUnbuffered) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> { | ||||||
|  |     fn new_inner( | ||||||
|  |         _peri: impl Peripheral<P = T> + 'd, | ||||||
|  |         dma_ch1: Option<ChannelAndRequest<'d>>, | ||||||
|  |         dma_ch2: Option<ChannelAndRequest<'d>>, | ||||||
|  |         #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode, | ||||||
|  |     ) -> Self { | ||||||
|         // Enable twice to increment the DAC refcount for each channel.
 |         // Enable twice to increment the DAC refcount for each channel.
 | ||||||
|         rcc::enable_and_reset::<T>(); |         rcc::enable_and_reset::<T>(); | ||||||
|         rcc::enable_and_reset::<T>(); |         rcc::enable_and_reset::<T>(); | ||||||
| @ -453,7 +510,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||||||
|         }; |         }; | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |         #[cfg(any(dac_v5, dac_v6, dac_v7))] | ||||||
|         ch1.set_hfsel(); |         ch1.set_hfsel(); | ||||||
|         ch1.set_mode(Mode::NormalInternalUnbuffered); |         #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|  |         ch1.set_mode(mode); | ||||||
|         ch1.enable(); |         ch1.enable(); | ||||||
| 
 | 
 | ||||||
|         let mut ch2 = DacCh2 { |         let mut ch2 = DacCh2 { | ||||||
| @ -462,7 +520,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||||||
|         }; |         }; | ||||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] |         #[cfg(any(dac_v5, dac_v6, dac_v7))] | ||||||
|         ch2.set_hfsel(); |         ch2.set_hfsel(); | ||||||
|         ch2.set_mode(Mode::NormalInternalUnbuffered); |         #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||||||
|  |         ch2.set_mode(mode); | ||||||
|         ch2.enable(); |         ch2.enable(); | ||||||
| 
 | 
 | ||||||
|         Self { ch1, ch2 } |         Self { ch1, ch2 } | ||||||
| @ -471,17 +530,17 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||||||
|     /// Split this `Dac` into separate channels.
 |     /// Split this `Dac` into separate channels.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// You can access and move the channels around separately after splitting.
 |     /// You can access and move the channels around separately after splitting.
 | ||||||
|     pub fn split(self) -> (DacCh1<'d, T, DMACh1>, DacCh2<'d, T, DMACh2>) { |     pub fn split(self) -> (DacCh1<'d, T, M>, DacCh2<'d, T, M>) { | ||||||
|         (self.ch1, self.ch2) |         (self.ch1, self.ch2) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Temporarily access channel 1.
 |     /// Temporarily access channel 1.
 | ||||||
|     pub fn ch1(&mut self) -> &mut DacCh1<'d, T, DMACh1> { |     pub fn ch1(&mut self) -> &mut DacCh1<'d, T, M> { | ||||||
|         &mut self.ch1 |         &mut self.ch1 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Temporarily access channel 2.
 |     /// Temporarily access channel 2.
 | ||||||
|     pub fn ch2(&mut self) -> &mut DacCh2<'d, T, DMACh2> { |     pub fn ch2(&mut self) -> &mut DacCh2<'d, T, M> { | ||||||
|         &mut self.ch2 |         &mut self.ch2 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -514,11 +573,30 @@ trait SealedInstance { | |||||||
| /// DAC instance.
 | /// DAC instance.
 | ||||||
| #[allow(private_bounds)] | #[allow(private_bounds)] | ||||||
| pub trait Instance: SealedInstance + RccPeripheral + 'static {} | pub trait Instance: SealedInstance + RccPeripheral + 'static {} | ||||||
| dma_trait!(DacDma1, Instance); |  | ||||||
| dma_trait!(DacDma2, Instance); |  | ||||||
| 
 | 
 | ||||||
| /// Marks a pin that can be used with the DAC
 | /// Channel 1 marker type.
 | ||||||
| pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | pub enum Ch1 {} | ||||||
|  | /// Channel 2 marker type.
 | ||||||
|  | pub enum Ch2 {} | ||||||
|  | 
 | ||||||
|  | trait SealedChannel { | ||||||
|  |     const IDX: usize; | ||||||
|  | } | ||||||
|  | /// DAC channel trait.
 | ||||||
|  | #[allow(private_bounds)] | ||||||
|  | pub trait Channel: SealedChannel {} | ||||||
|  | 
 | ||||||
|  | impl SealedChannel for Ch1 { | ||||||
|  |     const IDX: usize = 0; | ||||||
|  | } | ||||||
|  | impl SealedChannel for Ch2 { | ||||||
|  |     const IDX: usize = 1; | ||||||
|  | } | ||||||
|  | impl Channel for Ch1 {} | ||||||
|  | impl Channel for Ch2 {} | ||||||
|  | 
 | ||||||
|  | dma_trait!(Dma, Instance, Channel); | ||||||
|  | pin_trait!(DacPin, Instance, Channel); | ||||||
| 
 | 
 | ||||||
| foreach_peripheral!( | foreach_peripheral!( | ||||||
|     (dac, $inst:ident) => { |     (dac, $inst:ident) => { | ||||||
| @ -531,9 +609,3 @@ foreach_peripheral!( | |||||||
|         impl crate::dac::Instance for peripherals::$inst {} |         impl crate::dac::Instance for peripherals::$inst {} | ||||||
|     }; |     }; | ||||||
| ); | ); | ||||||
| 
 |  | ||||||
| macro_rules! impl_dac_pin { |  | ||||||
|     ($inst:ident, $pin:ident, $ch:expr) => { |  | ||||||
|         impl crate::dac::DacPin<peripherals::$inst, $ch> for crate::peripherals::$pin {} |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -108,17 +108,6 @@ impl Channel for AnyChannel {} | |||||||
| const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); | const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); | ||||||
| static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; | static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; | ||||||
| 
 | 
 | ||||||
| /// "No DMA" placeholder.
 |  | ||||||
| ///
 |  | ||||||
| /// You may pass this in place of a real DMA channel when creating a driver
 |  | ||||||
| /// to indicate it should not use DMA.
 |  | ||||||
| ///
 |  | ||||||
| /// This often causes async functionality to not be available on the instance,
 |  | ||||||
| /// leaving only blocking functionality.
 |  | ||||||
| pub struct NoDma; |  | ||||||
| 
 |  | ||||||
| impl_peripheral!(NoDma); |  | ||||||
| 
 |  | ||||||
| // safety: must be called only once at startup
 | // safety: must be called only once at startup
 | ||||||
| pub(crate) unsafe fn init( | pub(crate) unsafe fn init( | ||||||
|     cs: critical_section::CriticalSection, |     cs: critical_section::CriticalSection, | ||||||
|  | |||||||
| @ -39,10 +39,10 @@ impl<'d> ChannelAndRequest<'d> { | |||||||
|         Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) |         Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub unsafe fn write_raw<'a, W: Word>( |     pub unsafe fn write_raw<'a, MW: Word, PW: Word>( | ||||||
|         &'a mut self, |         &'a mut self, | ||||||
|         buf: *const [W], |         buf: *const [MW], | ||||||
|         peri_addr: *mut W, |         peri_addr: *mut PW, | ||||||
|         options: TransferOptions, |         options: TransferOptions, | ||||||
|     ) -> Transfer<'a> { |     ) -> Transfer<'a> { | ||||||
|         Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) |         Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) | ||||||
|  | |||||||
| @ -12,10 +12,12 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||||||
| use embassy_sync::waitqueue::AtomicWaker; | use embassy_sync::waitqueue::AtomicWaker; | ||||||
| use stm32_metapac::hash::regs::*; | use stm32_metapac::hash::regs::*; | ||||||
| 
 | 
 | ||||||
| use crate::dma::NoDma; |  | ||||||
| #[cfg(hash_v2)] | #[cfg(hash_v2)] | ||||||
| use crate::dma::Transfer; | use crate::dma::ChannelAndRequest; | ||||||
| use crate::interrupt::typelevel::Interrupt; | use crate::interrupt::typelevel::Interrupt; | ||||||
|  | #[cfg(hash_v2)] | ||||||
|  | use crate::mode::Async; | ||||||
|  | use crate::mode::{Blocking, Mode}; | ||||||
| use crate::peripherals::HASH; | use crate::peripherals::HASH; | ||||||
| use crate::{interrupt, pac, peripherals, rcc, Peripheral}; | use crate::{interrupt, pac, peripherals, rcc, Peripheral}; | ||||||
| 
 | 
 | ||||||
| @ -116,24 +118,26 @@ pub struct Context<'c> { | |||||||
| type HmacKey<'k> = Option<&'k [u8]>; | type HmacKey<'k> = Option<&'k [u8]>; | ||||||
| 
 | 
 | ||||||
| /// HASH driver.
 | /// HASH driver.
 | ||||||
| pub struct Hash<'d, T: Instance, D = NoDma> { | pub struct Hash<'d, T: Instance, M: Mode> { | ||||||
|     _peripheral: PeripheralRef<'d, T>, |     _peripheral: PeripheralRef<'d, T>, | ||||||
|     #[allow(dead_code)] |     _phantom: PhantomData<M>, | ||||||
|     dma: PeripheralRef<'d, D>, |     #[cfg(hash_v2)] | ||||||
|  |     dma: Option<ChannelAndRequest<'d>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, D> Hash<'d, T, D> { | impl<'d, T: Instance> Hash<'d, T, Blocking> { | ||||||
|     /// Instantiates, resets, and enables the HASH peripheral.
 |     /// Instantiates, resets, and enables the HASH peripheral.
 | ||||||
|     pub fn new( |     pub fn new_blocking( | ||||||
|         peripheral: impl Peripheral<P = T> + 'd, |         peripheral: impl Peripheral<P = T> + 'd, | ||||||
|         dma: impl Peripheral<P = D> + 'd, |  | ||||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         rcc::enable_and_reset::<HASH>(); |         rcc::enable_and_reset::<HASH>(); | ||||||
|         into_ref!(peripheral, dma); |         into_ref!(peripheral); | ||||||
|         let instance = Self { |         let instance = Self { | ||||||
|             _peripheral: peripheral, |             _peripheral: peripheral, | ||||||
|             dma: dma, |             _phantom: PhantomData, | ||||||
|  |             #[cfg(hash_v2)] | ||||||
|  |             dma: None, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         T::Interrupt::unpend(); |         T::Interrupt::unpend(); | ||||||
| @ -141,7 +145,9 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||||||
| 
 | 
 | ||||||
|         instance |         instance | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | impl<'d, T: Instance, M: Mode> Hash<'d, T, M> { | ||||||
|     /// Starts computation of a new hash and returns the saved peripheral state.
 |     /// Starts computation of a new hash and returns the saved peripheral state.
 | ||||||
|     pub fn start<'c>(&mut self, algorithm: Algorithm, format: DataType, key: HmacKey<'c>) -> Context<'c> { |     pub fn start<'c>(&mut self, algorithm: Algorithm, format: DataType, key: HmacKey<'c>) -> Context<'c> { | ||||||
|         // Define a context for this new computation.
 |         // Define a context for this new computation.
 | ||||||
| @ -282,14 +288,136 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||||||
|         self.store_context(ctx); |         self.store_context(ctx); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// Computes a digest for the given context.
 | ||||||
|  |     /// The digest buffer must be large enough to accomodate a digest for the selected algorithm.
 | ||||||
|  |     /// The largest returned digest size is 128 bytes for SHA-512.
 | ||||||
|  |     /// Panics if the supplied digest buffer is too short.
 | ||||||
|  |     pub fn finish_blocking<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { | ||||||
|  |         // Restore the peripheral state.
 | ||||||
|  |         self.load_context(&ctx); | ||||||
|  | 
 | ||||||
|  |         // Hash the leftover bytes, if any.
 | ||||||
|  |         self.accumulate_blocking(&ctx.buffer[0..ctx.buflen]); | ||||||
|  |         ctx.buflen = 0; | ||||||
|  | 
 | ||||||
|  |         //Start the digest calculation.
 | ||||||
|  |         T::regs().str().write(|w| w.set_dcal(true)); | ||||||
|  | 
 | ||||||
|  |         // Load the HMAC key if provided.
 | ||||||
|  |         if let Some(key) = ctx.key { | ||||||
|  |             while !T::regs().sr().read().dinis() {} | ||||||
|  |             self.accumulate_blocking(key); | ||||||
|  |             T::regs().str().write(|w| w.set_dcal(true)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Block until digest computation is complete.
 | ||||||
|  |         while !T::regs().sr().read().dcis() {} | ||||||
|  | 
 | ||||||
|  |         // Return the digest.
 | ||||||
|  |         let digest_words = match ctx.algo { | ||||||
|  |             Algorithm::SHA1 => 5, | ||||||
|  |             #[cfg(any(hash_v1, hash_v2, hash_v4))] | ||||||
|  |             Algorithm::MD5 => 4, | ||||||
|  |             Algorithm::SHA224 => 7, | ||||||
|  |             Algorithm::SHA256 => 8, | ||||||
|  |             #[cfg(hash_v3)] | ||||||
|  |             Algorithm::SHA384 => 12, | ||||||
|  |             #[cfg(hash_v3)] | ||||||
|  |             Algorithm::SHA512_224 => 7, | ||||||
|  |             #[cfg(hash_v3)] | ||||||
|  |             Algorithm::SHA512_256 => 8, | ||||||
|  |             #[cfg(hash_v3)] | ||||||
|  |             Algorithm::SHA512 => 16, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let digest_len_bytes = digest_words * 4; | ||||||
|  |         // Panics if the supplied digest buffer is too short.
 | ||||||
|  |         if digest.len() < digest_len_bytes { | ||||||
|  |             panic!("Digest buffer must be at least {} bytes long.", digest_words * 4); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let mut i = 0; | ||||||
|  |         while i < digest_words { | ||||||
|  |             let word = T::regs().hr(i).read(); | ||||||
|  |             digest[(i * 4)..((i * 4) + 4)].copy_from_slice(word.to_be_bytes().as_slice()); | ||||||
|  |             i += 1; | ||||||
|  |         } | ||||||
|  |         digest_len_bytes | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Push data into the hash core.
 | ||||||
|  |     fn accumulate_blocking(&mut self, input: &[u8]) { | ||||||
|  |         // Set the number of valid bits.
 | ||||||
|  |         let num_valid_bits: u8 = (8 * (input.len() % 4)) as u8; | ||||||
|  |         T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); | ||||||
|  | 
 | ||||||
|  |         let mut i = 0; | ||||||
|  |         while i < input.len() { | ||||||
|  |             let mut word: [u8; 4] = [0; 4]; | ||||||
|  |             let copy_idx = min(i + 4, input.len()); | ||||||
|  |             word[0..copy_idx - i].copy_from_slice(&input[i..copy_idx]); | ||||||
|  |             T::regs().din().write_value(u32::from_ne_bytes(word)); | ||||||
|  |             i += 4; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Save the peripheral state to a context.
 | ||||||
|  |     fn store_context<'c>(&mut self, ctx: &mut Context<'c>) { | ||||||
|  |         // Block waiting for data in ready.
 | ||||||
|  |         while !T::regs().sr().read().dinis() {} | ||||||
|  | 
 | ||||||
|  |         // Store peripheral context.
 | ||||||
|  |         ctx.imr = T::regs().imr().read().0; | ||||||
|  |         ctx.str = T::regs().str().read().0; | ||||||
|  |         ctx.cr = T::regs().cr().read().0; | ||||||
|  |         let mut i = 0; | ||||||
|  |         while i < NUM_CONTEXT_REGS { | ||||||
|  |             ctx.csr[i] = T::regs().csr(i).read(); | ||||||
|  |             i += 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Restore the peripheral state from a context.
 | ||||||
|  |     fn load_context(&mut self, ctx: &Context) { | ||||||
|  |         // Restore the peripheral state from the context.
 | ||||||
|  |         T::regs().imr().write_value(Imr { 0: ctx.imr }); | ||||||
|  |         T::regs().str().write_value(Str { 0: ctx.str }); | ||||||
|  |         T::regs().cr().write_value(Cr { 0: ctx.cr }); | ||||||
|  |         T::regs().cr().modify(|w| w.set_init(true)); | ||||||
|  |         let mut i = 0; | ||||||
|  |         while i < NUM_CONTEXT_REGS { | ||||||
|  |             T::regs().csr(i).write_value(ctx.csr[i]); | ||||||
|  |             i += 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(hash_v2)] | ||||||
|  | impl<'d, T: Instance> Hash<'d, T, Async> { | ||||||
|  |     /// Instantiates, resets, and enables the HASH peripheral.
 | ||||||
|  |     pub fn new( | ||||||
|  |         peripheral: impl Peripheral<P = T> + 'd, | ||||||
|  |         dma: impl Peripheral<P = impl Dma<T>> + 'd, | ||||||
|  |         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||||
|  |     ) -> Self { | ||||||
|  |         rcc::enable_and_reset::<HASH>(); | ||||||
|  |         into_ref!(peripheral, dma); | ||||||
|  |         let instance = Self { | ||||||
|  |             _peripheral: peripheral, | ||||||
|  |             _phantom: PhantomData, | ||||||
|  |             dma: new_dma!(dma), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         T::Interrupt::unpend(); | ||||||
|  |         unsafe { T::Interrupt::enable() }; | ||||||
|  | 
 | ||||||
|  |         instance | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Restores the peripheral state using the given context,
 |     /// Restores the peripheral state using the given context,
 | ||||||
|     /// then updates the state with the provided data.
 |     /// then updates the state with the provided data.
 | ||||||
|     /// Peripheral state is saved upon return.
 |     /// Peripheral state is saved upon return.
 | ||||||
|     #[cfg(hash_v2)] |     pub async fn update(&mut self, ctx: &mut Context<'_>, input: &[u8]) { | ||||||
|     pub async fn update<'c>(&mut self, ctx: &mut Context<'c>, input: &[u8]) |  | ||||||
|     where |  | ||||||
|         D: crate::hash::Dma<T>, |  | ||||||
|     { |  | ||||||
|         // Restore the peripheral state.
 |         // Restore the peripheral state.
 | ||||||
|         self.load_context(&ctx); |         self.load_context(&ctx); | ||||||
| 
 | 
 | ||||||
| @ -353,68 +481,7 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||||||
|     /// The digest buffer must be large enough to accomodate a digest for the selected algorithm.
 |     /// The digest buffer must be large enough to accomodate a digest for the selected algorithm.
 | ||||||
|     /// The largest returned digest size is 128 bytes for SHA-512.
 |     /// The largest returned digest size is 128 bytes for SHA-512.
 | ||||||
|     /// Panics if the supplied digest buffer is too short.
 |     /// Panics if the supplied digest buffer is too short.
 | ||||||
|     pub fn finish_blocking<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { |     pub async fn finish<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { | ||||||
|         // Restore the peripheral state.
 |  | ||||||
|         self.load_context(&ctx); |  | ||||||
| 
 |  | ||||||
|         // Hash the leftover bytes, if any.
 |  | ||||||
|         self.accumulate_blocking(&ctx.buffer[0..ctx.buflen]); |  | ||||||
|         ctx.buflen = 0; |  | ||||||
| 
 |  | ||||||
|         //Start the digest calculation.
 |  | ||||||
|         T::regs().str().write(|w| w.set_dcal(true)); |  | ||||||
| 
 |  | ||||||
|         // Load the HMAC key if provided.
 |  | ||||||
|         if let Some(key) = ctx.key { |  | ||||||
|             while !T::regs().sr().read().dinis() {} |  | ||||||
|             self.accumulate_blocking(key); |  | ||||||
|             T::regs().str().write(|w| w.set_dcal(true)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Block until digest computation is complete.
 |  | ||||||
|         while !T::regs().sr().read().dcis() {} |  | ||||||
| 
 |  | ||||||
|         // Return the digest.
 |  | ||||||
|         let digest_words = match ctx.algo { |  | ||||||
|             Algorithm::SHA1 => 5, |  | ||||||
|             #[cfg(any(hash_v1, hash_v2, hash_v4))] |  | ||||||
|             Algorithm::MD5 => 4, |  | ||||||
|             Algorithm::SHA224 => 7, |  | ||||||
|             Algorithm::SHA256 => 8, |  | ||||||
|             #[cfg(hash_v3)] |  | ||||||
|             Algorithm::SHA384 => 12, |  | ||||||
|             #[cfg(hash_v3)] |  | ||||||
|             Algorithm::SHA512_224 => 7, |  | ||||||
|             #[cfg(hash_v3)] |  | ||||||
|             Algorithm::SHA512_256 => 8, |  | ||||||
|             #[cfg(hash_v3)] |  | ||||||
|             Algorithm::SHA512 => 16, |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let digest_len_bytes = digest_words * 4; |  | ||||||
|         // Panics if the supplied digest buffer is too short.
 |  | ||||||
|         if digest.len() < digest_len_bytes { |  | ||||||
|             panic!("Digest buffer must be at least {} bytes long.", digest_words * 4); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         let mut i = 0; |  | ||||||
|         while i < digest_words { |  | ||||||
|             let word = T::regs().hr(i).read(); |  | ||||||
|             digest[(i * 4)..((i * 4) + 4)].copy_from_slice(word.to_be_bytes().as_slice()); |  | ||||||
|             i += 1; |  | ||||||
|         } |  | ||||||
|         digest_len_bytes |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Computes a digest for the given context.
 |  | ||||||
|     /// The digest buffer must be large enough to accomodate a digest for the selected algorithm.
 |  | ||||||
|     /// The largest returned digest size is 128 bytes for SHA-512.
 |  | ||||||
|     /// Panics if the supplied digest buffer is too short.
 |  | ||||||
|     #[cfg(hash_v2)] |  | ||||||
|     pub async fn finish<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize |  | ||||||
|     where |  | ||||||
|         D: crate::hash::Dma<T>, |  | ||||||
|     { |  | ||||||
|         // Restore the peripheral state.
 |         // Restore the peripheral state.
 | ||||||
|         self.load_context(&ctx); |         self.load_context(&ctx); | ||||||
| 
 | 
 | ||||||
| @ -483,27 +550,7 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Push data into the hash core.
 |     /// Push data into the hash core.
 | ||||||
|     fn accumulate_blocking(&mut self, input: &[u8]) { |     async fn accumulate(&mut self, input: &[u8]) { | ||||||
|         // Set the number of valid bits.
 |  | ||||||
|         let num_valid_bits: u8 = (8 * (input.len() % 4)) as u8; |  | ||||||
|         T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); |  | ||||||
| 
 |  | ||||||
|         let mut i = 0; |  | ||||||
|         while i < input.len() { |  | ||||||
|             let mut word: [u8; 4] = [0; 4]; |  | ||||||
|             let copy_idx = min(i + 4, input.len()); |  | ||||||
|             word[0..copy_idx - i].copy_from_slice(&input[i..copy_idx]); |  | ||||||
|             T::regs().din().write_value(u32::from_ne_bytes(word)); |  | ||||||
|             i += 4; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Push data into the hash core.
 |  | ||||||
|     #[cfg(hash_v2)] |  | ||||||
|     async fn accumulate(&mut self, input: &[u8]) |  | ||||||
|     where |  | ||||||
|         D: crate::hash::Dma<T>, |  | ||||||
|     { |  | ||||||
|         // Ignore an input length of 0.
 |         // Ignore an input length of 0.
 | ||||||
|         if input.len() == 0 { |         if input.len() == 0 { | ||||||
|             return; |             return; | ||||||
| @ -514,57 +561,20 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||||||
|         T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); |         T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); | ||||||
| 
 | 
 | ||||||
|         // Configure DMA to transfer input to hash core.
 |         // Configure DMA to transfer input to hash core.
 | ||||||
|         let dma_request = self.dma.request(); |  | ||||||
|         let dst_ptr: *mut u32 = T::regs().din().as_ptr(); |         let dst_ptr: *mut u32 = T::regs().din().as_ptr(); | ||||||
|         let mut num_words = input.len() / 4; |         let mut num_words = input.len() / 4; | ||||||
|         if input.len() % 4 > 0 { |         if input.len() % 4 > 0 { | ||||||
|             num_words += 1; |             num_words += 1; | ||||||
|         } |         } | ||||||
|         let src_ptr: *const [u8] = ptr::slice_from_raw_parts(input.as_ptr().cast(), num_words); |         let src_ptr: *const [u8] = ptr::slice_from_raw_parts(input.as_ptr().cast(), num_words); | ||||||
|         let dma_transfer = unsafe { | 
 | ||||||
|             Transfer::new_write_raw( |         let dma = self.dma.as_mut().unwrap(); | ||||||
|                 &mut self.dma, |         let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr as *mut u32, Default::default()) }; | ||||||
|                 dma_request, |  | ||||||
|                 src_ptr, |  | ||||||
|                 dst_ptr as *mut u32, |  | ||||||
|                 Default::default(), |  | ||||||
|             ) |  | ||||||
|         }; |  | ||||||
|         T::regs().cr().modify(|w| w.set_dmae(true)); |         T::regs().cr().modify(|w| w.set_dmae(true)); | ||||||
| 
 | 
 | ||||||
|         // Wait for the transfer to complete.
 |         // Wait for the transfer to complete.
 | ||||||
|         dma_transfer.await; |         dma_transfer.await; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /// Save the peripheral state to a context.
 |  | ||||||
|     fn store_context<'c>(&mut self, ctx: &mut Context<'c>) { |  | ||||||
|         // Block waiting for data in ready.
 |  | ||||||
|         while !T::regs().sr().read().dinis() {} |  | ||||||
| 
 |  | ||||||
|         // Store peripheral context.
 |  | ||||||
|         ctx.imr = T::regs().imr().read().0; |  | ||||||
|         ctx.str = T::regs().str().read().0; |  | ||||||
|         ctx.cr = T::regs().cr().read().0; |  | ||||||
|         let mut i = 0; |  | ||||||
|         while i < NUM_CONTEXT_REGS { |  | ||||||
|             ctx.csr[i] = T::regs().csr(i).read(); |  | ||||||
|             i += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Restore the peripheral state from a context.
 |  | ||||||
|     fn load_context(&mut self, ctx: &Context) { |  | ||||||
|         // Restore the peripheral state from the context.
 |  | ||||||
|         T::regs().imr().write_value(Imr { 0: ctx.imr }); |  | ||||||
|         T::regs().str().write_value(Str { 0: ctx.str }); |  | ||||||
|         T::regs().cr().write_value(Cr { 0: ctx.cr }); |  | ||||||
|         T::regs().cr().modify(|w| w.set_init(true)); |  | ||||||
|         let mut i = 0; |  | ||||||
|         while i < NUM_CONTEXT_REGS { |  | ||||||
|             T::regs().csr(i).write_value(ctx.csr[i]); |  | ||||||
|             i += 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| trait SealedInstance { | trait SealedInstance { | ||||||
|  | |||||||
| @ -85,6 +85,18 @@ macro_rules! dma_trait_impl { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[allow(unused)] | ||||||
|  | macro_rules! new_dma_nonopt { | ||||||
|  |     ($name:ident) => {{ | ||||||
|  |         let dma = $name.into_ref(); | ||||||
|  |         let request = dma.request(); | ||||||
|  |         crate::dma::ChannelAndRequest { | ||||||
|  |             channel: dma.map_into(), | ||||||
|  |             request, | ||||||
|  |         } | ||||||
|  |     }}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| macro_rules! new_dma { | macro_rules! new_dma { | ||||||
|     ($name:ident) => {{ |     ($name:ident) => {{ | ||||||
|         let dma = $name.into_ref(); |         let dma = $name.into_ref(); | ||||||
|  | |||||||
| @ -12,7 +12,8 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||||||
| use embassy_sync::waitqueue::AtomicWaker; | use embassy_sync::waitqueue::AtomicWaker; | ||||||
| use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | ||||||
| 
 | 
 | ||||||
| use crate::dma::NoDma; | #[cfg(sdmmc_v1)] | ||||||
|  | use crate::dma::ChannelAndRequest; | ||||||
| #[cfg(gpio_v2)] | #[cfg(gpio_v2)] | ||||||
| use crate::gpio::Pull; | use crate::gpio::Pull; | ||||||
| use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | ||||||
| @ -301,10 +302,10 @@ impl Default for Config { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Sdmmc device
 | /// Sdmmc device
 | ||||||
| pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | pub struct Sdmmc<'d, T: Instance> { | ||||||
|     _peri: PeripheralRef<'d, T>, |     _peri: PeripheralRef<'d, T>, | ||||||
|     #[allow(unused)] |     #[cfg(sdmmc_v1)] | ||||||
|     dma: PeripheralRef<'d, Dma>, |     dma: ChannelAndRequest<'d>, | ||||||
| 
 | 
 | ||||||
|     clk: PeripheralRef<'d, AnyPin>, |     clk: PeripheralRef<'d, AnyPin>, | ||||||
|     cmd: PeripheralRef<'d, AnyPin>, |     cmd: PeripheralRef<'d, AnyPin>, | ||||||
| @ -334,18 +335,18 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh | |||||||
| const DATA_AF: AfType = CMD_AF; | const DATA_AF: AfType = CMD_AF; | ||||||
| 
 | 
 | ||||||
| #[cfg(sdmmc_v1)] | #[cfg(sdmmc_v1)] | ||||||
| impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | impl<'d, T: Instance> Sdmmc<'d, T> { | ||||||
|     /// Create a new SDMMC driver, with 1 data lane.
 |     /// Create a new SDMMC driver, with 1 data lane.
 | ||||||
|     pub fn new_1bit( |     pub fn new_1bit( | ||||||
|         sdmmc: impl Peripheral<P = T> + 'd, |         sdmmc: impl Peripheral<P = T> + 'd, | ||||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||||
|         dma: impl Peripheral<P = Dma> + 'd, |         dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, | ||||||
|         clk: impl Peripheral<P = impl CkPin<T>> + 'd, |         clk: impl Peripheral<P = impl CkPin<T>> + 'd, | ||||||
|         cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |         cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | ||||||
|         d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |         d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | ||||||
|         config: Config, |         config: Config, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         into_ref!(clk, cmd, d0); |         into_ref!(dma, clk, cmd, d0); | ||||||
| 
 | 
 | ||||||
|         critical_section::with(|_| { |         critical_section::with(|_| { | ||||||
|             clk.set_as_af(clk.af_num(), CLK_AF); |             clk.set_as_af(clk.af_num(), CLK_AF); | ||||||
| @ -355,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             sdmmc, |             sdmmc, | ||||||
|             dma, |             new_dma_nonopt!(dma), | ||||||
|             clk.map_into(), |             clk.map_into(), | ||||||
|             cmd.map_into(), |             cmd.map_into(), | ||||||
|             d0.map_into(), |             d0.map_into(), | ||||||
| @ -370,7 +371,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||||||
|     pub fn new_4bit( |     pub fn new_4bit( | ||||||
|         sdmmc: impl Peripheral<P = T> + 'd, |         sdmmc: impl Peripheral<P = T> + 'd, | ||||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||||
|         dma: impl Peripheral<P = Dma> + 'd, |         dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, | ||||||
|         clk: impl Peripheral<P = impl CkPin<T>> + 'd, |         clk: impl Peripheral<P = impl CkPin<T>> + 'd, | ||||||
|         cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |         cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | ||||||
|         d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |         d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | ||||||
| @ -392,7 +393,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             sdmmc, |             sdmmc, | ||||||
|             dma, |             new_dma_nonopt!(dma), | ||||||
|             clk.map_into(), |             clk.map_into(), | ||||||
|             cmd.map_into(), |             cmd.map_into(), | ||||||
|             d0.map_into(), |             d0.map_into(), | ||||||
| @ -405,7 +406,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(sdmmc_v2)] | #[cfg(sdmmc_v2)] | ||||||
| impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | impl<'d, T: Instance> Sdmmc<'d, T> { | ||||||
|     /// Create a new SDMMC driver, with 1 data lane.
 |     /// Create a new SDMMC driver, with 1 data lane.
 | ||||||
|     pub fn new_1bit( |     pub fn new_1bit( | ||||||
|         sdmmc: impl Peripheral<P = T> + 'd, |         sdmmc: impl Peripheral<P = T> + 'd, | ||||||
| @ -425,7 +426,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             sdmmc, |             sdmmc, | ||||||
|             NoDma.into_ref(), |  | ||||||
|             clk.map_into(), |             clk.map_into(), | ||||||
|             cmd.map_into(), |             cmd.map_into(), | ||||||
|             d0.map_into(), |             d0.map_into(), | ||||||
| @ -461,7 +461,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||||||
| 
 | 
 | ||||||
|         Self::new_inner( |         Self::new_inner( | ||||||
|             sdmmc, |             sdmmc, | ||||||
|             NoDma.into_ref(), |  | ||||||
|             clk.map_into(), |             clk.map_into(), | ||||||
|             cmd.map_into(), |             cmd.map_into(), | ||||||
|             d0.map_into(), |             d0.map_into(), | ||||||
| @ -473,10 +472,10 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | impl<'d, T: Instance> Sdmmc<'d, T> { | ||||||
|     fn new_inner( |     fn new_inner( | ||||||
|         sdmmc: impl Peripheral<P = T> + 'd, |         sdmmc: impl Peripheral<P = T> + 'd, | ||||||
|         dma: impl Peripheral<P = Dma> + 'd, |         #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, | ||||||
|         clk: PeripheralRef<'d, AnyPin>, |         clk: PeripheralRef<'d, AnyPin>, | ||||||
|         cmd: PeripheralRef<'d, AnyPin>, |         cmd: PeripheralRef<'d, AnyPin>, | ||||||
|         d0: PeripheralRef<'d, AnyPin>, |         d0: PeripheralRef<'d, AnyPin>, | ||||||
| @ -485,7 +484,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         d3: Option<PeripheralRef<'d, AnyPin>>, |         d3: Option<PeripheralRef<'d, AnyPin>>, | ||||||
|         config: Config, |         config: Config, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         into_ref!(sdmmc, dma); |         into_ref!(sdmmc); | ||||||
| 
 | 
 | ||||||
|         rcc::enable_and_reset::<T>(); |         rcc::enable_and_reset::<T>(); | ||||||
| 
 | 
 | ||||||
| @ -514,6 +513,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
| 
 | 
 | ||||||
|         Self { |         Self { | ||||||
|             _peri: sdmmc, |             _peri: sdmmc, | ||||||
|  |             #[cfg(sdmmc_v1)] | ||||||
|             dma, |             dma, | ||||||
| 
 | 
 | ||||||
|             clk, |             clk, | ||||||
| @ -567,7 +567,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|     #[allow(unused_variables)] |     #[allow(unused_variables)] | ||||||
|     fn prepare_datapath_read<'a>( |     fn prepare_datapath_read<'a>( | ||||||
|         config: &Config, |         config: &Config, | ||||||
|         dma: &'a mut PeripheralRef<'d, Dma>, |         #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, | ||||||
|         buffer: &'a mut [u32], |         buffer: &'a mut [u32], | ||||||
|         length_bytes: u32, |         length_bytes: u32, | ||||||
|         block_size: u8, |         block_size: u8, | ||||||
| @ -583,16 +583,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         regs.dlenr().write(|w| w.set_datalength(length_bytes)); |         regs.dlenr().write(|w| w.set_datalength(length_bytes)); | ||||||
| 
 | 
 | ||||||
|         #[cfg(sdmmc_v1)] |         #[cfg(sdmmc_v1)] | ||||||
|         let transfer = unsafe { |         let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; | ||||||
|             let request = dma.request(); |  | ||||||
|             Transfer::new_read( |  | ||||||
|                 dma, |  | ||||||
|                 request, |  | ||||||
|                 regs.fifor().as_ptr() as *mut u32, |  | ||||||
|                 buffer, |  | ||||||
|                 DMA_TRANSFER_OPTIONS, |  | ||||||
|             ) |  | ||||||
|         }; |  | ||||||
|         #[cfg(sdmmc_v2)] |         #[cfg(sdmmc_v2)] | ||||||
|         let transfer = { |         let transfer = { | ||||||
|             regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); |             regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); | ||||||
| @ -632,14 +623,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
| 
 | 
 | ||||||
|         #[cfg(sdmmc_v1)] |         #[cfg(sdmmc_v1)] | ||||||
|         let transfer = unsafe { |         let transfer = unsafe { | ||||||
|             let request = self.dma.request(); |             self.dma | ||||||
|             Transfer::new_write( |                 .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) | ||||||
|                 &mut self.dma, |  | ||||||
|                 request, |  | ||||||
|                 buffer, |  | ||||||
|                 regs.fifor().as_ptr() as *mut u32, |  | ||||||
|                 DMA_TRANSFER_OPTIONS, |  | ||||||
|             ) |  | ||||||
|         }; |         }; | ||||||
|         #[cfg(sdmmc_v2)] |         #[cfg(sdmmc_v2)] | ||||||
|         let transfer = { |         let transfer = { | ||||||
| @ -735,7 +720,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let on_drop = OnDrop::new(|| Self::on_drop()); |         let on_drop = OnDrop::new(|| Self::on_drop()); | ||||||
| 
 | 
 | ||||||
|         let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); |         let transfer = Self::prepare_datapath_read( | ||||||
|  |             &self.config, | ||||||
|  |             #[cfg(sdmmc_v1)] | ||||||
|  |             &mut self.dma, | ||||||
|  |             status.as_mut(), | ||||||
|  |             64, | ||||||
|  |             6, | ||||||
|  |         ); | ||||||
|         InterruptHandler::<T>::data_interrupts(true); |         InterruptHandler::<T>::data_interrupts(true); | ||||||
|         Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
 |         Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6
 | ||||||
| 
 | 
 | ||||||
| @ -821,7 +813,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let on_drop = OnDrop::new(|| Self::on_drop()); |         let on_drop = OnDrop::new(|| Self::on_drop()); | ||||||
| 
 | 
 | ||||||
|         let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); |         let transfer = Self::prepare_datapath_read( | ||||||
|  |             &self.config, | ||||||
|  |             #[cfg(sdmmc_v1)] | ||||||
|  |             &mut self.dma, | ||||||
|  |             status.as_mut(), | ||||||
|  |             64, | ||||||
|  |             6, | ||||||
|  |         ); | ||||||
|         InterruptHandler::<T>::data_interrupts(true); |         InterruptHandler::<T>::data_interrupts(true); | ||||||
|         Self::cmd(Cmd::card_status(0), true)?; |         Self::cmd(Cmd::card_status(0), true)?; | ||||||
| 
 | 
 | ||||||
| @ -924,7 +923,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let on_drop = OnDrop::new(|| Self::on_drop()); |         let on_drop = OnDrop::new(|| Self::on_drop()); | ||||||
| 
 | 
 | ||||||
|         let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3); |         let transfer = Self::prepare_datapath_read( | ||||||
|  |             &self.config, | ||||||
|  |             #[cfg(sdmmc_v1)] | ||||||
|  |             &mut self.dma, | ||||||
|  |             scr, | ||||||
|  |             8, | ||||||
|  |             3, | ||||||
|  |         ); | ||||||
|         InterruptHandler::<T>::data_interrupts(true); |         InterruptHandler::<T>::data_interrupts(true); | ||||||
|         Self::cmd(Cmd::cmd51(), true)?; |         Self::cmd(Cmd::cmd51(), true)?; | ||||||
| 
 | 
 | ||||||
| @ -1214,7 +1220,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|         let regs = T::regs(); |         let regs = T::regs(); | ||||||
|         let on_drop = OnDrop::new(|| Self::on_drop()); |         let on_drop = OnDrop::new(|| Self::on_drop()); | ||||||
| 
 | 
 | ||||||
|         let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9); |         let transfer = Self::prepare_datapath_read( | ||||||
|  |             &self.config, | ||||||
|  |             #[cfg(sdmmc_v1)] | ||||||
|  |             &mut self.dma, | ||||||
|  |             buffer, | ||||||
|  |             512, | ||||||
|  |             9, | ||||||
|  |         ); | ||||||
|         InterruptHandler::<T>::data_interrupts(true); |         InterruptHandler::<T>::data_interrupts(true); | ||||||
|         Self::cmd(Cmd::read_single_block(address), true)?; |         Self::cmd(Cmd::read_single_block(address), true)?; | ||||||
| 
 | 
 | ||||||
| @ -1347,7 +1360,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { | impl<'d, T: Instance> Drop for Sdmmc<'d, T> { | ||||||
|     fn drop(&mut self) { |     fn drop(&mut self) { | ||||||
|         T::Interrupt::disable(); |         T::Interrupt::disable(); | ||||||
|         Self::on_drop(); |         Self::on_drop(); | ||||||
| @ -1484,15 +1497,6 @@ pin_trait!(D7Pin, Instance); | |||||||
| #[cfg(sdmmc_v1)] | #[cfg(sdmmc_v1)] | ||||||
| dma_trait!(SdmmcDma, Instance); | dma_trait!(SdmmcDma, Instance); | ||||||
| 
 | 
 | ||||||
| /// DMA instance trait.
 |  | ||||||
| ///
 |  | ||||||
| /// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of
 |  | ||||||
| /// using ST's system-wide DMA peripheral.
 |  | ||||||
| #[cfg(sdmmc_v2)] |  | ||||||
| pub trait SdmmcDma<T: Instance> {} |  | ||||||
| #[cfg(sdmmc_v2)] |  | ||||||
| impl<T: Instance> SdmmcDma<T> for NoDma {} |  | ||||||
| 
 |  | ||||||
| foreach_peripheral!( | foreach_peripheral!( | ||||||
|     (sdmmc, $inst:ident) => { |     (sdmmc, $inst:ident) => { | ||||||
|         impl SealedInstance for peripherals::$inst { |         impl SealedInstance for peripherals::$inst { | ||||||
| @ -1512,7 +1516,7 @@ foreach_peripheral!( | |||||||
|     }; |     }; | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> { | impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { | ||||||
|     type Error = Error; |     type Error = Error; | ||||||
|     type Align = aligned::A4; |     type Align = aligned::A4; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -839,7 +839,7 @@ impl<'d> Spi<'d, Async> { | |||||||
|         let rx_src = self.info.regs.rx_ptr(); |         let rx_src = self.info.regs.rx_ptr(); | ||||||
|         let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; |         let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; | ||||||
| 
 | 
 | ||||||
|         let tx_dst = self.info.regs.tx_ptr(); |         let tx_dst: *mut W = self.info.regs.tx_ptr(); | ||||||
|         let tx_f = unsafe { |         let tx_f = unsafe { | ||||||
|             self.tx_dma |             self.tx_dma | ||||||
|                 .as_mut() |                 .as_mut() | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ | |||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| @ -12,7 +11,7 @@ async fn main(_spawner: Spawner) -> ! { | |||||||
|     let p = embassy_stm32::init(Default::default()); |     let p = embassy_stm32::init(Default::default()); | ||||||
|     info!("Hello World, dude!"); |     info!("Hello World, dude!"); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ | |||||||
| use cortex_m_rt::entry; | use cortex_m_rt::entry; | ||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use embassy_stm32::Config; | use embassy_stm32::Config; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| 
 | 
 | ||||||
| @ -44,7 +43,7 @@ fn main() -> ! { | |||||||
|     } |     } | ||||||
|     let p = embassy_stm32::init(config); |     let p = embassy_stm32::init(config); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|  | |||||||
| @ -4,8 +4,9 @@ | |||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | ||||||
|  | use embassy_stm32::mode::Async; | ||||||
| use embassy_stm32::pac::timer::vals::Mms; | use embassy_stm32::pac::timer::vals::Mms; | ||||||
| use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; | ||||||
| use embassy_stm32::rcc::frequency; | use embassy_stm32::rcc::frequency; | ||||||
| use embassy_stm32::time::Hertz; | use embassy_stm32::time::Hertz; | ||||||
| use embassy_stm32::timer::low_level::Timer; | use embassy_stm32::timer::low_level::Timer; | ||||||
| @ -56,7 +57,7 @@ async fn main(spawner: Spawner) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::task] | #[embassy_executor::task] | ||||||
| async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) { | ||||||
|     let data: &[u8; 256] = &calculate_array::<256>(); |     let data: &[u8; 256] = &calculate_array::<256>(); | ||||||
| 
 | 
 | ||||||
|     info!("TIM6 frequency is {}", frequency::<TIM6>()); |     info!("TIM6 frequency is {}", frequency::<TIM6>()); | ||||||
| @ -99,7 +100,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::task] | #[embassy_executor::task] | ||||||
| async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) { | ||||||
|     let data: &[u8; 256] = &calculate_array::<256>(); |     let data: &[u8; 256] = &calculate_array::<256>(); | ||||||
| 
 | 
 | ||||||
|     info!("TIM7 frequency is {}", frequency::<TIM6>()); |     info!("TIM7 frequency is {}", frequency::<TIM6>()); | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| 
 | 
 | ||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| 
 | 
 | ||||||
| #[cortex_m_rt::entry] | #[cortex_m_rt::entry] | ||||||
| @ -11,7 +10,7 @@ fn main() -> ! { | |||||||
|     let p = embassy_stm32::init(Default::default()); |     let p = embassy_stm32::init(Default::default()); | ||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|  | |||||||
| @ -4,8 +4,9 @@ | |||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | ||||||
|  | use embassy_stm32::mode::Async; | ||||||
| use embassy_stm32::pac::timer::vals::Mms; | use embassy_stm32::pac::timer::vals::Mms; | ||||||
| use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; | ||||||
| use embassy_stm32::rcc::frequency; | use embassy_stm32::rcc::frequency; | ||||||
| use embassy_stm32::time::Hertz; | use embassy_stm32::time::Hertz; | ||||||
| use embassy_stm32::timer::low_level::Timer; | use embassy_stm32::timer::low_level::Timer; | ||||||
| @ -27,7 +28,7 @@ async fn main(spawner: Spawner) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::task] | #[embassy_executor::task] | ||||||
| async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) { | ||||||
|     let data: &[u8; 256] = &calculate_array::<256>(); |     let data: &[u8; 256] = &calculate_array::<256>(); | ||||||
| 
 | 
 | ||||||
|     info!("TIM6 frequency is {}", frequency::<TIM6>()); |     info!("TIM6 frequency is {}", frequency::<TIM6>()); | ||||||
| @ -70,7 +71,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::task] | #[embassy_executor::task] | ||||||
| async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) { | ||||||
|     let data: &[u8; 256] = &calculate_array::<256>(); |     let data: &[u8; 256] = &calculate_array::<256>(); | ||||||
| 
 | 
 | ||||||
|     info!("TIM7 frequency is {}", frequency::<TIM7>()); |     info!("TIM7 frequency is {}", frequency::<TIM7>()); | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| 
 | 
 | ||||||
| use defmt::*; | use defmt::*; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| 
 | 
 | ||||||
| #[cortex_m_rt::entry] | #[cortex_m_rt::entry] | ||||||
| @ -11,7 +10,7 @@ fn main() -> ! { | |||||||
|     let p = embassy_stm32::init(Default::default()); |     let p = embassy_stm32::init(Default::default()); | ||||||
|     info!("Hello World!"); |     info!("Hello World!"); | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); |     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||||
| 
 | 
 | ||||||
|     loop { |     loop { | ||||||
|         for v in 0..=255 { |         for v in 0..=255 { | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ use defmt::assert; | |||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::adc::Adc; | use embassy_stm32::adc::Adc; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use embassy_time::Timer; | use embassy_time::Timer; | ||||||
| use micromath::F32Ext; | use micromath::F32Ext; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| @ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     let dac_pin = peri!(p, DAC_PIN); |     let dac_pin = peri!(p, DAC_PIN); | ||||||
|     let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; |     let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(dac, NoDma, dac_pin); |     let mut dac = DacCh1::new_blocking(dac, dac_pin); | ||||||
|     let mut adc = Adc::new(adc); |     let mut adc = Adc::new(adc); | ||||||
| 
 | 
 | ||||||
|     #[cfg(feature = "stm32h755zi")] |     #[cfg(feature = "stm32h755zi")] | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ use defmt::assert; | |||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::adc::Adc; | use embassy_stm32::adc::Adc; | ||||||
| use embassy_stm32::dac::{DacCh1, Value}; | use embassy_stm32::dac::{DacCh1, Value}; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use embassy_stm32::{bind_interrupts, peripherals}; | use embassy_stm32::{bind_interrupts, peripherals}; | ||||||
| use embassy_time::Timer; | use embassy_time::Timer; | ||||||
| use micromath::F32Ext; | use micromath::F32Ext; | ||||||
| @ -32,7 +31,7 @@ async fn main(_spawner: Spawner) { | |||||||
|     let dac_pin = peri!(p, DAC_PIN); |     let dac_pin = peri!(p, DAC_PIN); | ||||||
|     let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; |     let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; | ||||||
| 
 | 
 | ||||||
|     let mut dac = DacCh1::new(dac, NoDma, dac_pin); |     let mut dac = DacCh1::new_blocking(dac, dac_pin); | ||||||
|     let mut adc = Adc::new(adc, Irqs); |     let mut adc = Adc::new(adc, Irqs); | ||||||
| 
 | 
 | ||||||
|     #[cfg(feature = "stm32h755zi")] |     #[cfg(feature = "stm32h755zi")] | ||||||
|  | |||||||
| @ -6,7 +6,6 @@ | |||||||
| mod common; | mod common; | ||||||
| use common::*; | use common::*; | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_stm32::dma::NoDma; |  | ||||||
| use embassy_stm32::hash::*; | use embassy_stm32::hash::*; | ||||||
| use embassy_stm32::{bind_interrupts, hash, peripherals}; | use embassy_stm32::{bind_interrupts, hash, peripherals}; | ||||||
| use hmac::{Hmac, Mac}; | use hmac::{Hmac, Mac}; | ||||||
| @ -36,7 +35,7 @@ bind_interrupts!(struct Irqs { | |||||||
| #[embassy_executor::main] | #[embassy_executor::main] | ||||||
| async fn main(_spawner: Spawner) { | async fn main(_spawner: Spawner) { | ||||||
|     let p: embassy_stm32::Peripherals = init(); |     let p: embassy_stm32::Peripherals = init(); | ||||||
|     let mut hw_hasher = Hash::new(p.HASH, NoDma, Irqs); |     let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); | ||||||
| 
 | 
 | ||||||
|     let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; |     let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; | ||||||
|     let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; |     let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user