Merge pull request #2735 from eZioPan/stm32-timer-api-leak

stm32: fix timer api leaking
This commit is contained in:
Dario Nieuwenhuis 2024-04-04 23:04:38 +00:00 committed by GitHub
commit 9d0b682b2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 115 additions and 65 deletions

View file

@ -15,9 +15,7 @@ use crate::pac::timer::vals;
use crate::rcc::SealedRccPeripheral; use crate::rcc::SealedRccPeripheral;
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
use crate::rtc::Rtc; use crate::rtc::Rtc;
#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] use crate::timer::{CoreInstance, GeneralInstance1Channel};
use crate::timer::AdvancedInstance1Channel;
use crate::timer::CoreInstance;
use crate::{interrupt, peripherals}; use crate::{interrupt, peripherals};
// NOTE regarding ALARM_COUNT: // NOTE regarding ALARM_COUNT:
@ -69,7 +67,7 @@ type T = peripherals::TIM23;
type T = peripherals::TIM24; type T = peripherals::TIM24;
foreach_interrupt! { foreach_interrupt! {
(TIM1, timer, $block:ident, UP, $irq:ident) => { (TIM1, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim1)] #[cfg(time_driver_tim1)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -85,7 +83,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM2, timer, $block:ident, UP, $irq:ident) => { (TIM2, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim2)] #[cfg(time_driver_tim2)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -93,7 +91,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM3, timer, $block:ident, UP, $irq:ident) => { (TIM3, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim3)] #[cfg(time_driver_tim3)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -101,7 +99,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM4, timer, $block:ident, UP, $irq:ident) => { (TIM4, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim4)] #[cfg(time_driver_tim4)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -109,7 +107,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM5, timer, $block:ident, UP, $irq:ident) => { (TIM5, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim5)] #[cfg(time_driver_tim5)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -117,7 +115,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM8, timer, $block:ident, UP, $irq:ident) => { (TIM8, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim8)] #[cfg(time_driver_tim8)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -133,7 +131,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM9, timer, $block:ident, UP, $irq:ident) => { (TIM9, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim9)] #[cfg(time_driver_tim9)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -141,7 +139,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM12, timer, $block:ident, UP, $irq:ident) => { (TIM12, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim12)] #[cfg(time_driver_tim12)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -149,7 +147,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM15, timer, $block:ident, UP, $irq:ident) => { (TIM15, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim15)] #[cfg(time_driver_tim15)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -157,7 +155,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM20, timer, $block:ident, UP, $irq:ident) => { (TIM20, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim20)] #[cfg(time_driver_tim20)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -173,7 +171,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM21, timer, $block:ident, UP, $irq:ident) => { (TIM21, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim21)] #[cfg(time_driver_tim21)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -181,7 +179,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM22, timer, $block:ident, UP, $irq:ident) => { (TIM22, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim22)] #[cfg(time_driver_tim22)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -189,7 +187,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM23, timer, $block:ident, UP, $irq:ident) => { (TIM23, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim23)] #[cfg(time_driver_tim23)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -197,7 +195,7 @@ foreach_interrupt! {
DRIVER.on_interrupt() DRIVER.on_interrupt()
} }
}; };
(TIM24, timer, $block:ident, UP, $irq:ident) => { (TIM24, timer, $block:ident, CC, $irq:ident) => {
#[cfg(time_driver_tim24)] #[cfg(time_driver_tim24)]
#[cfg(feature = "rt")] #[cfg(feature = "rt")]
#[interrupt] #[interrupt]
@ -263,6 +261,7 @@ pub(crate) struct RtcDriver {
rtc: Mutex<CriticalSectionRawMutex, Cell<Option<&'static Rtc>>>, rtc: Mutex<CriticalSectionRawMutex, Cell<Option<&'static Rtc>>>,
} }
#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NEW: AlarmState = AlarmState::new(); const ALARM_STATE_NEW: AlarmState = AlarmState::new();
embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
@ -307,16 +306,8 @@ impl RtcDriver {
w.set_ccie(0, true); w.set_ccie(0, true);
}); });
<T as CoreInstance>::Interrupt::unpend(); <T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend();
unsafe { <T as CoreInstance>::Interrupt::enable() }; unsafe { <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable() };
#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
{
<T as AdvancedInstance1Channel>::CaptureCompareInterrupt::unpend();
unsafe {
<T as AdvancedInstance1Channel>::CaptureCompareInterrupt::enable();
}
}
r.cr1().modify(|w| w.set_cen(true)); r.cr1().modify(|w| w.set_cen(true));
} }

View file

