aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/build.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 6c364f7bb..2b66e7dad 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -308,6 +308,9 @@ fn main() {
308 // ======== 308 // ========
309 // Generate RccPeripheral impls 309 // Generate RccPeripheral impls
310 310
311 let refcounted_peripherals = HashSet::from(["ADC", "USART", "SPI", "I2C"]);
312 let mut refcount_statics = HashSet::new();
313
311 for p in METADATA.peripherals { 314 for p in METADATA.peripherals {
312 // generating RccPeripheral impl for H7 ADC3 would result in bad frequency 315 // generating RccPeripheral impl for H7 ADC3 would result in bad frequency
313 if !singletons.contains(&p.name.to_string()) 316 if !singletons.contains(&p.name.to_string())
@@ -344,11 +347,40 @@ fn main() {
344 TokenStream::new() 347 TokenStream::new()
345 }; 348 };
346 349
350 let ptype = p
351 .name
352 .replace(&['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'][..], "");
347 let pname = format_ident!("{}", p.name); 353 let pname = format_ident!("{}", p.name);
348 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); 354 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
349 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); 355 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
350 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); 356 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
351 357
358 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype.trim_start_matches("LP")) {
359 let refcount_static =
360 format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());
361
362 refcount_statics.insert(refcount_static.clone());
363
364 (
365 quote! {
366 use atomic_polyfill::Ordering;
367
368 if refcount_statics::#refcount_static.fetch_add(1, Ordering::SeqCst) > 0 {
369 return;
370 }
371 },
372 quote! {
373 use atomic_polyfill::Ordering;
374
375 if refcount_statics::#refcount_static.fetch_sub(1, Ordering::SeqCst) > 1 {
376 return;
377 }
378 },
379 )
380 } else {
381 (TokenStream::new(), TokenStream::new())
382 };
383
352 g.extend(quote! { 384 g.extend(quote! {
353 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { 385 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
354 fn frequency() -> crate::time::Hertz { 386 fn frequency() -> crate::time::Hertz {
@@ -356,6 +388,7 @@ fn main() {
356 } 388 }
357 fn enable() { 389 fn enable() {
358 critical_section::with(|_| { 390 critical_section::with(|_| {
391 #before_enable
359 #[cfg(feature = "low-power")] 392 #[cfg(feature = "low-power")]
360 crate::rcc::clock_refcount_add(); 393 crate::rcc::clock_refcount_add();
361 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); 394 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
@@ -364,6 +397,7 @@ fn main() {
364 } 397 }
365 fn disable() { 398 fn disable() {
366 critical_section::with(|_| { 399 critical_section::with(|_| {
400 #before_disable
367 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); 401 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
368 #[cfg(feature = "low-power")] 402 #[cfg(feature = "low-power")]
369 crate::rcc::clock_refcount_sub(); 403 crate::rcc::clock_refcount_sub();
@@ -379,6 +413,21 @@ fn main() {
379 } 413 }
380 } 414 }
381 415
416 let mut refcount_mod = TokenStream::new();
417 for refcount_static in refcount_statics {
418 refcount_mod.extend(quote! {
419 pub(crate) static #refcount_static: AtomicU8 = AtomicU8::new(0);
420 });
421 }
422
423 g.extend(quote! {
424 mod refcount_statics {
425 use atomic_polyfill::AtomicU8;
426
427 #refcount_mod
428 }
429 });
430
382 // ======== 431 // ========
383 // Generate fns to enable GPIO, DMA in RCC 432 // Generate fns to enable GPIO, DMA in RCC
384 433