diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs index 274560a0..0a3a5abb 100644 --- a/embassy-macros/src/chip/stm32.rs +++ b/embassy-macros/src/chip/stm32.rs @@ -16,7 +16,10 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream interrupt::take!(TIM2), ); let clock = unsafe { make_static(&mut c) }; - clock.start_tim2(); + + // TODO: Is TIM2 always APB1? + let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk }; + clock.start(timer_freq); let mut alarm = clock.alarm1(); unsafe { #embassy_path::time::set_clock(clock) }; diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs index 7f478e79..39a96402 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs @@ -11,6 +11,7 @@ use embassy::time::{Clock as EmbassyClock, TICKS_PER_SECOND}; use crate::interrupt::{CriticalSection, Interrupt, Mutex}; use crate::pac::timer::TimGp16; use crate::peripherals; +use crate::rcc::RccPeripheral; use crate::time::Hertz; // Clock timekeeping works with something we call "periods", which are time intervals @@ -76,27 +77,12 @@ impl Clock { } } - // TODO: Temporary until clock code generation is in place - pub fn start_tim2(&'static self) { - cfg_if::cfg_if! { - if #[cfg(rcc_l0)] { - unsafe { - let rcc = crate::pac::RCC; - rcc.apb1enr() - .modify(|w| w.set_tim2en(true)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(true)); - rcc.apb1rstr().modify(|w| w.set_tim2rst(false)); - } - - let timer_freq = unsafe { crate::rcc::get_freqs().apb1_clk }; - self.start(timer_freq); - } - } - } - pub fn start(&'static self, timer_freq: Hertz) { let inner = T::inner(); + T::enable(); + T::reset(); + // NOTE(unsafe) Critical section to use the unsafe methods critical_section::with(|_| { unsafe { @@ -359,7 +345,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + Sized + 'static {} +pub trait Instance: sealed::Instance + Sized + RccPeripheral + 'static {} macro_rules! impl_timer { ($inst:ident) => { diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index c4090cca..6db950be 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -267,32 +267,42 @@ pub fn gen(options: Options) { _ => {} } - if let Some(clock) = &p.clock { - if let Some(rcc) = &rcc { - // Workaround for clock registers being split on some chip families. Assume fields are - // named after peripheral and look for first field matching and use that register. - let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); - let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); + if let Some(rcc) = &rcc { + // Workaround for clock registers being split on some chip families. Assume fields are + // named after peripheral and look for first field matching and use that register. + // + // Not all peripherals have the clock hint due to insufficient information from + // chip definition. If clock is not specified, the first matching register with the + // expected field will be used. + let en = find_reg_for_field( + &rcc, + p.clock.as_ref().unwrap_or(&String::new()), + &format!("{}EN", name), + ); + let rst = find_reg_for_field( + &rcc, + p.clock.as_ref().unwrap_or(&String::new()), + &format!("{}RST", name), + ); - match (en, rst) { - (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { - peripheral_rcc_table.push(vec![ - name.clone(), - enable_reg.to_ascii_lowercase(), - reset_reg.to_ascii_lowercase(), - format!("set_{}", enable_field.to_ascii_lowercase()), - format!("set_{}", reset_field.to_ascii_lowercase()), - ]); - } - (None, Some(_)) => { - println!("Unable to find enable register for {}", name) - } - (Some(_), None) => { - println!("Unable to find reset register for {}", name) - } - (None, None) => { - println!("Unable to find enable and reset register for {}", name) - } + match (en, rst) { + (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { + peripheral_rcc_table.push(vec![ + name.clone(), + enable_reg.to_ascii_lowercase(), + reset_reg.to_ascii_lowercase(), + format!("set_{}", enable_field.to_ascii_lowercase()), + format!("set_{}", reset_field.to_ascii_lowercase()), + ]); + } + (None, Some(_)) => { + println!("Unable to find enable register for {}", name) + } + (Some(_), None) => { + println!("Unable to find reset register for {}", name) + } + (None, None) => { + println!("Unable to find enable and reset register for {}", name) } } }