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_IO3"), quote!(crate::tsc::G8IO3Pin)), | ||||
|         (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), | ||||
|         (("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)), | ||||
|         (("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)), | ||||
|     ].into(); | ||||
| 
 | ||||
|     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" { | ||||
|                     let peri = format_ident!("{}", p.name); | ||||
|                     let pin_name = format_ident!("{}", pin.pin); | ||||
| @ -1304,8 +1295,8 @@ fn main() { | ||||
|         (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), | ||||
|         (("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)), | ||||
|         (("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)), | ||||
|         (("dac", "CH1"), quote!(crate::dac::DacDma1)), | ||||
|         (("dac", "CH2"), quote!(crate::dac::DacDma2)), | ||||
|         (("dac", "CH1"), quote!(crate::dac::Dma<Ch1>)), | ||||
|         (("dac", "CH2"), quote!(crate::dac::Dma<Ch2>)), | ||||
|         (("timer", "UP"), quote!(crate::timer::UpDma)), | ||||
|         (("hash", "IN"), quote!(crate::hash::Dma)), | ||||
|         (("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 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))] | ||||
| use crate::pac::dac; | ||||
| use crate::rcc::{self, RccPeripheral}; | ||||
| @ -100,24 +101,20 @@ pub enum ValueArray<'a> { | ||||
| ///
 | ||||
| /// If you want to use both channels, either together or independently,
 | ||||
| /// create a [`Dac`] first and use it to access each channel.
 | ||||
| pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> { | ||||
|     phantom: PhantomData<&'d mut T>, | ||||
| pub struct DacChannel<'d, T: Instance, C: Channel, M: PeriMode> { | ||||
|     phantom: PhantomData<&'d mut (T, C, M)>, | ||||
|     #[allow(unused)] | ||||
|     dma: PeripheralRef<'d, DMA>, | ||||
|     dma: Option<ChannelAndRequest<'d>>, | ||||
| } | ||||
| 
 | ||||
| /// 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.
 | ||||
| pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; | ||||
| 
 | ||||
| impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | ||||
|     const IDX: usize = (N - 1) as usize; | ||||
| pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>; | ||||
| 
 | ||||
| impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Async> { | ||||
|     /// 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.
 | ||||
|     /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
 | ||||
|     /// 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
 | ||||
|     /// [`DacChannel::set_trigger()`].
 | ||||
|     pub fn new( | ||||
|         _peri: impl Peripheral<P = T> + 'd, | ||||
|         dma: impl Peripheral<P = DMA> + 'd, | ||||
|         pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd, | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         dma: impl Peripheral<P = impl Dma<T, C>> + 'd, | ||||
|         pin: impl Peripheral<P = impl DacPin<T, C>> + 'd, | ||||
|     ) -> Self { | ||||
|         into_ref!(dma, pin); | ||||
|         pin.set_as_analog(); | ||||
|         rcc::enable_and_reset::<T>(); | ||||
|         let mut dac = Self { | ||||
|             phantom: PhantomData, | ||||
|             dma, | ||||
|         }; | ||||
|         #[cfg(any(dac_v5, dac_v6, dac_v7))] | ||||
|         dac.set_hfsel(); | ||||
|         dac.enable(); | ||||
|         dac | ||||
|         Self::new_inner( | ||||
|             peri, | ||||
|             new_dma!(dma), | ||||
|             #[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,
 | ||||
| @ -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
 | ||||
|     /// 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
 | ||||
|     /// [`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 = DMA> + 'd) -> Self { | ||||
|         into_ref!(dma); | ||||
|     pub fn new_internal_blocking(peri: impl Peripheral<P = T> + 'd) -> Self { | ||||
|         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>(); | ||||
|         let mut dac = Self { | ||||
|             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))] | ||||
|         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 | ||||
|     } | ||||
| @ -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) { | ||||
|         critical_section::with(|_| { | ||||
|             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) { | ||||
|         critical_section::with(|_| { | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_en(Self::IDX, false); | ||||
|                 reg.set_tsel(Self::IDX, source as u8); | ||||
|                 reg.set_en(C::IDX, false); | ||||
|                 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) { | ||||
|         critical_section::with(|_| { | ||||
|             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.
 | ||||
|     pub fn trigger(&mut self) { | ||||
|         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) { | ||||
|         critical_section::with(|_| { | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_en(Self::IDX, false); | ||||
|                 reg.set_en(C::IDX, false); | ||||
|             }); | ||||
|             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.
 | ||||
|     pub fn set(&mut self, value: Value) { | ||||
|         match value { | ||||
|             Value::Bit8(v) => T::regs().dhr8r(Self::IDX).write(|reg| reg.set_dhr(v)), | ||||
|             Value::Bit12Left(v) => T::regs().dhr12l(Self::IDX).write(|reg| reg.set_dhr(v)), | ||||
|             Value::Bit12Right(v) => T::regs().dhr12r(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(C::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.
 | ||||
|     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.
 | ||||
| @ -279,82 +360,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| macro_rules! impl_dma_methods { | ||||
|     ($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> { | ||||
| impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> { | ||||
|     fn drop(&mut self) { | ||||
|         rcc::disable::<T>(); | ||||
|     } | ||||
| @ -368,14 +374,14 @@ impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> { | ||||
| ///
 | ||||
| /// ```ignore
 | ||||
| /// // 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> { | ||||
|     ch1: DacChannel<'d, T, 1, DMACh1>, | ||||
|     ch2: DacChannel<'d, T, 2, DMACh2>, | ||||
| pub struct Dac<'d, T: Instance, M: PeriMode> { | ||||
|     ch1: DacChannel<'d, T, Ch1, M>, | ||||
|     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.
 | ||||
|     ///
 | ||||
|     /// 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()`
 | ||||
|     /// method on the underlying channels.
 | ||||
|     pub fn new( | ||||
|         _peri: impl Peripheral<P = T> + 'd, | ||||
|         dma_ch1: impl Peripheral<P = DMACh1> + 'd, | ||||
|         dma_ch2: impl Peripheral<P = DMACh2> + 'd, | ||||
|         pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd, | ||||
|         pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd, | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, | ||||
|         dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + '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!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); | ||||
|         pin_ch1.set_as_analog(); | ||||
|         pin_ch2.set_as_analog(); | ||||
| 
 | ||||
|         // Enable twice to increment the DAC refcount for each channel.
 | ||||
|         rcc::enable_and_reset::<T>(); | ||||
|         rcc::enable_and_reset::<T>(); | ||||
| 
 | ||||
|         let mut ch1 = DacCh1 { | ||||
|             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 } | ||||
|         Self::new_inner( | ||||
|             peri, | ||||
|             new_dma!(dma_ch1), | ||||
|             new_dma!(dma_ch2), | ||||
|             #[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,
 | ||||
| @ -438,11 +429,77 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | ||||
|     /// 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, | ||||
|         dma_ch1: impl Peripheral<P = DMACh1> + 'd, | ||||
|         dma_ch2: impl Peripheral<P = DMACh2> + 'd, | ||||
|         peri: impl Peripheral<P = T> + 'd, | ||||
|         dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, | ||||
|         dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd, | ||||
|     ) -> Self { | ||||
|         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.
 | ||||
|         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))] | ||||
|         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(); | ||||
| 
 | ||||
|         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))] | ||||
|         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(); | ||||
| 
 | ||||
|         Self { ch1, ch2 } | ||||
| @ -471,17 +530,17 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | ||||
|     /// Split this `Dac` into separate channels.
 | ||||
|     ///
 | ||||
|     /// 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) | ||||
|     } | ||||
| 
 | ||||
|     /// 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 | ||||
|     } | ||||
| 
 | ||||
|     /// 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 | ||||
|     } | ||||
| 
 | ||||
| @ -514,11 +573,30 @@ trait SealedInstance { | ||||
| /// DAC instance.
 | ||||
| #[allow(private_bounds)] | ||||
| pub trait Instance: SealedInstance + RccPeripheral + 'static {} | ||||
| dma_trait!(DacDma1, Instance); | ||||
| dma_trait!(DacDma2, Instance); | ||||
| 
 | ||||
| /// Marks a pin that can be used with the DAC
 | ||||
| pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | ||||
| /// Channel 1 marker type.
 | ||||
| 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!( | ||||
|     (dac, $inst:ident) => { | ||||
| @ -531,9 +609,3 @@ foreach_peripheral!( | ||||
|         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(); | ||||
| 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
 | ||||
| pub(crate) unsafe fn init( | ||||
|     cs: critical_section::CriticalSection, | ||||
|  | ||||
| @ -39,10 +39,10 @@ impl<'d> ChannelAndRequest<'d> { | ||||
|         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, | ||||
|         buf: *const [W], | ||||
|         peri_addr: *mut W, | ||||
|         buf: *const [MW], | ||||
|         peri_addr: *mut PW, | ||||
|         options: TransferOptions, | ||||
|     ) -> Transfer<'a> { | ||||
|         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 stm32_metapac::hash::regs::*; | ||||
| 
 | ||||
| use crate::dma::NoDma; | ||||
| #[cfg(hash_v2)] | ||||
| use crate::dma::Transfer; | ||||
| use crate::dma::ChannelAndRequest; | ||||
| use crate::interrupt::typelevel::Interrupt; | ||||
| #[cfg(hash_v2)] | ||||
| use crate::mode::Async; | ||||
| use crate::mode::{Blocking, Mode}; | ||||
| use crate::peripherals::HASH; | ||||
| use crate::{interrupt, pac, peripherals, rcc, Peripheral}; | ||||
| 
 | ||||
| @ -116,24 +118,26 @@ pub struct Context<'c> { | ||||
| type HmacKey<'k> = Option<&'k [u8]>; | ||||
| 
 | ||||
| /// HASH driver.
 | ||||
| pub struct Hash<'d, T: Instance, D = NoDma> { | ||||
| pub struct Hash<'d, T: Instance, M: Mode> { | ||||
|     _peripheral: PeripheralRef<'d, T>, | ||||
|     #[allow(dead_code)] | ||||
|     dma: PeripheralRef<'d, D>, | ||||
|     _phantom: PhantomData<M>, | ||||
|     #[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.
 | ||||
|     pub fn new( | ||||
|     pub fn new_blocking( | ||||
|         peripheral: impl Peripheral<P = T> + 'd, | ||||
|         dma: impl Peripheral<P = D> + 'd, | ||||
|         _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||||
|     ) -> Self { | ||||
|         rcc::enable_and_reset::<HASH>(); | ||||
|         into_ref!(peripheral, dma); | ||||
|         into_ref!(peripheral); | ||||
|         let instance = Self { | ||||
|             _peripheral: peripheral, | ||||
|             dma: dma, | ||||
|             _phantom: PhantomData, | ||||
|             #[cfg(hash_v2)] | ||||
|             dma: None, | ||||
|         }; | ||||
| 
 | ||||
|         T::Interrupt::unpend(); | ||||
| @ -141,7 +145,9 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | ||||
| 
 | ||||
|         instance | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'d, T: Instance, M: Mode> Hash<'d, T, M> { | ||||
|     /// 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> { | ||||
|         // Define a context for this new computation.
 | ||||
| @ -282,14 +288,136 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | ||||
|         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,
 | ||||
|     /// then updates the state with the provided data.
 | ||||
|     /// Peripheral state is saved upon return.
 | ||||
|     #[cfg(hash_v2)] | ||||
|     pub async fn update<'c>(&mut self, ctx: &mut Context<'c>, input: &[u8]) | ||||
|     where | ||||
|         D: crate::hash::Dma<T>, | ||||
|     { | ||||
|     pub async fn update(&mut self, ctx: &mut Context<'_>, input: &[u8]) { | ||||
|         // Restore the peripheral state.
 | ||||
|         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 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 | ||||
|     } | ||||
| 
 | ||||
|     /// 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>, | ||||
|     { | ||||
|     pub async fn finish<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { | ||||
|         // Restore the peripheral state.
 | ||||
|         self.load_context(&ctx); | ||||
| 
 | ||||
| @ -483,27 +550,7 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | ||||
|     } | ||||
| 
 | ||||
|     /// 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; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Push data into the hash core.
 | ||||
|     #[cfg(hash_v2)] | ||||
|     async fn accumulate(&mut self, input: &[u8]) | ||||
|     where | ||||
|         D: crate::hash::Dma<T>, | ||||
|     { | ||||
|     async fn accumulate(&mut self, input: &[u8]) { | ||||
|         // Ignore an input length of 0.
 | ||||
|         if input.len() == 0 { | ||||
|             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)); | ||||
| 
 | ||||
|         // 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 mut num_words = input.len() / 4; | ||||
|         if input.len() % 4 > 0 { | ||||
|             num_words += 1; | ||||
|         } | ||||
|         let src_ptr: *const [u8] = ptr::slice_from_raw_parts(input.as_ptr().cast(), num_words); | ||||
|         let dma_transfer = unsafe { | ||||
|             Transfer::new_write_raw( | ||||
|                 &mut self.dma, | ||||
|                 dma_request, | ||||
|                 src_ptr, | ||||
|                 dst_ptr as *mut u32, | ||||
|                 Default::default(), | ||||
|             ) | ||||
|         }; | ||||
| 
 | ||||
|         let dma = self.dma.as_mut().unwrap(); | ||||
|         let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr as *mut u32, Default::default()) }; | ||||
|         T::regs().cr().modify(|w| w.set_dmae(true)); | ||||
| 
 | ||||
|         // Wait for the transfer to complete.
 | ||||
|         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 { | ||||
|  | ||||
| @ -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 { | ||||
|     ($name:ident) => {{ | ||||
|         let dma = $name.into_ref(); | ||||
|  | ||||
| @ -12,7 +12,8 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | ||||
| use embassy_sync::waitqueue::AtomicWaker; | ||||
| 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)] | ||||
| use crate::gpio::Pull; | ||||
| use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | ||||
| @ -301,10 +302,10 @@ impl Default for Config { | ||||
| } | ||||
| 
 | ||||
| /// Sdmmc device
 | ||||
| pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | ||||
| pub struct Sdmmc<'d, T: Instance> { | ||||
|     _peri: PeripheralRef<'d, T>, | ||||
|     #[allow(unused)] | ||||
|     dma: PeripheralRef<'d, Dma>, | ||||
|     #[cfg(sdmmc_v1)] | ||||
|     dma: ChannelAndRequest<'d>, | ||||
| 
 | ||||
|     clk: 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; | ||||
| 
 | ||||
| #[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.
 | ||||
|     pub fn new_1bit( | ||||
|         sdmmc: impl Peripheral<P = 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, | ||||
|         cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | ||||
|         d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         into_ref!(clk, cmd, d0); | ||||
|         into_ref!(dma, clk, cmd, d0); | ||||
| 
 | ||||
|         critical_section::with(|_| { | ||||
|             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( | ||||
|             sdmmc, | ||||
|             dma, | ||||
|             new_dma_nonopt!(dma), | ||||
|             clk.map_into(), | ||||
|             cmd.map_into(), | ||||
|             d0.map_into(), | ||||
| @ -370,7 +371,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | ||||
|     pub fn new_4bit( | ||||
|         sdmmc: impl Peripheral<P = 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, | ||||
|         cmd: impl Peripheral<P = impl CmdPin<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( | ||||
|             sdmmc, | ||||
|             dma, | ||||
|             new_dma_nonopt!(dma), | ||||
|             clk.map_into(), | ||||
|             cmd.map_into(), | ||||
|             d0.map_into(), | ||||
| @ -405,7 +406,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | ||||
| } | ||||
| 
 | ||||
| #[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.
 | ||||
|     pub fn new_1bit( | ||||
|         sdmmc: impl Peripheral<P = T> + 'd, | ||||
| @ -425,7 +426,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | ||||
| 
 | ||||
|         Self::new_inner( | ||||
|             sdmmc, | ||||
|             NoDma.into_ref(), | ||||
|             clk.map_into(), | ||||
|             cmd.map_into(), | ||||
|             d0.map_into(), | ||||
| @ -461,7 +461,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | ||||
| 
 | ||||
|         Self::new_inner( | ||||
|             sdmmc, | ||||
|             NoDma.into_ref(), | ||||
|             clk.map_into(), | ||||
|             cmd.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( | ||||
|         sdmmc: impl Peripheral<P = T> + 'd, | ||||
|         dma: impl Peripheral<P = Dma> + 'd, | ||||
|         #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, | ||||
|         clk: PeripheralRef<'d, AnyPin>, | ||||
|         cmd: 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>>, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         into_ref!(sdmmc, dma); | ||||
|         into_ref!(sdmmc); | ||||
| 
 | ||||
|         rcc::enable_and_reset::<T>(); | ||||
| 
 | ||||
| @ -514,6 +513,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | ||||
| 
 | ||||
|         Self { | ||||
|             _peri: sdmmc, | ||||
|             #[cfg(sdmmc_v1)] | ||||
|             dma, | ||||
| 
 | ||||
|             clk, | ||||
| @ -567,7 +567,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | ||||
|     #[allow(unused_variables)] | ||||
|     fn prepare_datapath_read<'a>( | ||||
|         config: &Config, | ||||
|         dma: &'a mut PeripheralRef<'d, Dma>, | ||||
|         #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, | ||||
|         buffer: &'a mut [u32], | ||||
|         length_bytes: u32, | ||||
|         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)); | ||||
| 
 | ||||
|         #[cfg(sdmmc_v1)] | ||||
|         let transfer = unsafe { | ||||
|             let request = dma.request(); | ||||
|             Transfer::new_read( | ||||
|                 dma, | ||||
|                 request, | ||||
|                 regs.fifor().as_ptr() as *mut u32, | ||||
|                 buffer, | ||||
|                 DMA_TRANSFER_OPTIONS, | ||||
|             ) | ||||
|         }; | ||||
|         let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; | ||||
|         #[cfg(sdmmc_v2)] | ||||
|         let transfer = { | ||||
|             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)] | ||||
|         let transfer = unsafe { | ||||
|             let request = self.dma.request(); | ||||
|             Transfer::new_write( | ||||
|                 &mut self.dma, | ||||
|                 request, | ||||
|                 buffer, | ||||
|                 regs.fifor().as_ptr() as *mut u32, | ||||
|                 DMA_TRANSFER_OPTIONS, | ||||
|             ) | ||||
|             self.dma | ||||
|                 .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) | ||||
|         }; | ||||
|         #[cfg(sdmmc_v2)] | ||||
|         let transfer = { | ||||
| @ -735,7 +720,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | ||||
|         let regs = T::regs(); | ||||
|         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); | ||||
|         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 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); | ||||
|         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 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); | ||||
|         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 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); | ||||
|         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) { | ||||
|         T::Interrupt::disable(); | ||||
|         Self::on_drop(); | ||||
| @ -1484,15 +1497,6 @@ pin_trait!(D7Pin, Instance); | ||||
| #[cfg(sdmmc_v1)] | ||||
| 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!( | ||||
|     (sdmmc, $inst:ident) => { | ||||
|         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 Align = aligned::A4; | ||||
| 
 | ||||
|  | ||||
| @ -839,7 +839,7 @@ impl<'d> Spi<'d, Async> { | ||||
|         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 tx_dst = self.info.regs.tx_ptr(); | ||||
|         let tx_dst: *mut W = self.info.regs.tx_ptr(); | ||||
|         let tx_f = unsafe { | ||||
|             self.tx_dma | ||||
|                 .as_mut() | ||||
|  | ||||
| @ -4,7 +4,6 @@ | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
| 
 | ||||
| #[embassy_executor::main] | ||||
| @ -12,7 +11,7 @@ async fn main(_spawner: Spawner) -> ! { | ||||
|     let p = embassy_stm32::init(Default::default()); | ||||
|     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 { | ||||
|         for v in 0..=255 { | ||||
|  | ||||
| @ -4,7 +4,6 @@ | ||||
| use cortex_m_rt::entry; | ||||
| use defmt::*; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use embassy_stm32::Config; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
| 
 | ||||
| @ -44,7 +43,7 @@ fn main() -> ! { | ||||
|     } | ||||
|     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 { | ||||
|         for v in 0..=255 { | ||||
|  | ||||
| @ -4,8 +4,9 @@ | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | ||||
| use embassy_stm32::mode::Async; | ||||
| 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::time::Hertz; | ||||
| use embassy_stm32::timer::low_level::Timer; | ||||
| @ -56,7 +57,7 @@ async fn main(spawner: Spawner) { | ||||
| } | ||||
| 
 | ||||
| #[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>(); | ||||
| 
 | ||||
|     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] | ||||
| 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>(); | ||||
| 
 | ||||
|     info!("TIM7 frequency is {}", frequency::<TIM6>()); | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| 
 | ||||
| use defmt::*; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
| 
 | ||||
| #[cortex_m_rt::entry] | ||||
| @ -11,7 +10,7 @@ fn main() -> ! { | ||||
|     let p = embassy_stm32::init(Default::default()); | ||||
|     info!("Hello World!"); | ||||
| 
 | ||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | ||||
|     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||
| 
 | ||||
|     loop { | ||||
|         for v in 0..=255 { | ||||
|  | ||||
| @ -4,8 +4,9 @@ | ||||
| use defmt::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | ||||
| use embassy_stm32::mode::Async; | ||||
| 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::time::Hertz; | ||||
| use embassy_stm32::timer::low_level::Timer; | ||||
| @ -27,7 +28,7 @@ async fn main(spawner: Spawner) { | ||||
| } | ||||
| 
 | ||||
| #[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>(); | ||||
| 
 | ||||
|     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] | ||||
| 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>(); | ||||
| 
 | ||||
|     info!("TIM7 frequency is {}", frequency::<TIM7>()); | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| 
 | ||||
| use defmt::*; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
| 
 | ||||
| #[cortex_m_rt::entry] | ||||
| @ -11,7 +10,7 @@ fn main() -> ! { | ||||
|     let p = embassy_stm32::init(Default::default()); | ||||
|     info!("Hello World!"); | ||||
| 
 | ||||
|     let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | ||||
|     let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); | ||||
| 
 | ||||
|     loop { | ||||
|         for v in 0..=255 { | ||||
|  | ||||
| @ -12,7 +12,6 @@ use defmt::assert; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::adc::Adc; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use embassy_time::Timer; | ||||
| use micromath::F32Ext; | ||||
| use {defmt_rtt as _, panic_probe as _}; | ||||
| @ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | ||||
|     let dac_pin = peri!(p, 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); | ||||
| 
 | ||||
|     #[cfg(feature = "stm32h755zi")] | ||||
|  | ||||
| @ -12,7 +12,6 @@ use defmt::assert; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::adc::Adc; | ||||
| use embassy_stm32::dac::{DacCh1, Value}; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use embassy_stm32::{bind_interrupts, peripherals}; | ||||
| use embassy_time::Timer; | ||||
| use micromath::F32Ext; | ||||
| @ -32,7 +31,7 @@ async fn main(_spawner: Spawner) { | ||||
|     let dac_pin = peri!(p, 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); | ||||
| 
 | ||||
|     #[cfg(feature = "stm32h755zi")] | ||||
|  | ||||
| @ -6,7 +6,6 @@ | ||||
| mod common; | ||||
| use common::*; | ||||
| use embassy_executor::Spawner; | ||||
| use embassy_stm32::dma::NoDma; | ||||
| use embassy_stm32::hash::*; | ||||
| use embassy_stm32::{bind_interrupts, hash, peripherals}; | ||||
| use hmac::{Hmac, Mac}; | ||||
| @ -36,7 +35,7 @@ bind_interrupts!(struct Irqs { | ||||
| #[embassy_executor::main] | ||||
| async fn main(_spawner: Spawner) { | ||||
|     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_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user