From 952f525af5bfbb800ab4593b77e69b8b13f95b16 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 11 Jun 2021 09:19:02 +0200 Subject: [PATCH] Provide a way for a peripheral to query its clock frequency Currently this looks up the frequency in the global singleton that must be initialized by the per-chip RCC implementation. At present, this is only done for the L0 family of chips. --- embassy-macros/src/chip/stm32.rs | 4 +--- embassy-stm32/src/clock.rs | 4 +++- embassy-stm32/src/rcc/l0/mod.rs | 24 ++++++++++-------------- embassy-stm32/src/rcc/mod.rs | 23 ++++++++++++++--------- embassy-stm32/src/spi/v2.rs | 2 +- stm32-metapac/gen/src/lib.rs | 15 +++++++++++++++ 6 files changed, 44 insertions(+), 28 deletions(-) diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs index 0a3a5abb..9cd0111c 100644 --- a/embassy-macros/src/chip/stm32.rs +++ b/embassy-macros/src/chip/stm32.rs @@ -17,9 +17,7 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream ); let clock = unsafe { make_static(&mut c) }; - // TODO: Is TIM2 always APB1? - let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk }; - clock.start(timer_freq); + clock.start(); 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 39a96402..6c317578 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs @@ -77,12 +77,14 @@ impl Clock { } } - pub fn start(&'static self, timer_freq: Hertz) { + pub fn start(&'static self) { let inner = T::inner(); T::enable(); T::reset(); + let timer_freq = T::frequency(); + // NOTE(unsafe) Critical section to use the unsafe methods critical_section::with(|_| { unsafe { diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index d08c32b1..978d373a 100644 --- a/embassy-stm32/src/rcc/l0/mod.rs +++ b/embassy-stm32/src/rcc/l0/mod.rs @@ -469,35 +469,31 @@ impl RccExt for RCC { } }; - let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre { - APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), + let apb1_freq = match cfgr.apb1_pre { + APBPrescaler::NotDivided => ahb_freq, pre => { let pre: Ppre = pre.into(); let pre: u8 = 1 << (pre.0 - 3); let freq = ahb_freq / pre as u32; - (freq, freq * 2, pre as u8) + freq } }; - let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre { - APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), + let apb2_freq = match cfgr.apb2_pre { + APBPrescaler::NotDivided => ahb_freq, pre => { let pre: Ppre = pre.into(); let pre: u8 = 1 << (pre.0 - 3); let freq = ahb_freq / (1 << (pre as u8 - 3)); - (freq, freq * 2, pre as u8) + freq } }; Clocks { - sys_clk: sys_clk.hz(), - ahb_clk: ahb_freq.hz(), - apb1_clk: apb1_freq.hz(), - apb2_clk: apb2_freq.hz(), - apb1_tim_clk: apb1_tim_freq.hz(), - apb2_tim_clk: apb2_tim_freq.hz(), - apb1_pre, - apb2_pre, + sys: sys_clk.hz(), + ahb: ahb_freq.hz(), + apb1: apb1_freq.hz(), + apb2: apb2_freq.hz(), } } } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 3c5b53b0..132b50b0 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -9,14 +9,10 @@ use core::mem::MaybeUninit; /// The existence of this value indicates that the clock configuration can no longer be changed #[derive(Clone, Copy)] pub struct Clocks { - pub sys_clk: Hertz, - pub ahb_clk: Hertz, - pub apb1_clk: Hertz, - pub apb1_tim_clk: Hertz, - pub apb2_clk: Hertz, - pub apb2_tim_clk: Hertz, - pub apb1_pre: u8, - pub apb2_pre: u8, + pub sys: Hertz, + pub ahb: Hertz, + pub apb1: Hertz, + pub apb2: Hertz, } static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); @@ -50,6 +46,7 @@ cfg_if::cfg_if! { pub(crate) mod sealed { pub trait RccPeripheral { + fn frequency() -> crate::time::Hertz; fn reset(); fn enable(); fn disable(); @@ -59,8 +56,16 @@ pub(crate) mod sealed { pub trait RccPeripheral: sealed::RccPeripheral + 'static {} crate::pac::peripheral_rcc!( - ($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { + ($inst:ident, $clk:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { impl sealed::RccPeripheral for peripherals::$inst { + fn frequency() -> crate::time::Hertz { + critical_section::with(|_| { + unsafe { + let freqs = get_freqs(); + freqs.$clk + } + }) + } fn enable() { critical_section::with(|_| { unsafe { diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index a7ac54cd..4e135e9d 100644 --- a/embassy-stm32/src/spi/v2.rs +++ b/embassy-stm32/src/spi/v2.rs @@ -37,7 +37,6 @@ pub struct Spi<'d, T: Instance> { impl<'d, T: Instance> Spi<'d, T> { pub fn new( - pclk: Hertz, _peri: impl Unborrow + 'd, sck: impl Unborrow>, mosi: impl Unborrow>, @@ -60,6 +59,7 @@ impl<'d, T: Instance> Spi<'d, T> { let mosi = mosi.degrade(); let miso = miso.degrade(); + let pclk = T::frequency(); let br = Self::compute_baud_rate(pclk, freq.into()); unsafe { diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 399840c5..ae01f1e8 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs @@ -287,8 +287,23 @@ pub fn gen(options: Options) { match (en, rst) { (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { + let clock = if clock_prefix == "" { + let re = Regex::new("([A-Z]+\\d*).*").unwrap(); + if !re.is_match(enable_reg) { + panic!( + "unable to derive clock name from register name {}", + enable_reg + ); + } else { + let caps = re.captures(enable_reg).unwrap(); + caps.get(1).unwrap().as_str() + } + } else { + clock_prefix + }; peripheral_rcc_table.push(vec![ name.clone(), + clock.to_ascii_lowercase(), enable_reg.to_ascii_lowercase(), reset_reg.to_ascii_lowercase(), format!("set_{}", enable_field.to_ascii_lowercase()),