Merge pull request #4005 from embassy-rs/no-nodma

stm32: remove DMA generic params, remove NoDma.
This commit is contained in:
Dario Nieuwenhuis 2025-03-25 21:31:14 +00:00 committed by GitHub
commit 4f250f3995
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 919 additions and 853 deletions

View File

@ -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

View File

@ -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 {}
};
}

View File

@ -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,

View File

@ -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)

View File

@ -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 {

View File

@ -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();

View File

@ -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;

View File

@ -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()

View File

@ -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 {

View File

@ -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 {

View File

@ -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>());

View File

@ -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 {

View File

@ -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>());

View File

@ -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 {

View File

@ -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")]

View File

@ -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")]

View File

@ -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";