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 {
+ }
+ };
}