@ -47,8 +47,8 @@ pub enum TimerBits {
/// Core timer instance. /// Core timer instance.
pub trait CoreInstance: RccPeripheral + 'static { pub trait CoreInstance: RccPeripheral + 'static {
/// Interrupt for this timer. /// Update Interrupt for this timer.
type Interrupt: interrupt::typelevel::Interrupt; type UpdateInterrupt: interrupt::typelevel::Interrupt;
/// Amount of bits this timer has. /// Amount of bits this timer has.
const BITS: TimerBits; const BITS: TimerBits;
@ -64,29 +64,46 @@ pub trait BasicNoCr2Instance: CoreInstance {}
pub trait BasicInstance: BasicNoCr2Instance {} pub trait BasicInstance: BasicNoCr2Instance {}
/// General-purpose 16-bit timer with 1 channel instance. /// General-purpose 16-bit timer with 1 channel instance.
pub trait GeneralInstance1Channel: CoreInstance {} pub trait GeneralInstance1Channel: CoreInstance {
/// Capture compare interrupt for this timer.
type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
}
/// General-purpose 16-bit timer with 2 channels instance. /// General-purpose 16-bit timer with 2 channels instance.
pub trait GeneralInstance2Channel: GeneralInstance1Channel {} pub trait GeneralInstance2Channel: GeneralInstance1Channel {
/// Trigger event interrupt for this timer.
type TriggerInterrupt: interrupt::typelevel::Interrupt;
}
/// General-purpose 16-bit timer with 4 channels instance. // This trait add *extra* methods to GeneralInstance4Channel,
pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel { // that GeneralInstance4Channel doesn't use, but the "AdvancedInstance"s need.
// And it's a private trait, so it's content won't leak to outer namespace.
//
// If you want to add a new method to it, please leave a detail comment to explain it.
trait General4ChBlankSealed {
// SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel
// Advanced timers implement this trait, but the output needs to be // Advanced timers implement this trait, but the output needs to be
// enabled explicitly. // enabled explicitly.
// To support general-purpose and advanced timers, this function is added // To support general-purpose and advanced timers, this function is added
// here defaulting to noop and overwritten for advanced timers. // here defaulting to noop and overwritten for advanced timers.
/// Enable timer outputs. //
// Enable timer outputs.
fn enable_outputs(&self) {} fn enable_outputs(&self) {}
} }
/// General-purpose 16-bit timer with 4 channels instance.
#[allow(private_bounds)]
pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel + General4ChBlankSealed {}
/// General-purpose 32-bit timer with 4 channels instance. /// General-purpose 32-bit timer with 4 channels instance.
pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {} pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
/// Advanced 16-bit timer with 1 channel instance. /// Advanced 16-bit timer with 1 channel instance.
pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel { pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
/// Capture compare interrupt for this timer. /// Communication interrupt for this timer.
type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; type CommunicationInterrupt: interrupt::typelevel::Interrupt;
/// Break input interrupt for this timer.
type BreakInputInterrupt: interrupt::typelevel::Interrupt;
} }
/// Advanced 16-bit timer with 2 channels instance. /// Advanced 16-bit timer with 2 channels instance.
@ -127,7 +144,7 @@ dma_trait!(Ch4Dma, GeneralInstance4Channel);
macro_rules! impl_core_timer { macro_rules! impl_core_timer {
($inst:ident, $bits:expr) => { ($inst:ident, $bits:expr) => {
impl CoreInstance for crate::peripherals::$inst { impl CoreInstance for crate::peripherals::$inst {
type Interrupt = crate::_generated::peripheral_interrupts::$inst::UP; type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
const BITS: TimerBits = $bits; const BITS: TimerBits = $bits;
@ -138,6 +155,49 @@ macro_rules! impl_core_timer {
}; };
} }
#[allow(unused)]
macro_rules! impl_general_1ch {
($inst:ident) => {
impl GeneralInstance1Channel for crate::peripherals::$inst {
type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC;
}
};
}
#[allow(unused)]
macro_rules! impl_general_2ch {
($inst:ident) => {
impl GeneralInstance2Channel for crate::peripherals::$inst {
type TriggerInterrupt = crate::_generated::peripheral_interrupts::$inst::TRG;
}
};
}
#[allow(unused)]
macro_rules! impl_advanced_1ch {
($inst:ident) => {
impl AdvancedInstance1Channel for crate::peripherals::$inst {
type CommunicationInterrupt = crate::_generated::peripheral_interrupts::$inst::COM;
type BreakInputInterrupt = crate::_generated::peripheral_interrupts::$inst::BRK;
}
};
}
// This macro only apply to "AdvancedInstance(s)",
// not "GeneralInstance4Channel" itself.
#[allow(unused)]
macro_rules! impl_general_4ch_blank_sealed {
($inst:ident) => {
impl General4ChBlankSealed for crate::peripherals::$inst {
fn enable_outputs(&self) {
unsafe { crate::pac::timer::Tim1chCmp::from_ptr(Self::regs()) }
.bdtr()
.modify(|w| w.set_moe(true));
}
}
};
}
foreach_interrupt! { foreach_interrupt! {
($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
@ -149,47 +209,52 @@ foreach_interrupt! {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
}; };
($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
}; };
($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
}; };
($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits32); impl_core_timer!($inst, TimerBits::Bits32);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl GeneralInstance32bit4Channel for crate::peripherals::$inst {} impl GeneralInstance32bit4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
}; };
($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {} impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {} impl AdvancedInstance4Channel for crate::peripherals::$inst {}
}; };
@ -198,10 +263,11 @@ foreach_interrupt! {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {} impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {} impl AdvancedInstance4Channel for crate::peripherals::$inst {}
}; };
@ -210,19 +276,12 @@ foreach_interrupt! {
impl_core_timer!($inst, TimerBits::Bits16); impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {}
impl GeneralInstance1Channel for crate::peripherals::$inst {} impl_general_1ch!($inst);
impl GeneralInstance2Channel for crate::peripherals::$inst {} impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::<Self>() }} impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {} impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {} impl AdvancedInstance4Channel for crate::peripherals::$inst {}
}; };
} }
#[cfg(not(stm32l0))]
#[allow(unused)]
fn set_moe<T: GeneralInstance4Channel>() {
unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) }
.bdtr()
.modify(|w| w.set_moe(true));
}