#![macro_use] macro_rules! peri_trait { ( $(irqs: [$($irq:ident),*],)? ) => { #[allow(private_interfaces)] pub(crate) trait SealedInstance { #[allow(unused)] fn info() -> &'static Info; #[allow(unused)] fn state() -> &'static State; } /// Peripheral instance trait. #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { $($( /// Interrupt for this peripheral. type $irq: crate::interrupt::typelevel::Interrupt; )*)? } }; } macro_rules! peri_trait_impl { ($instance:ident, $info:expr) => { #[allow(private_interfaces)] impl SealedInstance for crate::peripherals::$instance { fn info() -> &'static Info { static INFO: Info = $info; &INFO } fn state() -> &'static State { static STATE: State = State::new(); &STATE } } impl Instance for crate::peripherals::$instance {} }; } macro_rules! pin_trait { ($signal:ident, $instance:path $(, $mode:path)? $(, @$afio:ident)?) => { #[doc = concat!(stringify!($signal), " pin trait")] pub trait $signal: crate::gpio::Pin { #[cfg(not(afio))] #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))] fn af_num(&self) -> u8; #[cfg(afio)] #[doc = concat!("Configures AFIO_MAPR to use this pin as ", stringify!($signal))] fn afio_remap(&self); } }; } macro_rules! pin_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr $(, $afio:path)?) => { #[cfg(afio)] impl crate::$mod::$trait for crate::peripherals::$pin { fn afio_remap(&self) { // nothing } } #[cfg(not(afio))] impl crate::$mod::$trait for crate::peripherals::$pin { fn af_num(&self) -> u8 { $af } } }; } #[cfg(afio)] macro_rules! pin_trait_afio_impl { (@set mapr, $setter:ident, $val:expr) => { crate::pac::AFIO.mapr().modify(|w| { w.set_swj_cfg(crate::pac::afio::vals::SwjCfg::NO_OP); w.$setter($val); }); }; (@set mapr2, $setter:ident, $val:expr) => { crate::pac::AFIO.mapr2().modify(|w| { w.$setter($val); }); }; (crate::$mod:ident::$trait:ident<$mode:ident>, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { $( impl crate::$mod::$trait> for crate::peripherals::$pin { fn afio_remap(&self) { pin_trait_afio_impl!(@set $reg, $setter, $val); } } )+ }; (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, {$reg:ident, $setter:ident, $type:ident, [$($val:expr),+]}) => { $( impl crate::$mod::$trait> for crate::peripherals::$pin { fn afio_remap(&self) { pin_trait_afio_impl!(@set $reg, $setter, $val); } } )+ }; } #[allow(unused_macros)] macro_rules! sel_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $sel:expr) => { impl crate::$mod::$trait for crate::peripherals::$pin { fn sel(&self) -> u8 { $sel } } }; } // ==================== macro_rules! dma_trait { ($signal:ident, $instance:path$(, $mode:path)?) => { #[doc = concat!(stringify!($signal), " DMA request trait")] pub trait $signal: crate::dma::Channel { #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] /// Note: in some chips, ST calls this the "channel", and calls channels "streams". /// `embassy-stm32` always uses the "channel" and "request number" names. fn request(&self) -> crate::dma::Request; #[doc = "Remap the DMA channel"] fn remap(&self); } }; } #[allow(unused)] macro_rules! dma_trait_impl { (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $channel:ident, $request:expr, $remap:expr) => { impl crate::$mod::$trait for crate::peripherals::$channel { fn request(&self) -> crate::dma::Request { $request } fn remap(&self) { critical_section::with(|_| { #[allow(unused_unsafe)] unsafe { $remap; } }); } } }; } #[allow(unused)] macro_rules! new_dma_nonopt { ($name:ident) => {{ let dma = $name; let request = dma.request(); crate::dma::ChannelAndRequest { channel: dma.into(), request, } }}; } macro_rules! new_dma { ($name:ident) => {{ let dma = $name; dma.remap(); let request = dma.request(); Some(crate::dma::ChannelAndRequest { channel: dma.into(), request, }) }}; } macro_rules! new_pin { ($name:ident, $af_type:expr) => {{ let pin = $name; #[cfg(afio)] pin.afio_remap(); pin.set_as_af( #[cfg(not(afio))] pin.af_num(), $af_type, ); Some(pin.into()) }}; } /// Macro to configure a pin for alternate function use. /// For AFIO chips (STM32F1), it calls afio_remap(). /// For non-AFIO chips, it calls set_as_af() with the pin's af_num(). macro_rules! set_as_af { ($pin:expr, $af_type:expr) => { #[cfg(afio)] { $pin.set_as_af($af_type); $pin.afio_remap(); } #[cfg(not(afio))] { $pin.set_as_af($pin.af_num(), $af_type); } }; } #[cfg(afio)] macro_rules! if_afio { ($($t:tt)*) => { $($t)* } } #[cfg(not(afio))] macro_rules! if_afio { (($a:ty, A)) => { ($a,) }; (($a:ty, $b:ty, A)) => { ($a,$b) }; (($a:ty, $b:ty, $c:ty, A)) => { ($a,$b, $c) }; ($type:ident<$lt:lifetime, $a:ty, $b:ty, A>) => { $type<$lt, $a, $b> }; ($type:ident<$lt:lifetime, $a:ty, $b:ty, $c:ty, A>) => { $type<$lt, $a, $b, $c> }; ($type:ident<$a:ty, A>) => { $type<$a> }; ($type:ident<$a:ty, $b:ty, A>) => { $type<$a, $b> }; ($type:ident<$a:ty, $b:ty, $c:ty, A>) => { $type<$a, $b, $c> }; (impl $trait:ident<$a:ty, A>) => { impl $trait<$a> }; (impl $trait:ident<$a:ty, $b:ty, A>) => { impl $trait<$a, $b> }; (impl $trait:ident<$a:ty, $b:ty, $c:ty, A>) => { impl $trait<$a, $b, $c> }; }