aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2021-06-11 09:19:02 +0200
committerUlf Lilleengen <[email protected]>2021-06-14 11:33:11 +0200
commit952f525af5bfbb800ab4593b77e69b8b13f95b16 (patch)
treeea871dd6729a3cf365d8331a60d46a87a3e32aa4
parent85f172dd93227e637724d37e76bbcd7d886678f9 (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.rs4
-rw-r--r--embassy-stm32/src/clock.rs4
-rw-r--r--embassy-stm32/src/rcc/l0/mod.rs24
-rw-r--r--embassy-stm32/src/rcc/mod.rs23
-rw-r--r--embassy-stm32/src/spi/v2.rs2
-rw-r--r--stm32-metapac/gen/src/lib.rs15
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)]
11pub struct Clocks { 11pub 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
22static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); 18static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
@@ -50,6 +46,7 @@ cfg_if::cfg_if! {
50 46
51pub(crate) mod sealed { 47pub(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 {
59pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 56pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
60 57
61crate::pac::peripheral_rcc!( 58crate::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
38impl<'d, T: Instance> Spi<'d, T> { 38impl<'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![ 304 peripheral_rcc_table.push(vec![
291 name.clone(), 305 name.clone(),
306 clock.to_ascii_lowercase(),
292 enable_reg.to_ascii_lowercase(), 307 enable_reg.to_ascii_lowercase(),
293 reset_reg.to_ascii_lowercase(), 308 reset_reg.to_ascii_lowercase(),
294 format!("set_{}", enable_field.to_ascii_lowercase()), 309 format!("set_{}", enable_field.to_ascii_lowercase()),