diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index e643722aa..6377054c5 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -6,6 +6,8 @@ //! //! The available functionality depends on the timer type. +use core::mem::ManuallyDrop; + use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; // Re-export useful enums pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; @@ -198,6 +200,13 @@ impl<'d, T: CoreInstance> Timer<'d, T> { Self { tim } } + pub(crate) unsafe fn clone_unchecked(&self) -> ManuallyDrop { + // this doesn't work for some reason + // let tim = unsafe { self.tim.clone_unchecked() }; + let tim = todo!(); + ManuallyDrop::new(Self { tim }) + } + /// Get access to the virutal core 16bit timer registers. /// /// Note: This works even if the timer is more capable, because registers diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 25782ee13..6cf22689b 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -2,6 +2,7 @@ use core::marker::PhantomData; +use embassy_hal_internal::Peripheral; use embassy_sync::waitqueue::AtomicWaker; #[cfg(not(stm32l0))] diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 7e2e9c202..9e4a09095 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -1,6 +1,7 @@ //! Simple PWM driver. use core::marker::PhantomData; +use core::mem::ManuallyDrop; use embassy_hal_internal::{into_ref, PeripheralRef}; @@ -57,7 +58,7 @@ channel_impl!(new_ch4, Ch4, Channel4Pin); /// It is not possible to change the pwm frequency because /// the frequency configuration is shared with all four channels. pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { - timer: &'d Timer<'d, T>, + timer: ManuallyDrop>, channel: Channel, } @@ -199,7 +200,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// If you need to use multiple channels, use [`Self::split`]. pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> { SimplePwmChannel { - timer: &self.inner, + timer: unsafe { self.inner.clone_unchecked() }, channel, } } @@ -245,12 +246,16 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// This returns all four channels, including channels that /// aren't configured with a [`PwmPin`]. // TODO: I hate the name "split" - pub fn split(&mut self) -> SimplePwmChannels<'_, T> { - // TODO: pre-enable channels? + pub fn split(self) -> SimplePwmChannels<'static, T> + where + // must be static because the timer will never be dropped/disabled + 'd: 'static, + { + // without this, the timer would be disabled at the end of this function + let timer = ManuallyDrop::new(self.inner); - // we can't use self.channel() because that takes &mut self let ch = |channel| SimplePwmChannel { - timer: &self.inner, + timer: unsafe { timer.clone_unchecked() }, channel, };