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