diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 40103d322..4856047ce 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -589,6 +589,16 @@ fn main() { (("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)), (("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)), (("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)), + (("hrtim", "CHA1"), quote!(crate::pwm::ChannelAPin)), + (("hrtim", "CHA2"), quote!(crate::pwm::ChannelAComplementaryPin)), + (("hrtim", "CHB1"), quote!(crate::pwm::ChannelBPin)), + (("hrtim", "CHB2"), quote!(crate::pwm::ChannelBComplementaryPin)), + (("hrtim", "CHC1"), quote!(crate::pwm::ChannelCPin)), + (("hrtim", "CHC2"), quote!(crate::pwm::ChannelCComplementaryPin)), + (("hrtim", "CHD1"), quote!(crate::pwm::ChannelDPin)), + (("hrtim", "CHD2"), quote!(crate::pwm::ChannelDComplementaryPin)), + (("hrtim", "CHE1"), quote!(crate::pwm::ChannelEPin)), + (("hrtim", "CHE2"), quote!(crate::pwm::ChannelEComplementaryPin)), (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)), (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)), (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)), diff --git a/embassy-stm32/src/pwm/advanced_pwm.rs b/embassy-stm32/src/pwm/advanced_pwm.rs new file mode 100644 index 000000000..39d60c50c --- /dev/null +++ b/embassy-stm32/src/pwm/advanced_pwm.rs @@ -0,0 +1,147 @@ +use core::marker::PhantomData; + +use embassy_hal_common::{into_ref, PeripheralRef}; + +use super::simple_pwm::*; +use super::*; +#[allow(unused_imports)] +use crate::gpio::sealed::{AFType, Pin}; +use crate::gpio::AnyPin; +use crate::time::Hertz; +use crate::Peripheral; + +// Re-implement the channels for hrtim +pub struct ChA; +pub struct ChB; +pub struct ChC; +pub struct ChD; +pub struct ChE; + +pub struct PwmPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, +} + +pub struct ComplementaryPwmPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, +} + +macro_rules! advanced_channel_impl { + ($new_chx:ident, $channel:ident, $pin_trait:ident, $complementary_pin_trait:ident) => { + impl<'d, Perip: AdvancedCaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + PwmPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } + } + + impl<'d, Perip: AdvancedCaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + ComplementaryPwmPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } + } + }; +} + +advanced_channel_impl!(new_cha, ChA, ChannelAPin, ChannelAComplementaryPin); +advanced_channel_impl!(new_chb, ChB, ChannelBPin, ChannelBComplementaryPin); +advanced_channel_impl!(new_chc, ChC, ChannelCPin, ChannelCComplementaryPin); +advanced_channel_impl!(new_chd, ChD, ChannelDPin, ChannelDComplementaryPin); +advanced_channel_impl!(new_che, ChE, ChannelEPin, ChannelEComplementaryPin); + +pub struct AdvancedPwm<'d, T> { + inner: PeripheralRef<'d, T>, +} + +impl<'d, T: ComplementaryCaptureCompare16bitInstance> AdvancedPwm<'d, T> { + pub fn new( + tim: impl Peripheral

+ 'd, + _ch1: Option>, + _ch1n: Option>, + _ch2: Option>, + _ch2n: Option>, + _ch3: Option>, + _ch3n: Option>, + _ch4: Option>, + _ch4n: Option>, + freq: Hertz, + ) -> Self { + Self::new_inner(tim, freq) + } + + fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz) -> Self { + into_ref!(tim); + + T::enable(); + ::reset(); + + let mut this = Self { inner: tim }; + // + // this.inner.set_frequency(freq); + // this.inner.start(); + // + // this.inner.enable_outputs(true); + // + // this.inner + // .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); + // this.inner + // .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); + // this.inner + // .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); + // this.inner + // .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); + this + } + + pub fn enable(&mut self, channel: AdvancedChannel) { + // self.inner.enable_channel(channel, true); + // self.inner.enable_complementary_channel(channel, true); + } + + pub fn disable(&mut self, channel: AdvancedChannel) { + // self.inner.enable_complementary_channel(channel, false); + // self.inner.enable_channel(channel, false); + } + + pub fn set_freq(&mut self, freq: Hertz) { + // self.inner.set_frequency(freq); + } + + pub fn get_max_duty(&self) -> u16 { + todo!() + // self.inner.get_max_compare_value() + } + + pub fn set_duty(&mut self, channel: AdvancedChannel, duty: u16) { + // assert!(duty < self.get_max_duty()); + // self.inner.set_compare_value(channel, duty) + } + + /// Set the dead time as a proportion of max_duty + pub fn set_dead_time(&mut self, value: u16) { + // let (ckd, value) = compute_dead_time_value(value); + // + // self.inner.set_dead_time_clock_division(ckd); + // self.inner.set_dead_time_value(value); + } +} diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index 5aba2663e..4c2031348 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs @@ -1,3 +1,5 @@ +#[cfg(hrtim_v1)] +pub mod advanced_pwm; pub mod complementary_pwm; pub mod simple_pwm; @@ -27,6 +29,29 @@ impl Channel { } } +#[cfg(hrtim_v1)] +#[derive(Clone, Copy)] +pub enum AdvancedChannel { + ChA, + ChB, + ChC, + ChD, + ChE, +} + +#[cfg(hrtim_v1)] +impl AdvancedChannel { + pub fn raw(&self) -> usize { + match self { + AdvancedChannel::ChA => 0, + AdvancedChannel::ChB => 1, + AdvancedChannel::ChC => 2, + AdvancedChannel::ChD => 3, + AdvancedChannel::ChE => 4, + } + } +} + #[derive(Clone, Copy)] pub enum OutputCompareMode { Frozen, @@ -57,6 +82,14 @@ impl From for stm32_metapac::timer::vals::Ocm { pub(crate) mod sealed { use super::*; + pub trait AdvancedCaptureCompare16bitInstance: crate::timer::sealed::HighResolutionControlInstance { + fn enable_outputs(&mut self, enable: bool); + + fn set_output_compare_mode(&mut self, channel: AdvancedChannel, mode: OutputCompareMode); + + fn enable_channel(&mut self, channel: AdvancedChannel, enable: bool); + } + pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { /// Global output enable. Does not do anything on non-advanced timers. fn enable_outputs(&mut self, enable: bool); @@ -89,6 +122,8 @@ pub(crate) mod sealed { } } +pub trait AdvancedCaptureCompare16bitInstance: sealed::AdvancedCaptureCompare16bitInstance + 'static {} + pub trait CaptureCompare16bitInstance: sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static { @@ -250,6 +285,20 @@ foreach_interrupt! { } }; + + ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { + impl crate::pwm::sealed::AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { + fn enable_outputs(&mut self, enable: bool) { todo!() } + + fn set_output_compare_mode(&mut self, channel: AdvancedChannel, mode: OutputCompareMode) { todo!() } + + fn enable_channel(&mut self, channel: AdvancedChannel, enable: bool) { todo!() } + } + + impl AdvancedCaptureCompare16bitInstance for crate::peripherals::$inst { + + } + }; } pin_trait!(Channel1Pin, CaptureCompare16bitInstance); @@ -267,3 +316,14 @@ pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance); pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); + +pin_trait!(ChannelAPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelAComplementaryPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelBPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelBComplementaryPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelCPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelCComplementaryPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelDPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelDComplementaryPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelEPin, AdvancedCaptureCompare16bitInstance); +pin_trait!(ChannelEComplementaryPin, AdvancedCaptureCompare16bitInstance); diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 09b7a3776..34ad5db11 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -43,6 +43,21 @@ pub(crate) mod sealed { pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { fn regs_advanced() -> crate::pac::timer::TimAdv; } + + #[cfg(hrtim_v1)] + pub trait HighResolutionControlInstance: RccPeripheral { + type Interrupt: interrupt::typelevel::Interrupt; + + fn regs_highres() -> crate::pac::hrtim::Hrtim; + + fn start(&mut self); + + fn stop(&mut self); + + fn reset(&mut self); + + fn set_frequency(&mut self, frequency: Hertz); + } } pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {} @@ -51,6 +66,9 @@ pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'st pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {} +#[cfg(hrtim_v1)] +pub trait HighResolutionControlInstance: sealed::HighResolutionControlInstance + 'static {} + pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} #[allow(unused)] @@ -208,4 +226,25 @@ foreach_interrupt! { impl AdvancedControlInstance for crate::peripherals::$inst { } }; + + ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { + impl sealed::HighResolutionControlInstance for crate::peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + + fn regs_highres() -> crate::pac::hrtim::Hrtim { + crate::pac::$inst + } + + fn start(&mut self) { todo!() } + + fn stop(&mut self) { todo!() } + + fn reset(&mut self) { todo!() } + + fn set_frequency(&mut self, frequency: Hertz) { todo!() } + } + + impl HighResolutionControlInstance for crate::peripherals::$inst { + } + }; }