aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2021-06-10 09:31:41 +0200
committerUlf Lilleengen <[email protected]>2021-06-10 09:37:30 +0200
commit0a9022d59f412f8ecade98da273126d834006841 (patch)
tree7235b9e0f50c2061fcc4cfc926c24aee4db24727
parent37fbc5fcc453a7a544703ff4dd69e7ebc38ed993 (diff)
Enable timer clock in RCC on timer start
* Moves the tim2-specific code into macro which always uses TIM2 * For peripherals without clock specified, attempt to locate enable and reset registers in the RCC block matching the peripheral name. This could be useful for peripherals where deducing the clock name might not be feasible, but it remains to be tested with more chip families to see if it is sufficiently accurate.
-rw-r--r--embassy-macros/src/chip/stm32.rs5
-rw-r--r--embassy-stm32/src/clock.rs24
-rw-r--r--stm32-metapac/gen/src/lib.rs62
3 files changed, 45 insertions, 46 deletions
diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs
index 274560a03..0a3a5abb9 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
16 interrupt::take!(TIM2), 16 interrupt::take!(TIM2),
17 ); 17 );
18 let clock = unsafe { make_static(&mut c) }; 18 let clock = unsafe { make_static(&mut c) };
19 clock.start_tim2(); 19
20 // TODO: Is TIM2 always APB1?
21 let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk };
22 clock.start(timer_freq);
20 23
21 let mut alarm = clock.alarm1(); 24 let mut alarm = clock.alarm1();
22 unsafe { #embassy_path::time::set_clock(clock) }; 25 unsafe { #embassy_path::time::set_clock(clock) };
diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs
index 7f478e790..39a96402a 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};
11use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 11use crate::interrupt::{CriticalSection, Interrupt, Mutex};
12use crate::pac::timer::TimGp16; 12use crate::pac::timer::TimGp16;
13use crate::peripherals; 13use crate::peripherals;
14use crate::rcc::RccPeripheral;
14use crate::time::Hertz; 15use crate::time::Hertz;
15 16
16// Clock timekeeping works with something we call "periods", which are time intervals 17// Clock timekeeping works with something we call "periods", which are time intervals
@@ -76,27 +77,12 @@ impl<T: Instance> Clock<T> {
76 } 77 }
77 } 78 }
78 79
79 // TODO: Temporary until clock code generation is in place
80 pub fn start_tim2(&'static self) {
81 cfg_if::cfg_if! {
82 if #[cfg(rcc_l0)] {
83 unsafe {
84 let rcc = crate::pac::RCC;
85 rcc.apb1enr()
86 .modify(|w| w.set_tim2en(true));
87 rcc.apb1rstr().modify(|w| w.set_tim2rst(true));
88 rcc.apb1rstr().modify(|w| w.set_tim2rst(false));
89 }
90
91 let timer_freq = unsafe { crate::rcc::get_freqs().apb1_clk };
92 self.start(timer_freq);
93 }
94 }
95 }
96
97 pub fn start(&'static self, timer_freq: Hertz) { 80 pub fn start(&'static self, timer_freq: Hertz) {
98 let inner = T::inner(); 81 let inner = T::inner();
99 82
83 T::enable();
84 T::reset();
85
100 // NOTE(unsafe) Critical section to use the unsafe methods 86 // NOTE(unsafe) Critical section to use the unsafe methods
101 critical_section::with(|_| { 87 critical_section::with(|_| {
102 unsafe { 88 unsafe {
@@ -359,7 +345,7 @@ pub(crate) mod sealed {
359 } 345 }
360} 346}
361 347
362pub trait Instance: sealed::Instance + Sized + 'static {} 348pub trait Instance: sealed::Instance + Sized + RccPeripheral + 'static {}
363 349
364macro_rules! impl_timer { 350macro_rules! impl_timer {
365 ($inst:ident) => { 351 ($inst:ident) => {
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs
index c4090ccaf..6db950be3 100644
--- a/stm32-metapac/gen/src/lib.rs
+++ b/stm32-metapac/gen/src/lib.rs
@@ -267,32 +267,42 @@ pub fn gen(options: Options) {
267 _ => {} 267 _ => {}
268 } 268 }
269 269
270 if let Some(clock) = &p.clock { 270 if let Some(rcc) = &rcc {
271 if let Some(rcc) = &rcc { 271 // Workaround for clock registers being split on some chip families. Assume fields are
272 // Workaround for clock registers being split on some chip families. Assume fields are 272 // named after peripheral and look for first field matching and use that register.
273 // named after peripheral and look for first field matching and use that register. 273 //
274 let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); 274 // Not all peripherals have the clock hint due to insufficient information from
275 let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); 275 // chip definition. If clock is not specified, the first matching register with the
276 276 // expected field will be used.
277 match (en, rst) { 277 let en = find_reg_for_field(
278 (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { 278 &rcc,
279 peripheral_rcc_table.push(vec![ 279 p.clock.as_ref().unwrap_or(&String::new()),
280 name.clone(), 280 &format!("{}EN", name),
281 enable_reg.to_ascii_lowercase(), 281 );
282 reset_reg.to_ascii_lowercase(), 282 let rst = find_reg_for_field(
283 format!("set_{}", enable_field.to_ascii_lowercase()), 283 &rcc,
284 format!("set_{}", reset_field.to_ascii_lowercase()), 284 p.clock.as_ref().unwrap_or(&String::new()),
285 ]); 285 &format!("{}RST", name),
286 } 286 );
287 (None, Some(_)) => { 287
288 println!("Unable to find enable register for {}", name) 288 match (en, rst) {
289 } 289 (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => {
290 (Some(_), None) => { 290 peripheral_rcc_table.push(vec![
291 println!("Unable to find reset register for {}", name) 291 name.clone(),
292 } 292 enable_reg.to_ascii_lowercase(),
293 (None, None) => { 293 reset_reg.to_ascii_lowercase(),
294 println!("Unable to find enable and reset register for {}", name) 294 format!("set_{}", enable_field.to_ascii_lowercase()),
295 } 295 format!("set_{}", reset_field.to_ascii_lowercase()),
296 ]);
297 }
298 (None, Some(_)) => {
299 println!("Unable to find enable register for {}", name)
300 }
301 (Some(_), None) => {
302 println!("Unable to find reset register for {}", name)
303 }
304 (None, None) => {
305 println!("Unable to find enable and reset register for {}", name)
296 } 306 }
297 } 307 }
298 } 308 }