Merge #605
605: stm32: Remove OptionalPin r=Dirbaio a=Dirbaio The idea behind OptionalPin has a few problems: - you need to impl the signal traits for NoPin which is a bit weird https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L413-L416 - you can pass any combination of set/unset pins, which needs checking at runtime https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/dcmi.rs#L130 The replacement is to do multiple `new` constructors for each combination of pins you want to take. Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
		| @@ -62,11 +62,11 @@ fn calc_prescs(freq: u32) -> (u8, u8) { | ||||
|  | ||||
| impl<'d, T: Instance> Spi<'d, T> { | ||||
|     pub fn new( | ||||
|         inner: impl Unborrow<Target = T>, | ||||
|         clk: impl Unborrow<Target = impl ClkPin<T>>, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<T>>, | ||||
|         cs: impl Unborrow<Target = impl CsPin<T>>, | ||||
|         inner: impl Unborrow<Target = T> + 'd, | ||||
|         clk: impl Unborrow<Target = impl ClkPin<T>> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<T>> + 'd, | ||||
|         cs: impl Unborrow<Target = impl CsPin<T>> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(inner, clk, mosi, miso, cs); | ||||
|   | ||||
| @@ -30,11 +30,11 @@ pub struct Uart<'d, T: Instance> { | ||||
|  | ||||
| impl<'d, T: Instance> Uart<'d, T> { | ||||
|     pub fn new( | ||||
|         inner: impl Unborrow<Target = T>, | ||||
|         tx: impl Unborrow<Target = impl TxPin<T>>, | ||||
|         rx: impl Unborrow<Target = impl RxPin<T>>, | ||||
|         cts: impl Unborrow<Target = impl CtsPin<T>>, | ||||
|         rts: impl Unborrow<Target = impl RtsPin<T>>, | ||||
|         inner: impl Unborrow<Target = T> + 'd, | ||||
|         tx: impl Unborrow<Target = impl TxPin<T>> + 'd, | ||||
|         rx: impl Unborrow<Target = impl RxPin<T>> + 'd, | ||||
|         cts: impl Unborrow<Target = impl CtsPin<T>> + 'd, | ||||
|         rts: impl Unborrow<Target = impl RtsPin<T>> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(inner, tx, rx, cts, rts); | ||||
|   | ||||
| @@ -1,16 +1,19 @@ | ||||
| use core::marker::PhantomData; | ||||
|  | ||||
| use crate::pac::CRC as PAC_CRC; | ||||
| use crate::peripherals::CRC; | ||||
| use crate::rcc::sealed::RccPeripheral; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
|  | ||||
| pub struct Crc { | ||||
| pub struct Crc<'d> { | ||||
|     _peripheral: CRC, | ||||
|     _phantom: PhantomData<&'d mut CRC>, | ||||
| } | ||||
|  | ||||
| impl Crc { | ||||
| impl<'d> Crc<'d> { | ||||
|     /// Instantiates the CRC32 peripheral and initializes it to default values. | ||||
|     pub fn new(peripheral: impl Unborrow<Target = CRC>) -> Self { | ||||
|     pub fn new(peripheral: impl Unborrow<Target = CRC> + 'd) -> Self { | ||||
|         // Note: enable and reset come from RccPeripheral. | ||||
|         // enable CRC clock in RCC. | ||||
|         CRC::enable(); | ||||
| @@ -20,6 +23,7 @@ impl Crc { | ||||
|         unborrow!(peripheral); | ||||
|         let mut instance = Self { | ||||
|             _peripheral: peripheral, | ||||
|             _phantom: PhantomData, | ||||
|         }; | ||||
|         instance.reset(); | ||||
|         instance | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| use core::marker::PhantomData; | ||||
|  | ||||
| use crate::pac::crc::vals; | ||||
| use crate::pac::CRC as PAC_CRC; | ||||
| use crate::peripherals::CRC; | ||||
| @@ -5,8 +7,9 @@ use crate::rcc::sealed::RccPeripheral; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
|  | ||||
| pub struct Crc { | ||||
| pub struct Crc<'d> { | ||||
|     _peripheral: CRC, | ||||
|     _phantom: PhantomData<&'d mut CRC>, | ||||
|     _config: Config, | ||||
| } | ||||
|  | ||||
| @@ -64,9 +67,9 @@ pub enum PolySize { | ||||
|     Width32, | ||||
| } | ||||
|  | ||||
| impl Crc { | ||||
| impl<'d> Crc<'d> { | ||||
|     /// Instantiates the CRC32 peripheral and initializes it to default values. | ||||
|     pub fn new(peripheral: impl Unborrow<Target = CRC>, config: Config) -> Self { | ||||
|     pub fn new(peripheral: impl Unborrow<Target = CRC> + 'd, config: Config) -> Self { | ||||
|         // Note: enable and reset come from RccPeripheral. | ||||
|         // enable CRC clock in RCC. | ||||
|         CRC::enable(); | ||||
| @@ -75,6 +78,7 @@ impl Crc { | ||||
|         unborrow!(peripheral); | ||||
|         let mut instance = Self { | ||||
|             _peripheral: peripheral, | ||||
|             _phantom: PhantomData, | ||||
|             _config: config, | ||||
|         }; | ||||
|         CRC::reset(); | ||||
|   | ||||
| @@ -3,27 +3,21 @@ | ||||
| #[cfg_attr(dac_v1, path = "v1.rs")] | ||||
| #[cfg_attr(dac_v2, path = "v2.rs")] | ||||
| mod _version; | ||||
| use crate::gpio::NoPin; | ||||
| use crate::peripherals; | ||||
| pub use _version::*; | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use crate::gpio::OptionalPin; | ||||
|  | ||||
|     pub trait Instance { | ||||
|         fn regs() -> &'static crate::pac::dac::Dac; | ||||
|     } | ||||
|  | ||||
|     pub trait DacPin<T: Instance, const C: u8>: OptionalPin {} | ||||
|     pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin {} | ||||
| } | ||||
|  | ||||
| pub trait Instance: sealed::Instance + 'static {} | ||||
|  | ||||
| pub trait DacPin<T: Instance, const C: u8>: sealed::DacPin<T, C> + 'static {} | ||||
|  | ||||
| impl<T: Instance, const C: u8> DacPin<T, C> for NoPin {} | ||||
| impl<T: Instance, const C: u8> sealed::DacPin<T, C> for NoPin {} | ||||
|  | ||||
| crate::pac::peripherals!( | ||||
|     (dac, $inst:ident) => { | ||||
|         impl crate::dac::sealed::Instance for peripherals::$inst { | ||||
|   | ||||
| @@ -1,33 +1,25 @@ | ||||
| use crate::dac::{DacPin, Instance}; | ||||
| use crate::gpio::AnyPin; | ||||
| use crate::pac::dac; | ||||
| use core::marker::PhantomData; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
|  | ||||
| /// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock | ||||
| /// configuration. | ||||
| unsafe fn enable() { | ||||
|     #[cfg(rcc_h7)] | ||||
|     crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||||
|     #[cfg(rcc_g0)] | ||||
|     crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true)); | ||||
|     #[cfg(rcc_l4)] | ||||
|     crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true)); | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Error { | ||||
|     UnconfiguredChannel, | ||||
|     InvalidValue, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Channel { | ||||
|     Ch1, | ||||
|     Ch2, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Ch1Trigger { | ||||
|     Tim6, | ||||
|     Tim3, | ||||
| @@ -52,6 +44,8 @@ impl Ch1Trigger { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Ch2Trigger { | ||||
|     Tim6, | ||||
|     Tim8, | ||||
| @@ -78,46 +72,61 @@ impl Ch2Trigger { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Alignment { | ||||
|     Left, | ||||
|     Right, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| pub enum Value { | ||||
|     Bit8(u8), | ||||
|     Bit12(u16, Alignment), | ||||
| } | ||||
|  | ||||
| pub struct Dac<'d, T: Instance> { | ||||
|     ch1: Option<AnyPin>, | ||||
|     ch2: Option<AnyPin>, | ||||
|     channels: u8, | ||||
|     phantom: PhantomData<&'d mut T>, | ||||
| } | ||||
|  | ||||
| impl<'d, T: Instance> Dac<'d, T> { | ||||
|     pub fn new( | ||||
|         _peri: impl Unborrow<Target = T> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl DacPin<T, 1>>, | ||||
|         ch2: impl Unborrow<Target = impl DacPin<T, 2>>, | ||||
|     pub fn new_1ch( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         _ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch1, ch2); | ||||
|         unborrow!(peri); | ||||
|         Self::new_inner(peri, 1) | ||||
|     } | ||||
|  | ||||
|     pub fn new_2ch( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         _ch1: impl Unborrow<Target = impl DacPin<T, 1>> + 'd, | ||||
|         _ch2: impl Unborrow<Target = impl DacPin<T, 2>> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri); | ||||
|         Self::new_inner(peri, 2) | ||||
|     } | ||||
|  | ||||
|     fn new_inner(_peri: T, channels: u8) -> Self { | ||||
|         unsafe { | ||||
|             enable(); | ||||
|         } | ||||
|             // Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock | ||||
|             // configuration. | ||||
|             #[cfg(rcc_h7)] | ||||
|             crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||||
|             #[cfg(rcc_g0)] | ||||
|             crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true)); | ||||
|             #[cfg(rcc_l4)] | ||||
|             crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true)); | ||||
|  | ||||
|         let ch1 = ch1.degrade_optional(); | ||||
|         if ch1.is_some() { | ||||
|             unsafe { | ||||
|             if channels >= 1 { | ||||
|                 T::regs().cr().modify(|reg| { | ||||
|                     reg.set_en1(true); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let ch2 = ch2.degrade_optional(); | ||||
|         if ch2.is_some() { | ||||
|             unsafe { | ||||
|             if channels >= 2 { | ||||
|                 T::regs().cr().modify(|reg| { | ||||
|                     reg.set_en2(true); | ||||
|                 }); | ||||
| @@ -125,41 +134,37 @@ impl<'d, T: Instance> Dac<'d, T> { | ||||
|         } | ||||
|  | ||||
|         Self { | ||||
|             ch1, | ||||
|             ch2, | ||||
|             channels, | ||||
|             phantom: PhantomData, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { | ||||
|         match ch { | ||||
|             Channel::Ch1 => { | ||||
|                 if self.ch1.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     unsafe { | ||||
|                         T::regs().cr().modify(|reg| { | ||||
|                             reg.set_en1(on); | ||||
|                         }); | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Channel::Ch2 => { | ||||
|                 if self.ch2.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     unsafe { | ||||
|                         T::regs().cr().modify(|reg| { | ||||
|                             reg.set_en2(on); | ||||
|                         }); | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|     /// Check the channel is configured | ||||
|     fn check_channel_exists(&self, ch: Channel) -> Result<(), Error> { | ||||
|         if ch == Channel::Ch2 && self.channels < 2 { | ||||
|             Err(Error::UnconfiguredChannel) | ||||
|         } else { | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { | ||||
|         self.check_channel_exists(ch)?; | ||||
|         match ch { | ||||
|             Channel::Ch1 => unsafe { | ||||
|                 T::regs().cr().modify(|reg| { | ||||
|                     reg.set_en1(on); | ||||
|                 }) | ||||
|             }, | ||||
|             Channel::Ch2 => unsafe { | ||||
|                 T::regs().cr().modify(|reg| { | ||||
|                     reg.set_en2(on); | ||||
|                 }); | ||||
|             }, | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> { | ||||
|         self.set_channel_enable(ch, true) | ||||
|     } | ||||
| @@ -169,9 +174,7 @@ impl<'d, T: Instance> Dac<'d, T> { | ||||
|     } | ||||
|  | ||||
|     pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { | ||||
|         if self.ch1.is_none() { | ||||
|             return Err(Error::UnconfiguredChannel); | ||||
|         } | ||||
|         self.check_channel_exists(Channel::Ch1)?; | ||||
|         unwrap!(self.disable_channel(Channel::Ch1)); | ||||
|         unsafe { | ||||
|             T::regs().cr().modify(|reg| { | ||||
| @@ -182,9 +185,7 @@ impl<'d, T: Instance> Dac<'d, T> { | ||||
|     } | ||||
|  | ||||
|     pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { | ||||
|         if self.ch2.is_none() { | ||||
|             return Err(Error::UnconfiguredChannel); | ||||
|         } | ||||
|         self.check_channel_exists(Channel::Ch2)?; | ||||
|         unwrap!(self.disable_channel(Channel::Ch2)); | ||||
|         unsafe { | ||||
|             T::regs().cr().modify(|reg| { | ||||
| @@ -195,32 +196,20 @@ impl<'d, T: Instance> Dac<'d, T> { | ||||
|     } | ||||
|  | ||||
|     pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { | ||||
|         self.check_channel_exists(ch)?; | ||||
|         match ch { | ||||
|             Channel::Ch1 => { | ||||
|                 if self.ch1.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     unsafe { | ||||
|                         T::regs().swtrigr().write(|reg| { | ||||
|                             reg.set_swtrig1(true); | ||||
|                         }); | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Channel::Ch2 => { | ||||
|                 if self.ch2.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     unsafe { | ||||
|                         T::regs().swtrigr().write(|reg| { | ||||
|                             reg.set_swtrig2(true); | ||||
|                         }); | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Channel::Ch1 => unsafe { | ||||
|                 T::regs().swtrigr().write(|reg| { | ||||
|                     reg.set_swtrig1(true); | ||||
|                 }); | ||||
|             }, | ||||
|             Channel::Ch2 => unsafe { | ||||
|                 T::regs().swtrigr().write(|reg| { | ||||
|                     reg.set_swtrig2(true); | ||||
|                 }) | ||||
|             }, | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn trigger_all(&mut self) { | ||||
| @@ -233,43 +222,31 @@ impl<'d, T: Instance> Dac<'d, T> { | ||||
|     } | ||||
|  | ||||
|     pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { | ||||
|         self.check_channel_exists(Channel::Ch2)?; | ||||
|         match ch { | ||||
|             Channel::Ch1 => { | ||||
|                 if self.ch1.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     match value { | ||||
|                         Value::Bit8(v) => unsafe { | ||||
|                             T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                         }, | ||||
|                         Value::Bit12(v, Alignment::Left) => unsafe { | ||||
|                             T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                         }, | ||||
|                         Value::Bit12(v, Alignment::Right) => unsafe { | ||||
|                             T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                         }, | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Channel::Ch2 => { | ||||
|                 if self.ch2.is_none() { | ||||
|                     Err(Error::UnconfiguredChannel) | ||||
|                 } else { | ||||
|                     match value { | ||||
|                         Value::Bit8(v) => unsafe { | ||||
|                             T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                         }, | ||||
|                         Value::Bit12(v, Alignment::Left) => unsafe { | ||||
|                             T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                         }, | ||||
|                         Value::Bit12(v, Alignment::Right) => unsafe { | ||||
|                             T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                         }, | ||||
|                     } | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Channel::Ch1 => match value { | ||||
|                 Value::Bit8(v) => unsafe { | ||||
|                     T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                 }, | ||||
|                 Value::Bit12(v, Alignment::Left) => unsafe { | ||||
|                     T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                 }, | ||||
|                 Value::Bit12(v, Alignment::Right) => unsafe { | ||||
|                     T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v)); | ||||
|                 }, | ||||
|             }, | ||||
|             Channel::Ch2 => match value { | ||||
|                 Value::Bit8(v) => unsafe { | ||||
|                     T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                 }, | ||||
|                 Value::Bit12(v, Alignment::Left) => unsafe { | ||||
|                     T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                 }, | ||||
|                 Value::Bit12(v, Alignment::Right) => unsafe { | ||||
|                     T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v)); | ||||
|                 }, | ||||
|             }, | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,15 @@ use embassy::waitqueue::AtomicWaker; | ||||
| use embassy_hal_common::unborrow; | ||||
| use futures::future::poll_fn; | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! configure { | ||||
|     ($($name:ident),*) => { | ||||
|         $( | ||||
|             unsafe { $name.unborrow() }.configure(); | ||||
|         )* | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// The level on the VSync pin when the data is not valid on the parallel interface. | ||||
| #[derive(Clone, Copy, PartialEq)] | ||||
| pub enum VSyncDataInvalidLevel { | ||||
| @@ -50,6 +59,23 @@ pub enum Error { | ||||
|     PeripheralError, | ||||
| } | ||||
|  | ||||
| #[non_exhaustive] | ||||
| pub struct Config { | ||||
|     pub vsync_level: VSyncDataInvalidLevel, | ||||
|     pub hsync_level: HSyncDataInvalidLevel, | ||||
|     pub pixclk_polarity: PixelClockPolarity, | ||||
| } | ||||
|  | ||||
| impl Default for Config { | ||||
|     fn default() -> Self { | ||||
|         Self { | ||||
|             vsync_level: VSyncDataInvalidLevel::High, | ||||
|             hsync_level: HSyncDataInvalidLevel::Low, | ||||
|             pixclk_polarity: PixelClockPolarity::RisingEdge, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Dcmi<'d, T: Instance, Dma: FrameDma> { | ||||
|     inner: T, | ||||
|     dma: Dma, | ||||
| @@ -61,13 +87,85 @@ where | ||||
|     T: Instance, | ||||
|     Dma: FrameDma, | ||||
| { | ||||
|     pub fn new( | ||||
|     pub fn new_8bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         v_sync: impl Unborrow<Target = impl VSyncPin> + 'd, | ||||
|         h_sync: impl Unborrow<Target = impl HSyncPin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7); | ||||
|         configure!(v_sync, h_sync, pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, false, 0b00) | ||||
|     } | ||||
|     pub fn new_10bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         d8: impl Unborrow<Target = impl D8Pin> + 'd, | ||||
|         d9: impl Unborrow<Target = impl D9Pin> + 'd, | ||||
|         v_sync: impl Unborrow<Target = impl VSyncPin> + 'd, | ||||
|         h_sync: impl Unborrow<Target = impl HSyncPin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9); | ||||
|         configure!(v_sync, h_sync, pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, false, 0b01) | ||||
|     } | ||||
|  | ||||
|     pub fn new_12bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         d8: impl Unborrow<Target = impl D8Pin> + 'd, | ||||
|         d9: impl Unborrow<Target = impl D9Pin> + 'd, | ||||
|         d10: impl Unborrow<Target = impl D10Pin> + 'd, | ||||
|         d11: impl Unborrow<Target = impl D11Pin> + 'd, | ||||
|         v_sync: impl Unborrow<Target = impl VSyncPin> + 'd, | ||||
|         h_sync: impl Unborrow<Target = impl HSyncPin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11); | ||||
|         configure!(v_sync, h_sync, pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, false, 0b10) | ||||
|     } | ||||
|     pub fn new_14bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         vsync_level: VSyncDataInvalidLevel, | ||||
|         hsync_level: HSyncDataInvalidLevel, | ||||
|         pixclk_polarity: PixelClockPolarity, | ||||
|         use_embedded_synchronization: bool, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
| @@ -86,58 +184,132 @@ where | ||||
|         v_sync: impl Unborrow<Target = impl VSyncPin> + 'd, | ||||
|         h_sync: impl Unborrow<Target = impl HSyncPin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13); | ||||
|         configure!(v_sync, h_sync, pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, false, 0b11) | ||||
|     } | ||||
|  | ||||
|     pub fn new_es_8bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7); | ||||
|         configure!(pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, true, 0b00) | ||||
|     } | ||||
|  | ||||
|     pub fn new_es_10bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         d8: impl Unborrow<Target = impl D8Pin> + 'd, | ||||
|         d9: impl Unborrow<Target = impl D9Pin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9); | ||||
|         configure!(pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, true, 0b01) | ||||
|     } | ||||
|  | ||||
|     pub fn new_es_12bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         d8: impl Unborrow<Target = impl D8Pin> + 'd, | ||||
|         d9: impl Unborrow<Target = impl D9Pin> + 'd, | ||||
|         d10: impl Unborrow<Target = impl D10Pin> + 'd, | ||||
|         d11: impl Unborrow<Target = impl D11Pin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11); | ||||
|         configure!(pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, true, 0b10) | ||||
|     } | ||||
|     pub fn new_es_14bit( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         dma: impl Unborrow<Target = Dma> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         d0: impl Unborrow<Target = impl D0Pin> + 'd, | ||||
|         d1: impl Unborrow<Target = impl D1Pin> + 'd, | ||||
|         d2: impl Unborrow<Target = impl D2Pin> + 'd, | ||||
|         d3: impl Unborrow<Target = impl D3Pin> + 'd, | ||||
|         d4: impl Unborrow<Target = impl D4Pin> + 'd, | ||||
|         d5: impl Unborrow<Target = impl D5Pin> + 'd, | ||||
|         d6: impl Unborrow<Target = impl D6Pin> + 'd, | ||||
|         d7: impl Unborrow<Target = impl D7Pin> + 'd, | ||||
|         d8: impl Unborrow<Target = impl D8Pin> + 'd, | ||||
|         d9: impl Unborrow<Target = impl D9Pin> + 'd, | ||||
|         d10: impl Unborrow<Target = impl D10Pin> + 'd, | ||||
|         d11: impl Unborrow<Target = impl D11Pin> + 'd, | ||||
|         d12: impl Unborrow<Target = impl D12Pin> + 'd, | ||||
|         d13: impl Unborrow<Target = impl D13Pin> + 'd, | ||||
|         pixclk: impl Unborrow<Target = impl PixClkPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(peri, dma, irq); | ||||
|         configure!(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13); | ||||
|         configure!(pixclk); | ||||
|  | ||||
|         Self::new_inner(peri, dma, irq, config, true, 0b11) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         peri: T, | ||||
|         dma: Dma, | ||||
|         irq: T::Interrupt, | ||||
|         config: Config, | ||||
|         use_embedded_synchronization: bool, | ||||
|         edm: u8, | ||||
|     ) -> Self { | ||||
|         T::reset(); | ||||
|         T::enable(); | ||||
|  | ||||
|         unborrow!( | ||||
|             peri, dma, irq, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, v_sync, | ||||
|             h_sync, pixclk | ||||
|         ); | ||||
|  | ||||
|         d0.configure(); | ||||
|         d1.configure(); | ||||
|         d2.configure(); | ||||
|         d3.configure(); | ||||
|         d4.configure(); | ||||
|         d5.configure(); | ||||
|         d6.configure(); | ||||
|         d7.configure(); | ||||
|         d8.configure(); | ||||
|         d9.configure(); | ||||
|         d10.configure(); | ||||
|         d11.configure(); | ||||
|         d12.configure(); | ||||
|         d13.configure(); | ||||
|  | ||||
|         v_sync.configure(); | ||||
|         h_sync.configure(); | ||||
|         pixclk.configure(); | ||||
|  | ||||
|         let edm = match ( | ||||
|             d8.pin().is_some(), | ||||
|             d9.pin().is_some(), | ||||
|             d10.pin().is_some(), | ||||
|             d11.pin().is_some(), | ||||
|             d12.pin().is_some(), | ||||
|             d13.pin().is_some(), | ||||
|         ) { | ||||
|             (true, true, true, true, true, true) => 0b11, // 14 bits | ||||
|             (true, true, true, true, false, false) => 0b10, // 12 bits | ||||
|             (true, true, false, false, false, false) => 0b01, // 10 bits | ||||
|             (false, false, false, false, false, false) => 0b00, // 8 bits | ||||
|             _ => { | ||||
|                 panic!("Invalid pin configuration."); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         unsafe { | ||||
|             peri.regs().cr().modify(|r| { | ||||
|                 r.set_cm(true); // disable continuous mode (snapshot mode) | ||||
|                 r.set_ess(use_embedded_synchronization); | ||||
|                 r.set_pckpol(pixclk_polarity == PixelClockPolarity::RisingEdge); | ||||
|                 r.set_vspol(vsync_level == VSyncDataInvalidLevel::High); | ||||
|                 r.set_hspol(hsync_level == HSyncDataInvalidLevel::High); | ||||
|                 r.set_pckpol(config.pixclk_polarity == PixelClockPolarity::RisingEdge); | ||||
|                 r.set_vspol(config.vsync_level == VSyncDataInvalidLevel::High); | ||||
|                 r.set_hspol(config.hsync_level == HSyncDataInvalidLevel::High); | ||||
|                 r.set_fcrc(0x00); // capture every frame | ||||
|                 r.set_edm(edm); // extended data mode | ||||
|             }); | ||||
| @@ -271,14 +443,6 @@ mod sealed { | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     macro_rules! optional_pin { | ||||
|         ($name:ident) => { | ||||
|             pub trait $name: crate::gpio::OptionalPin { | ||||
|                 fn configure(&mut self); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     pin!(D0Pin); | ||||
|     pin!(D1Pin); | ||||
|     pin!(D2Pin); | ||||
| @@ -287,15 +451,15 @@ mod sealed { | ||||
|     pin!(D5Pin); | ||||
|     pin!(D6Pin); | ||||
|     pin!(D7Pin); | ||||
|     optional_pin!(D8Pin); | ||||
|     optional_pin!(D9Pin); | ||||
|     optional_pin!(D10Pin); | ||||
|     optional_pin!(D11Pin); | ||||
|     optional_pin!(D12Pin); | ||||
|     optional_pin!(D13Pin); | ||||
|     pin!(D8Pin); | ||||
|     pin!(D9Pin); | ||||
|     pin!(D10Pin); | ||||
|     pin!(D11Pin); | ||||
|     pin!(D12Pin); | ||||
|     pin!(D13Pin); | ||||
|  | ||||
|     optional_pin!(HSyncPin); | ||||
|     optional_pin!(VSyncPin); | ||||
|     pin!(HSyncPin); | ||||
|     pin!(VSyncPin); | ||||
|     pin!(PixClkPin); | ||||
| } | ||||
|  | ||||
| @@ -408,24 +572,6 @@ macro_rules! impl_pin { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| macro_rules! impl_no_pin { | ||||
|     ($signal:ident) => { | ||||
|         impl sealed::$signal for crate::gpio::NoPin { | ||||
|             fn configure(&mut self) {} | ||||
|         } | ||||
|         impl $signal for crate::gpio::NoPin {} | ||||
|     }; | ||||
| } | ||||
|  | ||||
| impl_no_pin!(D8Pin); | ||||
| impl_no_pin!(D9Pin); | ||||
| impl_no_pin!(D10Pin); | ||||
| impl_no_pin!(D11Pin); | ||||
| impl_no_pin!(D12Pin); | ||||
| impl_no_pin!(D13Pin); | ||||
| impl_no_pin!(HSyncPin); | ||||
| impl_no_pin!(VSyncPin); | ||||
|  | ||||
| crate::pac::peripheral_pins!( | ||||
|     ($inst:ident, dcmi, DCMI, $pin:ident, D0, $af:expr) => { | ||||
|         impl_pin!($pin, D0Pin, $af); | ||||
|   | ||||
| @@ -544,54 +544,6 @@ impl sealed::Pin for AnyPin { | ||||
|  | ||||
| // ==================== | ||||
|  | ||||
| pub trait OptionalPin: sealed::OptionalPin + Sized { | ||||
|     type Pin: Pin; | ||||
|     fn pin(&self) -> Option<&Self::Pin>; | ||||
|     fn pin_mut(&mut self) -> Option<&mut Self::Pin>; | ||||
|  | ||||
|     /// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`. | ||||
|     #[inline] | ||||
|     fn degrade_optional(mut self) -> Option<AnyPin> { | ||||
|         self.pin_mut() | ||||
|             .map(|pin| unsafe { core::ptr::read(pin) }.degrade()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Pin> sealed::OptionalPin for T {} | ||||
| impl<T: Pin> OptionalPin for T { | ||||
|     type Pin = T; | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin(&self) -> Option<&T> { | ||||
|         Some(self) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin_mut(&mut self) -> Option<&mut T> { | ||||
|         Some(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| pub struct NoPin; | ||||
| unsafe_impl_unborrow!(NoPin); | ||||
| impl sealed::OptionalPin for NoPin {} | ||||
| impl OptionalPin for NoPin { | ||||
|     type Pin = AnyPin; | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin(&self) -> Option<&AnyPin> { | ||||
|         None | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin_mut(&mut self) -> Option<&mut AnyPin> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ==================== | ||||
|  | ||||
| crate::pac::pins!( | ||||
|     ($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => { | ||||
|         impl Pin for peripherals::$pin_name { | ||||
|   | ||||
| @@ -15,8 +15,8 @@ pub struct I2c<'d, T: Instance> { | ||||
| impl<'d, T: Instance> I2c<'d, T> { | ||||
|     pub fn new<F>( | ||||
|         _peri: impl Unborrow<Target = T> + 'd, | ||||
|         scl: impl Unborrow<Target = impl SclPin<T>>, | ||||
|         sda: impl Unborrow<Target = impl SdaPin<T>>, | ||||
|         scl: impl Unborrow<Target = impl SclPin<T>> + 'd, | ||||
|         sda: impl Unborrow<Target = impl SdaPin<T>> + 'd, | ||||
|         freq: F, | ||||
|     ) -> Self | ||||
|     where | ||||
|   | ||||
| @@ -248,31 +248,6 @@ crate::pac::interrupts! { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[allow(unused)] | ||||
| macro_rules! impl_pwm_nopin { | ||||
|     ($inst:ident) => { | ||||
|         impl_no_pin!($inst, Channel1Pin); | ||||
|         impl_no_pin!($inst, Channel1ComplementaryPin); | ||||
|         impl_no_pin!($inst, Channel2Pin); | ||||
|         impl_no_pin!($inst, Channel2ComplementaryPin); | ||||
|         impl_no_pin!($inst, Channel3Pin); | ||||
|         impl_no_pin!($inst, Channel3ComplementaryPin); | ||||
|         impl_no_pin!($inst, Channel4Pin); | ||||
|         impl_no_pin!($inst, Channel4ComplementaryPin); | ||||
|         impl_no_pin!($inst, ExternalTriggerPin); | ||||
|         impl_no_pin!($inst, BreakInputPin); | ||||
|         impl_no_pin!($inst, BreakInputComparator1Pin); | ||||
|         impl_no_pin!($inst, BreakInputComparator2Pin); | ||||
|         impl_no_pin!($inst, BreakInput2Pin); | ||||
|         impl_no_pin!($inst, BreakInput2Comparator1Pin); | ||||
|         impl_no_pin!($inst, BreakInput2Comparator2Pin); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| crate::pac::peripherals!( | ||||
|     (timer, $inst:ident) => { impl_pwm_nopin!($inst); }; | ||||
| ); | ||||
|  | ||||
| crate::pac::peripheral_pins!( | ||||
|     ($inst:ident, timer, $block:ident, $pin:ident, CH1, $af:expr) => { | ||||
|         impl_pin!($inst, Channel1Pin, $pin, $af); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| use crate::gpio::OptionalPin; | ||||
| use crate::gpio::Pin; | ||||
|  | ||||
| #[cfg(feature = "unstable-pac")] | ||||
| pub mod low_level { | ||||
| @@ -6,118 +6,106 @@ pub mod low_level { | ||||
| } | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use crate::gpio::sealed::OptionalPin; | ||||
|     use crate::gpio::sealed::Pin; | ||||
|  | ||||
|     pub trait Channel1Pin<Timer>: OptionalPin { | ||||
|     pub trait Channel1Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait Channel1ComplementaryPin<Timer>: OptionalPin { | ||||
|     pub trait Channel1ComplementaryPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait Channel2Pin<Timer>: OptionalPin { | ||||
|     pub trait Channel2Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait Channel2ComplementaryPin<Timer>: OptionalPin { | ||||
|     pub trait Channel2ComplementaryPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait Channel3Pin<Timer>: OptionalPin { | ||||
|     pub trait Channel3Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait Channel3ComplementaryPin<Timer>: OptionalPin { | ||||
|     pub trait Channel3ComplementaryPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait Channel4Pin<Timer>: OptionalPin { | ||||
|     pub trait Channel4Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait Channel4ComplementaryPin<Timer>: OptionalPin { | ||||
|     pub trait Channel4ComplementaryPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait ExternalTriggerPin<Timer>: OptionalPin { | ||||
|     pub trait ExternalTriggerPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait BreakInputPin<Timer>: OptionalPin { | ||||
|     pub trait BreakInputPin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait BreakInputComparator1Pin<Timer>: OptionalPin { | ||||
|     pub trait BreakInputComparator1Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait BreakInputComparator2Pin<Timer>: OptionalPin { | ||||
|     pub trait BreakInputComparator2Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|  | ||||
|     pub trait BreakInput2Pin<Timer>: OptionalPin { | ||||
|     pub trait BreakInput2Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait BreakInput2Comparator1Pin<Timer>: OptionalPin { | ||||
|     pub trait BreakInput2Comparator1Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
|     pub trait BreakInput2Comparator2Pin<Timer>: OptionalPin { | ||||
|     pub trait BreakInput2Comparator2Pin<Timer>: Pin { | ||||
|         unsafe fn configure(&mut self); | ||||
|     } | ||||
| } | ||||
| pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + OptionalPin + 'static {} | ||||
| pub trait Channel1Pin<Timer>: sealed::Channel1Pin<Timer> + Pin + 'static {} | ||||
| pub trait Channel1ComplementaryPin<Timer>: | ||||
|     sealed::Channel1ComplementaryPin<Timer> + OptionalPin + 'static | ||||
|     sealed::Channel1ComplementaryPin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| pub trait Channel2Pin<Timer>: sealed::Channel2Pin<Timer> + 'static {} | ||||
| pub trait Channel2ComplementaryPin<Timer>: | ||||
|     sealed::Channel2ComplementaryPin<Timer> + OptionalPin + 'static | ||||
|     sealed::Channel2ComplementaryPin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| pub trait Channel3Pin<Timer>: sealed::Channel3Pin<Timer> + 'static {} | ||||
| pub trait Channel3ComplementaryPin<Timer>: | ||||
|     sealed::Channel3ComplementaryPin<Timer> + OptionalPin + 'static | ||||
|     sealed::Channel3ComplementaryPin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| pub trait Channel4Pin<Timer>: sealed::Channel4Pin<Timer> + 'static {} | ||||
| pub trait Channel4ComplementaryPin<Timer>: | ||||
|     sealed::Channel4ComplementaryPin<Timer> + OptionalPin + 'static | ||||
|     sealed::Channel4ComplementaryPin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| pub trait ExternalTriggerPin<Timer>: | ||||
|     sealed::ExternalTriggerPin<Timer> + OptionalPin + 'static | ||||
| { | ||||
| } | ||||
| pub trait ExternalTriggerPin<Timer>: sealed::ExternalTriggerPin<Timer> + Pin + 'static {} | ||||
|  | ||||
| pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + OptionalPin + 'static {} | ||||
| pub trait BreakInputPin<Timer>: sealed::BreakInputPin<Timer> + Pin + 'static {} | ||||
| pub trait BreakInputComparator1Pin<Timer>: | ||||
|     sealed::BreakInputComparator1Pin<Timer> + OptionalPin + 'static | ||||
|     sealed::BreakInputComparator1Pin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
| pub trait BreakInputComparator2Pin<Timer>: | ||||
|     sealed::BreakInputComparator2Pin<Timer> + OptionalPin + 'static | ||||
|     sealed::BreakInputComparator2Pin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + OptionalPin + 'static {} | ||||
| pub trait BreakInput2Pin<Timer>: sealed::BreakInput2Pin<Timer> + Pin + 'static {} | ||||
| pub trait BreakInput2Comparator1Pin<Timer>: | ||||
|     sealed::BreakInput2Comparator1Pin<Timer> + OptionalPin + 'static | ||||
|     sealed::BreakInput2Comparator1Pin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
| pub trait BreakInput2Comparator2Pin<Timer>: | ||||
|     sealed::BreakInput2Comparator2Pin<Timer> + OptionalPin + 'static | ||||
|     sealed::BreakInput2Comparator2Pin<Timer> + Pin + 'static | ||||
| { | ||||
| } | ||||
|  | ||||
| macro_rules! impl_no_pin { | ||||
|     ($timer:ident, $signal:ident) => { | ||||
|         impl crate::pwm::pins::sealed::$signal<crate::peripherals::$timer> for crate::gpio::NoPin { | ||||
|             unsafe fn configure(&mut self) {} | ||||
|         } | ||||
|         impl crate::pwm::pins::$signal<crate::peripherals::$timer> for crate::gpio::NoPin {} | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[allow(unused)] | ||||
| macro_rules! impl_pin { | ||||
|     ($timer:ident, $signal:ident, $pin:ident, $af:expr) => { | ||||
|   | ||||
| @@ -12,7 +12,46 @@ pub struct SimplePwm<'d, T> { | ||||
| } | ||||
|  | ||||
| impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> { | ||||
|     pub fn new<F: Into<Hertz>>( | ||||
|     pub fn new_1ch<F: Into<Hertz>>( | ||||
|         tim: impl Unborrow<Target = T> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd, | ||||
|         freq: F, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch1); | ||||
|         Self::new_inner(tim, freq, move || unsafe { | ||||
|             ch1.configure(); | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn new_2ch<F: Into<Hertz>>( | ||||
|         tim: impl Unborrow<Target = T> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd, | ||||
|         freq: F, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch1, ch2); | ||||
|         Self::new_inner(tim, freq, move || unsafe { | ||||
|             ch1.configure(); | ||||
|             ch2.configure(); | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn new_3ch<F: Into<Hertz>>( | ||||
|         tim: impl Unborrow<Target = T> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd, | ||||
|         ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd, | ||||
|         freq: F, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch1, ch2, ch3); | ||||
|         Self::new_inner(tim, freq, move || unsafe { | ||||
|             ch1.configure(); | ||||
|             ch2.configure(); | ||||
|             ch3.configure(); | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn new_4ch<F: Into<Hertz>>( | ||||
|         tim: impl Unborrow<Target = T> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd, | ||||
| @@ -20,17 +59,26 @@ impl<'d, T: CaptureCompareCapable16bitInstance> SimplePwm<'d, T> { | ||||
|         ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd, | ||||
|         freq: F, | ||||
|     ) -> Self { | ||||
|         unborrow!(tim, ch1, ch2, ch3, ch4); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|  | ||||
|         unsafe { | ||||
|         unborrow!(ch1, ch2, ch3, ch4); | ||||
|         Self::new_inner(tim, freq, move || unsafe { | ||||
|             ch1.configure(); | ||||
|             ch2.configure(); | ||||
|             ch3.configure(); | ||||
|             ch4.configure(); | ||||
|         } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn new_inner<F: Into<Hertz>>( | ||||
|         tim: impl Unborrow<Target = T> + 'd, | ||||
|         freq: F, | ||||
|         configure_pins: impl FnOnce(), | ||||
|     ) -> Self { | ||||
|         unborrow!(tim); | ||||
|  | ||||
|         T::enable(); | ||||
|         <T as crate::rcc::sealed::RccPeripheral>::reset(); | ||||
|  | ||||
|         configure_pins(); | ||||
|  | ||||
|         let mut this = Self { | ||||
|             inner: tim, | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #![macro_use] | ||||
|  | ||||
| use core::marker::PhantomData; | ||||
| use core::task::Poll; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy::waitqueue::AtomicWaker; | ||||
| @@ -18,16 +19,20 @@ pub enum Error { | ||||
|     ClockError, | ||||
| } | ||||
|  | ||||
| pub struct Rng<T: Instance> { | ||||
| pub struct Rng<'d, T: Instance> { | ||||
|     _inner: T, | ||||
|     _phantom: PhantomData<&'d mut T>, | ||||
| } | ||||
|  | ||||
| impl<T: Instance> Rng<T> { | ||||
|     pub fn new(inner: impl Unborrow<Target = T>) -> Self { | ||||
| impl<'d, T: Instance> Rng<'d, T> { | ||||
|     pub fn new(inner: impl Unborrow<Target = T> + 'd) -> Self { | ||||
|         T::enable(); | ||||
|         T::reset(); | ||||
|         unborrow!(inner); | ||||
|         let mut random = Self { _inner: inner }; | ||||
|         let mut random = Self { | ||||
|             _inner: inner, | ||||
|             _phantom: PhantomData, | ||||
|         }; | ||||
|         random.reset(); | ||||
|         random | ||||
|     } | ||||
| @@ -88,7 +93,7 @@ impl<T: Instance> Rng<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Instance> RngCore for Rng<T> { | ||||
| impl<'d, T: Instance> RngCore for Rng<'d, T> { | ||||
|     fn next_u32(&mut self) -> u32 { | ||||
|         loop { | ||||
|             let bits = unsafe { T::regs().sr().read() }; | ||||
| @@ -119,7 +124,7 @@ impl<T: Instance> RngCore for Rng<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: Instance> CryptoRng for Rng<T> {} | ||||
| impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use super::*; | ||||
|   | ||||
| @@ -189,7 +189,7 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | ||||
|     pub unsafe fn new( | ||||
|         _peripheral: impl Unborrow<Target = T> + 'd, | ||||
|         pins: impl Unborrow<Target = P> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt>, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(irq, pins); | ||||
|   | ||||
| @@ -8,8 +8,8 @@ use embassy_hal_common::unborrow; | ||||
| use self::sealed::WordSize; | ||||
| use crate::dma; | ||||
| use crate::dma::NoDma; | ||||
| use crate::gpio::sealed::{AFType, Pin}; | ||||
| use crate::gpio::{AnyPin, NoPin, OptionalPin}; | ||||
| use crate::gpio::sealed::{AFType, Pin as _}; | ||||
| use crate::gpio::{AnyPin, Pin}; | ||||
| use crate::pac::spi::{regs, vals}; | ||||
| use crate::peripherals; | ||||
| use crate::rcc::RccPeripheral; | ||||
| @@ -92,45 +92,126 @@ pub struct Spi<'d, T: Instance, Tx, Rx> { | ||||
|  | ||||
| impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|     pub fn new<F>( | ||||
|         _peri: impl Unborrow<Target = T> + 'd, | ||||
|         sck: impl Unborrow<Target = impl SckPin<T>>, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<T>>, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<T>>, | ||||
|         txdma: impl Unborrow<Target = Tx>, | ||||
|         rxdma: impl Unborrow<Target = Rx>, | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         sck: impl Unborrow<Target = impl SckPin<T>> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<T>> + 'd, | ||||
|         txdma: impl Unborrow<Target = Tx> + 'd, | ||||
|         rxdma: impl Unborrow<Target = Rx> + 'd, | ||||
|         freq: F, | ||||
|         config: Config, | ||||
|     ) -> Self | ||||
|     where | ||||
|         F: Into<Hertz>, | ||||
|     { | ||||
|         unborrow!(sck, mosi, miso, txdma, rxdma); | ||||
|  | ||||
|         let sck_af = sck.af_num(); | ||||
|         let mosi_af = mosi.af_num(); | ||||
|         let miso_af = miso.af_num(); | ||||
|         let sck = sck.degrade_optional(); | ||||
|         let mosi = mosi.degrade_optional(); | ||||
|         let miso = miso.degrade_optional(); | ||||
|  | ||||
|         unborrow!(sck, mosi, miso); | ||||
|         unsafe { | ||||
|             sck.as_ref().map(|x| { | ||||
|                 x.set_as_af(sck_af, AFType::OutputPushPull); | ||||
|                 #[cfg(any(spi_v2, spi_v3))] | ||||
|                 x.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             }); | ||||
|             mosi.as_ref().map(|x| { | ||||
|                 x.set_as_af(mosi_af, AFType::OutputPushPull); | ||||
|                 #[cfg(any(spi_v2, spi_v3))] | ||||
|                 x.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             }); | ||||
|             miso.as_ref().map(|x| { | ||||
|                 x.set_as_af(miso_af, AFType::Input); | ||||
|                 #[cfg(any(spi_v2, spi_v3))] | ||||
|                 x.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             }); | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             mosi.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             miso.set_as_af(miso.af_num(), AFType::Input); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             miso.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
|         Self::new_inner( | ||||
|             peri, | ||||
|             Some(sck.degrade()), | ||||
|             Some(mosi.degrade()), | ||||
|             Some(miso.degrade()), | ||||
|             txdma, | ||||
|             rxdma, | ||||
|             freq, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     pub fn new_rxonly<F>( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         sck: impl Unborrow<Target = impl SckPin<T>> + 'd, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<T>> + 'd, | ||||
|         txdma: impl Unborrow<Target = Tx> + 'd, // TODO remove | ||||
|         rxdma: impl Unborrow<Target = Rx> + 'd, | ||||
|         freq: F, | ||||
|         config: Config, | ||||
|     ) -> Self | ||||
|     where | ||||
|         F: Into<Hertz>, | ||||
|     { | ||||
|         unborrow!(sck, miso); | ||||
|         unsafe { | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             miso.set_as_af(miso.af_num(), AFType::Input); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             miso.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
|         Self::new_inner( | ||||
|             peri, | ||||
|             Some(sck.degrade()), | ||||
|             None, | ||||
|             Some(miso.degrade()), | ||||
|             txdma, | ||||
|             rxdma, | ||||
|             freq, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     pub fn new_txonly<F>( | ||||
|         peri: impl Unborrow<Target = T> + 'd, | ||||
|         sck: impl Unborrow<Target = impl SckPin<T>> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<T>> + 'd, | ||||
|         txdma: impl Unborrow<Target = Tx> + 'd, | ||||
|         rxdma: impl Unborrow<Target = Rx> + 'd, // TODO remove | ||||
|         freq: F, | ||||
|         config: Config, | ||||
|     ) -> Self | ||||
|     where | ||||
|         F: Into<Hertz>, | ||||
|     { | ||||
|         unborrow!(sck, mosi); | ||||
|         unsafe { | ||||
|             sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             sck.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|             mosi.set_as_af(mosi.af_num(), AFType::OutputPushPull); | ||||
|             #[cfg(any(spi_v2, spi_v3))] | ||||
|             mosi.set_speed(crate::gpio::Speed::VeryHigh); | ||||
|         } | ||||
|  | ||||
|         Self::new_inner( | ||||
|             peri, | ||||
|             Some(sck.degrade()), | ||||
|             Some(mosi.degrade()), | ||||
|             None, | ||||
|             txdma, | ||||
|             rxdma, | ||||
|             freq, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fn new_inner<F>( | ||||
|         _peri: impl Unborrow<Target = T> + 'd, | ||||
|         sck: Option<AnyPin>, | ||||
|         mosi: Option<AnyPin>, | ||||
|         miso: Option<AnyPin>, | ||||
|         txdma: impl Unborrow<Target = Tx> + 'd, | ||||
|         rxdma: impl Unborrow<Target = Rx> + 'd, | ||||
|         freq: F, | ||||
|         config: Config, | ||||
|     ) -> Self | ||||
|     where | ||||
|         F: Into<Hertz>, | ||||
|     { | ||||
|         unborrow!(txdma, rxdma); | ||||
|  | ||||
|         let pclk = T::frequency(); | ||||
|         let br = compute_baud_rate(pclk, freq.into()); | ||||
|  | ||||
| @@ -719,15 +800,15 @@ pub(crate) mod sealed { | ||||
|         fn regs() -> &'static crate::pac::spi::Spi; | ||||
|     } | ||||
|  | ||||
|     pub trait SckPin<T: Instance>: OptionalPin { | ||||
|     pub trait SckPin<T: Instance>: Pin { | ||||
|         fn af_num(&self) -> u8; | ||||
|     } | ||||
|  | ||||
|     pub trait MosiPin<T: Instance>: OptionalPin { | ||||
|     pub trait MosiPin<T: Instance>: Pin { | ||||
|         fn af_num(&self) -> u8; | ||||
|     } | ||||
|  | ||||
|     pub trait MisoPin<T: Instance>: OptionalPin { | ||||
|     pub trait MisoPin<T: Instance>: Pin { | ||||
|         fn af_num(&self) -> u8; | ||||
|     } | ||||
|  | ||||
| @@ -865,26 +946,6 @@ crate::pac::peripheral_pins!( | ||||
|     }; | ||||
| ); | ||||
|  | ||||
| macro_rules! impl_nopin { | ||||
|     ($inst:ident, $signal:ident) => { | ||||
|         impl $signal<peripherals::$inst> for NoPin {} | ||||
|  | ||||
|         impl sealed::$signal<peripherals::$inst> for NoPin { | ||||
|             fn af_num(&self) -> u8 { | ||||
|                 0 | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| crate::pac::peripherals!( | ||||
|     (spi, $inst:ident) => { | ||||
|         impl_nopin!($inst, SckPin); | ||||
|         impl_nopin!($inst, MosiPin); | ||||
|         impl_nopin!($inst, MisoPin); | ||||
|     }; | ||||
| ); | ||||
|  | ||||
| macro_rules! impl_dma { | ||||
|     ($inst:ident, {dmamux: $dmamux:ident}, $signal:ident, $request:expr) => { | ||||
|         impl<T> sealed::$signal<peripherals::$inst> for T | ||||
|   | ||||
| @@ -215,11 +215,11 @@ impl<'d, Tx, Rx> SubGhz<'d, Tx, Rx> { | ||||
|     /// clock. | ||||
|     pub fn new( | ||||
|         peri: impl Unborrow<Target = SUBGHZSPI> + 'd, | ||||
|         sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>>, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>>, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>>, | ||||
|         txdma: impl Unborrow<Target = Tx>, | ||||
|         rxdma: impl Unborrow<Target = Rx>, | ||||
|         sck: impl Unborrow<Target = impl SckPin<SUBGHZSPI>> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl MosiPin<SUBGHZSPI>> + 'd, | ||||
|         miso: impl Unborrow<Target = impl MisoPin<SUBGHZSPI>> + 'd, | ||||
|         txdma: impl Unborrow<Target = Tx> + 'd, | ||||
|         rxdma: impl Unborrow<Target = Rx> + 'd, | ||||
|     ) -> Self { | ||||
|         Self::pulse_radio_reset(); | ||||
|  | ||||
|   | ||||
| @@ -81,11 +81,11 @@ pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { | ||||
|  | ||||
| impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | ||||
|     pub fn new( | ||||
|         inner: impl Unborrow<Target = T>, | ||||
|         rx: impl Unborrow<Target = impl RxPin<T>>, | ||||
|         tx: impl Unborrow<Target = impl TxPin<T>>, | ||||
|         tx_dma: impl Unborrow<Target = TxDma>, | ||||
|         rx_dma: impl Unborrow<Target = RxDma>, | ||||
|         inner: impl Unborrow<Target = T> + 'd, | ||||
|         rx: impl Unborrow<Target = impl RxPin<T>> + 'd, | ||||
|         tx: impl Unborrow<Target = impl TxPin<T>> + 'd, | ||||
|         tx_dma: impl Unborrow<Target = TxDma> + 'd, | ||||
|         rx_dma: impl Unborrow<Target = RxDma> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(inner, rx, tx, tx_dma, rx_dma); | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| mod example_common; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_stm32::gpio::NoPin; | ||||
| use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; | ||||
| use embassy_stm32::time::U32Ext; | ||||
| use embassy_stm32::Peripherals; | ||||
| @@ -16,7 +15,7 @@ use example_common::*; | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     info!("Hello World!"); | ||||
|  | ||||
|     let mut pwm = SimplePwm::new(p.TIM2, p.PA5, NoPin, NoPin, NoPin, 10000.hz()); | ||||
|     let mut pwm = SimplePwm::new_1ch(p.TIM2, p.PA5, 10000.hz()); | ||||
|     let max = pwm.get_max_duty(); | ||||
|     pwm.enable(Channel::Ch1); | ||||
|  | ||||
|   | ||||
| @@ -4,8 +4,8 @@ | ||||
|  | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_stm32::dcmi::*; | ||||
| use embassy_stm32::gpio::{Level, NoPin, Output, Speed}; | ||||
| use embassy_stm32::dcmi::{self, *}; | ||||
| use embassy_stm32::gpio::{Level, Output, Speed}; | ||||
| use embassy_stm32::i2c::I2c; | ||||
| use embassy_stm32::interrupt; | ||||
| use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; | ||||
| @@ -78,31 +78,10 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     ); | ||||
|  | ||||
|     let dcmi_irq = interrupt::take!(DCMI); | ||||
|     let mut dcmi = Dcmi::new( | ||||
|         p.DCMI, | ||||
|         p.DMA1_CH0, | ||||
|         VSyncDataInvalidLevel::High, | ||||
|         HSyncDataInvalidLevel::Low, | ||||
|         PixelClockPolarity::RisingEdge, | ||||
|         false, | ||||
|         dcmi_irq, | ||||
|         p.PC6, | ||||
|         p.PC7, | ||||
|         p.PE0, | ||||
|         p.PE1, | ||||
|         p.PE4, | ||||
|         p.PD3, | ||||
|         p.PE5, | ||||
|         p.PE6, | ||||
|         NoPin, | ||||
|         NoPin, | ||||
|         NoPin, | ||||
|         NoPin, | ||||
|         NoPin, | ||||
|         NoPin, | ||||
|         p.PB7, | ||||
|         p.PA4, | ||||
|         p.PA6, | ||||
|     let config = dcmi::Config::default(); | ||||
|     let mut dcmi = Dcmi::new_8bit( | ||||
|         p.DCMI, p.DMA1_CH0, dcmi_irq, p.PC6, p.PC7, p.PE0, p.PE1, p.PE4, p.PD3, p.PE5, p.PE6, | ||||
|         p.PB7, p.PA4, p.PA6, config, | ||||
|     ); | ||||
|  | ||||
|     defmt::info!("attempting capture"); | ||||
|   | ||||
| @@ -5,7 +5,6 @@ | ||||
| #[path = "../example_common.rs"] | ||||
| mod example_common; | ||||
|  | ||||
| use embassy_stm32::gpio::NoPin; | ||||
| use example_common::*; | ||||
|  | ||||
| use cortex_m_rt::entry; | ||||
| @@ -17,7 +16,7 @@ fn main() -> ! { | ||||
|  | ||||
|     let p = embassy_stm32::init(config()); | ||||
|  | ||||
|     let mut dac = Dac::new(p.DAC1, p.PA4, NoPin); | ||||
|     let mut dac = Dac::new_1ch(p.DAC1, p.PA4); | ||||
|  | ||||
|     loop { | ||||
|         for v in 0..=255 { | ||||
|   | ||||
| @@ -10,7 +10,6 @@ use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
| use embassy_stm32::gpio::NoPin; | ||||
| use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode}; | ||||
| use embassy_stm32::time::{Hertz, U32Ext}; | ||||
| use embassy_stm32::timer::GeneralPurpose32bitInstance; | ||||
| @@ -33,7 +32,7 @@ pub fn config() -> Config { | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     info!("Hello World!"); | ||||
|  | ||||
|     let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, NoPin, NoPin, NoPin, 10000.hz()); | ||||
|     let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, p.PA1, p.PA2, p.PA3, 10000.hz()); | ||||
|     let max = pwm.get_max_duty(); | ||||
|     pwm.enable(Channel::Ch1); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| mod example_common; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_stm32::gpio::NoPin; | ||||
| use embassy_stm32::pwm::{simple_pwm::SimplePwm, Channel}; | ||||
| use embassy_stm32::time::U32Ext; | ||||
| use embassy_stm32::{Config, Peripherals}; | ||||
| @@ -28,7 +27,7 @@ pub fn config() -> Config { | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     info!("Hello World!"); | ||||
|  | ||||
|     let mut pwm = SimplePwm::new(p.TIM3, p.PA6, NoPin, NoPin, NoPin, 10000.hz()); | ||||
|     let mut pwm = SimplePwm::new_1ch(p.TIM3, p.PA6, 10000.hz()); | ||||
|     let max = pwm.get_max_duty(); | ||||
|     pwm.enable(Channel::Ch1); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| mod example_common; | ||||
|  | ||||
| use embassy_stm32::dac::{Channel, Dac, Value}; | ||||
| use embassy_stm32::gpio::NoPin; | ||||
| use embassy_stm32::pac; | ||||
| use example_common::*; | ||||
|  | ||||
| @@ -22,7 +21,7 @@ fn main() -> ! { | ||||
|  | ||||
|     let p = embassy_stm32::init(Default::default()); | ||||
|  | ||||
|     let mut dac = Dac::new(p.DAC1, p.PA4, NoPin); | ||||
|     let mut dac = Dac::new_1ch(p.DAC1, p.PA4); | ||||
|  | ||||
|     loop { | ||||
|         for v in 0..=255 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user