diff options
| author | Ulf Lilleengen <[email protected]> | 2021-06-11 09:19:02 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2021-06-14 11:33:11 +0200 |
| commit | 952f525af5bfbb800ab4593b77e69b8b13f95b16 (patch) | |
| tree | ea871dd6729a3cf365d8331a60d46a87a3e32aa4 | |
| parent | 85f172dd93227e637724d37e76bbcd7d886678f9 (diff) | |
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.
| -rw-r--r-- | embassy-macros/src/chip/stm32.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/clock.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l0/mod.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 23 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/v2.rs | 2 | ||||
| -rw-r--r-- | 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 0a3a5abb9..9cd0111c9 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 | |||
| 17 | ); | 17 | ); |
| 18 | let clock = unsafe { make_static(&mut c) }; | 18 | let clock = unsafe { make_static(&mut c) }; |
| 19 | 19 | ||
| 20 | // TODO: Is TIM2 always APB1? | 20 | clock.start(); |
| 21 | let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk }; | ||
| 22 | clock.start(timer_freq); | ||
| 23 | 21 | ||
| 24 | let mut alarm = clock.alarm1(); | 22 | let mut alarm = clock.alarm1(); |
| 25 | unsafe { #embassy_path::time::set_clock(clock) }; | 23 | unsafe { #embassy_path::time::set_clock(clock) }; |
diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs index 39a96402a..6c3175789 100644 --- a/embassy-stm32/src/clock.rs +++ b/embassy-stm32/src/clock.rs | |||
| @@ -77,12 +77,14 @@ impl<T: Instance> Clock<T> { | |||
| 77 | } | 77 | } |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | pub fn start(&'static self, timer_freq: Hertz) { | 80 | pub fn start(&'static self) { |
| 81 | let inner = T::inner(); | 81 | let inner = T::inner(); |
| 82 | 82 | ||
| 83 | T::enable(); | 83 | T::enable(); |
| 84 | T::reset(); | 84 | T::reset(); |
| 85 | 85 | ||
| 86 | let timer_freq = T::frequency(); | ||
| 87 | |||
| 86 | // NOTE(unsafe) Critical section to use the unsafe methods | 88 | // NOTE(unsafe) Critical section to use the unsafe methods |
| 87 | critical_section::with(|_| { | 89 | critical_section::with(|_| { |
| 88 | unsafe { | 90 | unsafe { |
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs index d08c32b17..978d373a2 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 { | |||
| 469 | } | 469 | } |
| 470 | }; | 470 | }; |
| 471 | 471 | ||
| 472 | let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre { | 472 | let apb1_freq = match cfgr.apb1_pre { |
| 473 | APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), | 473 | APBPrescaler::NotDivided => ahb_freq, |
| 474 | pre => { | 474 | pre => { |
| 475 | let pre: Ppre = pre.into(); | 475 | let pre: Ppre = pre.into(); |
| 476 | let pre: u8 = 1 << (pre.0 - 3); | 476 | let pre: u8 = 1 << (pre.0 - 3); |
| 477 | let freq = ahb_freq / pre as u32; | 477 | let freq = ahb_freq / pre as u32; |
| 478 | (freq, freq * 2, pre as u8) | 478 | freq |
| 479 | } | 479 | } |
| 480 | }; | 480 | }; |
| 481 | 481 | ||
| 482 | let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre { | 482 | let apb2_freq = match cfgr.apb2_pre { |
| 483 | APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), | 483 | APBPrescaler::NotDivided => ahb_freq, |
| 484 | pre => { | 484 | pre => { |
| 485 | let pre: Ppre = pre.into(); | 485 | let pre: Ppre = pre.into(); |
| 486 | let pre: u8 = 1 << (pre.0 - 3); | 486 | let pre: u8 = 1 << (pre.0 - 3); |
| 487 | let freq = ahb_freq / (1 << (pre as u8 - 3)); | 487 | let freq = ahb_freq / (1 << (pre as u8 - 3)); |
| 488 | (freq, freq * 2, pre as u8) | 488 | freq |
| 489 | } | 489 | } |
| 490 | }; | 490 | }; |
| 491 | 491 | ||
| 492 | Clocks { | 492 | Clocks { |
| 493 | sys_clk: sys_clk.hz(), | 493 | sys: sys_clk.hz(), |
| 494 | ahb_clk: ahb_freq.hz(), | 494 | ahb: ahb_freq.hz(), |
| 495 | apb1_clk: apb1_freq.hz(), | 495 | apb1: apb1_freq.hz(), |
| 496 | apb2_clk: apb2_freq.hz(), | 496 | apb2: apb2_freq.hz(), |
| 497 | apb1_tim_clk: apb1_tim_freq.hz(), | ||
| 498 | apb2_tim_clk: apb2_tim_freq.hz(), | ||
| 499 | apb1_pre, | ||
| 500 | apb2_pre, | ||
| 501 | } | 497 | } |
| 502 | } | 498 | } |
| 503 | } | 499 | } |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 3c5b53b05..132b50b02 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -9,14 +9,10 @@ use core::mem::MaybeUninit; | |||
| 9 | /// The existence of this value indicates that the clock configuration can no longer be changed | 9 | /// The existence of this value indicates that the clock configuration can no longer be changed |
| 10 | #[derive(Clone, Copy)] | 10 | #[derive(Clone, Copy)] |
| 11 | pub struct Clocks { | 11 | pub struct Clocks { |
| 12 | pub sys_clk: Hertz, | 12 | pub sys: Hertz, |
| 13 | pub ahb_clk: Hertz, | 13 | pub ahb: Hertz, |
| 14 | pub apb1_clk: Hertz, | 14 | pub apb1: Hertz, |
| 15 | pub apb1_tim_clk: Hertz, | 15 | pub apb2: Hertz, |
| 16 | pub apb2_clk: Hertz, | ||
| 17 | pub apb2_tim_clk: Hertz, | ||
| 18 | pub apb1_pre: u8, | ||
| 19 | pub apb2_pre: u8, | ||
| 20 | } | 16 | } |
| 21 | 17 | ||
| 22 | static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); | 18 | static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); |
| @@ -50,6 +46,7 @@ cfg_if::cfg_if! { | |||
| 50 | 46 | ||
| 51 | pub(crate) mod sealed { | 47 | pub(crate) mod sealed { |
| 52 | pub trait RccPeripheral { | 48 | pub trait RccPeripheral { |
| 49 | fn frequency() -> crate::time::Hertz; | ||
| 53 | fn reset(); | 50 | fn reset(); |
| 54 | fn enable(); | 51 | fn enable(); |
| 55 | fn disable(); | 52 | fn disable(); |
| @@ -59,8 +56,16 @@ pub(crate) mod sealed { | |||
| 59 | pub trait RccPeripheral: sealed::RccPeripheral + 'static {} | 56 | pub trait RccPeripheral: sealed::RccPeripheral + 'static {} |
| 60 | 57 | ||
| 61 | crate::pac::peripheral_rcc!( | 58 | crate::pac::peripheral_rcc!( |
| 62 | ($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { | 59 | ($inst:ident, $clk:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { |
| 63 | impl sealed::RccPeripheral for peripherals::$inst { | 60 | impl sealed::RccPeripheral for peripherals::$inst { |
| 61 | fn frequency() -> crate::time::Hertz { | ||
| 62 | critical_section::with(|_| { | ||
| 63 | unsafe { | ||
| 64 | let freqs = get_freqs(); | ||
| 65 | freqs.$clk | ||
| 66 | } | ||
| 67 | }) | ||
| 68 | } | ||
| 64 | fn enable() { | 69 | fn enable() { |
| 65 | critical_section::with(|_| { | 70 | critical_section::with(|_| { |
| 66 | unsafe { | 71 | unsafe { |
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs index a7ac54cdd..4e135e9df 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> { | |||
| 37 | 37 | ||
| 38 | impl<'d, T: Instance> Spi<'d, T> { | 38 | impl<'d, T: Instance> Spi<'d, T> { |
| 39 | pub fn new<F>( | 39 | pub fn new<F>( |
| 40 | pclk: Hertz, | ||
| 41 | _peri: impl Unborrow<Target = T> + 'd, | 40 | _peri: impl Unborrow<Target = T> + 'd, |
| 42 | sck: impl Unborrow<Target = impl SckPin<T>>, | 41 | sck: impl Unborrow<Target = impl SckPin<T>>, |
| 43 | mosi: impl Unborrow<Target = impl MosiPin<T>>, | 42 | mosi: impl Unborrow<Target = impl MosiPin<T>>, |
| @@ -60,6 +59,7 @@ impl<'d, T: Instance> Spi<'d, T> { | |||
| 60 | let mosi = mosi.degrade(); | 59 | let mosi = mosi.degrade(); |
| 61 | let miso = miso.degrade(); | 60 | let miso = miso.degrade(); |
| 62 | 61 | ||
| 62 | let pclk = T::frequency(); | ||
| 63 | let br = Self::compute_baud_rate(pclk, freq.into()); | 63 | let br = Self::compute_baud_rate(pclk, freq.into()); |
| 64 | 64 | ||
| 65 | unsafe { | 65 | unsafe { |
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 399840c5b..ae01f1e85 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs | |||
| @@ -287,8 +287,23 @@ pub fn gen(options: Options) { | |||
| 287 | 287 | ||
| 288 | match (en, rst) { | 288 | match (en, rst) { |
| 289 | (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { | 289 | (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { |
| 290 | let clock = if clock_prefix == "" { | ||
| 291 | let re = Regex::new("([A-Z]+\\d*).*").unwrap(); | ||
| 292 | if !re.is_match(enable_reg) { | ||
| 293 | panic!( | ||
| 294 | "unable to derive clock name from register name {}", | ||
| 295 | enable_reg | ||
| 296 | ); | ||
| 297 | } else { | ||
| 298 | let caps = re.captures(enable_reg).unwrap(); | ||
| 299 | caps.get(1).unwrap().as_str() | ||
| 300 | } | ||
| 301 | } else { | ||
| 302 | clock_prefix | ||
| 303 | }; | ||
| 290 | peripheral_rcc_table.push(vec