stm32/dac: dedup pin and DMA traits, demacrofify.
This commit is contained in:
parent
17cce79807
commit
f007b53db3
@ -1151,6 +1151,8 @@ fn main() {
|
|||||||
(("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)),
|
(("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)),
|
||||||
(("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)),
|
(("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)),
|
||||||
(("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)),
|
(("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)),
|
||||||
|
(("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)),
|
||||||
|
(("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)),
|
||||||
].into();
|
].into();
|
||||||
|
|
||||||
for p in METADATA.peripherals {
|
for p in METADATA.peripherals {
|
||||||
@ -1250,17 +1252,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DAC is special
|
|
||||||
if regs.kind == "dac" {
|
|
||||||
let peri = format_ident!("{}", p.name);
|
|
||||||
let pin_name = format_ident!("{}", pin.pin);
|
|
||||||
let ch: u8 = pin.signal.strip_prefix("OUT").unwrap().parse().unwrap();
|
|
||||||
|
|
||||||
g.extend(quote! {
|
|
||||||
impl_dac_pin!( #peri, #pin_name, #ch);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if regs.kind == "spdifrx" {
|
if regs.kind == "spdifrx" {
|
||||||
let peri = format_ident!("{}", p.name);
|
let peri = format_ident!("{}", p.name);
|
||||||
let pin_name = format_ident!("{}", pin.pin);
|
let pin_name = format_ident!("{}", pin.pin);
|
||||||
@ -1304,8 +1295,8 @@ fn main() {
|
|||||||
(("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
|
(("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
|
||||||
(("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)),
|
(("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)),
|
||||||
(("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)),
|
(("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)),
|
||||||
(("dac", "CH1"), quote!(crate::dac::DacDma1)),
|
(("dac", "CH1"), quote!(crate::dac::Dma<Ch1>)),
|
||||||
(("dac", "CH2"), quote!(crate::dac::DacDma2)),
|
(("dac", "CH2"), quote!(crate::dac::Dma<Ch2>)),
|
||||||
(("timer", "UP"), quote!(crate::timer::UpDma)),
|
(("timer", "UP"), quote!(crate::timer::UpDma)),
|
||||||
(("hash", "IN"), quote!(crate::hash::Dma)),
|
(("hash", "IN"), quote!(crate::hash::Dma)),
|
||||||
(("cryp", "IN"), quote!(crate::cryp::DmaIn)),
|
(("cryp", "IN"), quote!(crate::cryp::DmaIn)),
|
||||||
|
|||||||
@ -100,20 +100,18 @@ pub enum ValueArray<'a> {
|
|||||||
///
|
///
|
||||||
/// If you want to use both channels, either together or independently,
|
/// If you want to use both channels, either together or independently,
|
||||||
/// create a [`Dac`] first and use it to access each channel.
|
/// create a [`Dac`] first and use it to access each channel.
|
||||||
pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> {
|
pub struct DacChannel<'d, T: Instance, C: Channel, DMA = NoDma> {
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut (T, C)>,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
dma: PeripheralRef<'d, DMA>,
|
dma: PeripheralRef<'d, DMA>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DAC channel 1 type alias.
|
/// DAC channel 1 type alias.
|
||||||
pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>;
|
pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch1, DMA>;
|
||||||
/// DAC channel 2 type alias.
|
/// DAC channel 2 type alias.
|
||||||
pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>;
|
pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, Ch2, DMA>;
|
||||||
|
|
||||||
impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|
||||||
const IDX: usize = (N - 1) as usize;
|
|
||||||
|
|
||||||
|
impl<'d, T: Instance, C: Channel, DMA> DacChannel<'d, T, C, DMA> {
|
||||||
/// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
|
/// Create a new `DacChannel` instance, consuming the underlying DAC peripheral.
|
||||||
///
|
///
|
||||||
/// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
|
/// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument.
|
||||||
@ -127,7 +125,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
dma: impl Peripheral<P = DMA> + 'd,
|
dma: impl Peripheral<P = DMA> + 'd,
|
||||||
pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd,
|
pin: impl Peripheral<P = impl DacPin<T, C> + crate::gpio::Pin> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(dma, pin);
|
into_ref!(dma, pin);
|
||||||
pin.set_as_analog();
|
pin.set_as_analog();
|
||||||
@ -173,7 +171,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
pub fn set_enable(&mut self, on: bool) {
|
pub fn set_enable(&mut self, on: bool) {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_en(Self::IDX, on);
|
reg.set_en(C::IDX, on);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -194,8 +192,8 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
pub fn set_trigger(&mut self, source: TriggerSel) {
|
pub fn set_trigger(&mut self, source: TriggerSel) {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_en(Self::IDX, false);
|
reg.set_en(C::IDX, false);
|
||||||
reg.set_tsel(Self::IDX, source as u8);
|
reg.set_tsel(C::IDX, source as u8);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -204,7 +202,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
pub fn set_triggering(&mut self, on: bool) {
|
pub fn set_triggering(&mut self, on: bool) {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_ten(Self::IDX, on);
|
reg.set_ten(C::IDX, on);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -212,7 +210,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
/// Software trigger this channel.
|
/// Software trigger this channel.
|
||||||
pub fn trigger(&mut self) {
|
pub fn trigger(&mut self) {
|
||||||
T::regs().swtrigr().write(|reg| {
|
T::regs().swtrigr().write(|reg| {
|
||||||
reg.set_swtrig(Self::IDX, true);
|
reg.set_swtrig(C::IDX, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,10 +221,10 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
pub fn set_mode(&mut self, mode: Mode) {
|
pub fn set_mode(&mut self, mode: Mode) {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
T::regs().cr().modify(|reg| {
|
T::regs().cr().modify(|reg| {
|
||||||
reg.set_en(Self::IDX, false);
|
reg.set_en(C::IDX, false);
|
||||||
});
|
});
|
||||||
T::regs().mcr().modify(|reg| {
|
T::regs().mcr().modify(|reg| {
|
||||||
reg.set_mode(Self::IDX, mode.mode());
|
reg.set_mode(C::IDX, mode.mode());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -237,15 +235,15 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
|||||||
/// it will be output after the next trigger.
|
/// it will be output after the next trigger.
|
||||||
pub fn set(&mut self, value: Value) {
|
pub fn set(&mut self, value: Value) {
|
||||||
match value {
|
match value {
|
||||||
Value::Bit8(v) => T::regs().dhr8r(Self::IDX).write(|reg| reg.set_dhr(v)),
|
Value::Bit8(v) => T::regs().dhr8r(C::IDX).write(|reg| reg.set_dhr(v)),
|
||||||
Value::Bit12Left(v) => T::regs().dhr12l(Self::IDX).write(|reg| reg.set_dhr(v)),
|
Value::Bit12Left(v) => T::regs().dhr12l(C::IDX).write(|reg| reg.set_dhr(v)),
|
||||||
Value::Bit12Right(v) => T::regs().dhr12r(Self::IDX).write(|reg| reg.set_dhr(v)),
|
Value::Bit12Right(v) => T::regs().dhr12r(C::IDX).write(|reg| reg.set_dhr(v)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the current output value of the DAC.
|
/// Read the current output value of the DAC.
|
||||||
pub fn read(&self) -> u16 {
|
pub fn read(&self) -> u16 {
|
||||||
T::regs().dor(Self::IDX).read().dor()
|
T::regs().dor(C::IDX).read().dor()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set HFSEL as appropriate for the current peripheral clock frequency.
|
/// Set HFSEL as appropriate for the current peripheral clock frequency.
|
||||||
@ -277,14 +275,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.
|
/// Write `data` to this channel via DMA.
|
||||||
///
|
///
|
||||||
/// To prevent delays or glitches when outputing a periodic waveform, the `circular`
|
/// To prevent delays or glitches when outputing a periodic waveform, the `circular`
|
||||||
@ -292,11 +283,14 @@ macro_rules! impl_dma_methods {
|
|||||||
/// `data`. Note that for performance reasons in circular mode the transfer-complete
|
/// `data`. Note that for performance reasons in circular mode the transfer-complete
|
||||||
/// interrupt is disabled.
|
/// interrupt is disabled.
|
||||||
#[cfg(not(gpdma))]
|
#[cfg(not(gpdma))]
|
||||||
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) {
|
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool)
|
||||||
|
where
|
||||||
|
DMA: Dma<T, C>,
|
||||||
|
{
|
||||||
// Enable DAC and DMA
|
// Enable DAC and DMA
|
||||||
T::regs().cr().modify(|w| {
|
T::regs().cr().modify(|w| {
|
||||||
w.set_en(Self::IDX, true);
|
w.set_en(C::IDX, true);
|
||||||
w.set_dmaen(Self::IDX, true);
|
w.set_dmaen(C::IDX, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
let tx_request = self.dma.request();
|
let tx_request = self.dma.request();
|
||||||
@ -316,7 +310,7 @@ macro_rules! impl_dma_methods {
|
|||||||
dma_channel,
|
dma_channel,
|
||||||
tx_request,
|
tx_request,
|
||||||
buf,
|
buf,
|
||||||
T::regs().dhr8r(Self::IDX).as_ptr() as *mut u8,
|
T::regs().dhr8r(C::IDX).as_ptr() as *mut u8,
|
||||||
tx_options,
|
tx_options,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -325,7 +319,7 @@ macro_rules! impl_dma_methods {
|
|||||||
dma_channel,
|
dma_channel,
|
||||||
tx_request,
|
tx_request,
|
||||||
buf,
|
buf,
|
||||||
T::regs().dhr12l(Self::IDX).as_ptr() as *mut u16,
|
T::regs().dhr12l(C::IDX).as_ptr() as *mut u16,
|
||||||
tx_options,
|
tx_options,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -334,7 +328,7 @@ macro_rules! impl_dma_methods {
|
|||||||
dma_channel,
|
dma_channel,
|
||||||
tx_request,
|
tx_request,
|
||||||
buf,
|
buf,
|
||||||
T::regs().dhr12r(Self::IDX).as_ptr() as *mut u16,
|
T::regs().dhr12r(C::IDX).as_ptr() as *mut u16,
|
||||||
tx_options,
|
tx_options,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -343,18 +337,13 @@ macro_rules! impl_dma_methods {
|
|||||||
tx_f.await;
|
tx_f.await;
|
||||||
|
|
||||||
T::regs().cr().modify(|w| {
|
T::regs().cr().modify(|w| {
|
||||||
w.set_en(Self::IDX, false);
|
w.set_en(C::IDX, false);
|
||||||
w.set_dmaen(Self::IDX, false);
|
w.set_dmaen(C::IDX, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_dma_methods!(1, DacDma1);
|
impl<'d, T: Instance, C: Channel, DMA> Drop for DacChannel<'d, T, C, DMA> {
|
||||||
impl_dma_methods!(2, DacDma2);
|
|
||||||
|
|
||||||
impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> {
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
rcc::disable::<T>();
|
rcc::disable::<T>();
|
||||||
}
|
}
|
||||||
@ -371,8 +360,8 @@ impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> {
|
|||||||
/// 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(p.DAC1, NoDma, NoDma, p.PA4, p.PA5).split();
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> {
|
pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> {
|
||||||
ch1: DacChannel<'d, T, 1, DMACh1>,
|
ch1: DacChannel<'d, T, Ch1, DMACh1>,
|
||||||
ch2: DacChannel<'d, T, 2, DMACh2>,
|
ch2: DacChannel<'d, T, Ch2, DMACh2>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
|
impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
|
||||||
@ -392,8 +381,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> {
|
|||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
dma_ch1: impl Peripheral<P = DMACh1> + 'd,
|
dma_ch1: impl Peripheral<P = DMACh1> + 'd,
|
||||||
dma_ch2: impl Peripheral<P = DMACh2> + 'd,
|
dma_ch2: impl Peripheral<P = DMACh2> + 'd,
|
||||||
pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd,
|
pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd,
|
||||||
pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd,
|
pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2);
|
into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2);
|
||||||
pin_ch1.set_as_analog();
|
pin_ch1.set_as_analog();
|
||||||
@ -514,11 +503,30 @@ trait SealedInstance {
|
|||||||
/// DAC instance.
|
/// DAC instance.
|
||||||
#[allow(private_bounds)]
|
#[allow(private_bounds)]
|
||||||
pub trait Instance: SealedInstance + RccPeripheral + 'static {}
|
pub trait Instance: SealedInstance + RccPeripheral + 'static {}
|
||||||
dma_trait!(DacDma1, Instance);
|
|
||||||
dma_trait!(DacDma2, Instance);
|
|
||||||
|
|
||||||
/// Marks a pin that can be used with the DAC
|
/// Channel 1 marker type.
|
||||||
pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
|
pub enum Ch1 {}
|
||||||
|
/// Channel 2 marker type.
|
||||||
|
pub enum Ch2 {}
|
||||||
|
|
||||||
|
trait SealedChannel {
|
||||||
|
const IDX: usize;
|
||||||
|
}
|
||||||
|
/// DAC channel trait.
|
||||||
|
#[allow(private_bounds)]
|
||||||
|
pub trait Channel: SealedChannel {}
|
||||||
|
|
||||||
|
impl SealedChannel for Ch1 {
|
||||||
|
const IDX: usize = 0;
|
||||||
|
}
|
||||||
|
impl SealedChannel for Ch2 {
|
||||||
|
const IDX: usize = 1;
|
||||||
|
}
|
||||||
|
impl Channel for Ch1 {}
|
||||||
|
impl Channel for Ch2 {}
|
||||||
|
|
||||||
|
dma_trait!(Dma, Instance, Channel);
|
||||||
|
pin_trait!(DacPin, Instance, Channel);
|
||||||
|
|
||||||
foreach_peripheral!(
|
foreach_peripheral!(
|
||||||
(dac, $inst:ident) => {
|
(dac, $inst:ident) => {
|
||||||
@ -531,9 +539,3 @@ foreach_peripheral!(
|
|||||||
impl crate::dac::Instance for peripherals::$inst {}
|
impl crate::dac::Instance for peripherals::$inst {}
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! impl_dac_pin {
|
|
||||||
($inst:ident, $pin:ident, $ch:expr) => {
|
|
||||||
impl crate::dac::DacPin<peripherals::$inst, $ch> for crate::peripherals::$pin {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user