diff options
| author | Harry Brooke <[email protected]> | 2024-03-09 18:24:31 +0000 |
|---|---|---|
| committer | Harry Brooke <[email protected]> | 2024-03-09 18:24:31 +0000 |
| commit | 2d7ec281e8843575b56982e8e2bc2159c6386111 (patch) | |
| tree | 85053bba04da2da318a159037601b96bdd13d4bd | |
| parent | 1b4d3e1e295a2325d9ceec8957db365f3155bf12 (diff) | |
stm32/rcc: wait for peripheral clock to be active. also, hold the peripheral reset while enabling the clock.
| -rw-r--r-- | embassy-stm32/build.rs | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 84e8be25d..ce8283540 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -509,25 +509,20 @@ fn main() { | |||
| 509 | if let Some(rcc) = &p.rcc { | 509 | if let Some(rcc) = &p.rcc { |
| 510 | let en = rcc.enable.as_ref().unwrap(); | 510 | let en = rcc.enable.as_ref().unwrap(); |
| 511 | 511 | ||
| 512 | let rst = match &rcc.reset { | 512 | let (start_rst, end_rst) = match &rcc.reset { |
| 513 | Some(rst) => { | 513 | Some(rst) => { |
| 514 | let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); | 514 | let rst_reg = format_ident!("{}", rst.register.to_ascii_lowercase()); |
| 515 | let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); | 515 | let set_rst_field = format_ident!("set_{}", rst.field.to_ascii_lowercase()); |
| 516 | quote! { | 516 | ( |
| 517 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); | 517 | quote! { |
| 518 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); | 518 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(true)); |
| 519 | } | 519 | }, |
| 520 | } | 520 | quote! { |
| 521 | None => TokenStream::new(), | 521 | crate::pac::RCC.#rst_reg().modify(|w| w.#set_rst_field(false)); |
| 522 | }; | 522 | }, |
| 523 | 523 | ) | |
| 524 | let after_enable = if chip_name.starts_with("stm32f2") { | ||
| 525 | // Errata: ES0005 - 2.1.11 Delay after an RCC peripheral clock enabling | ||
| 526 | quote! { | ||
| 527 | cortex_m::asm::dsb(); | ||
| 528 | } | 524 | } |
| 529 | } else { | 525 | None => (TokenStream::new(), TokenStream::new()), |
| 530 | TokenStream::new() | ||
| 531 | }; | 526 | }; |
| 532 | 527 | ||
| 533 | let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" }; | 528 | let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" }; |
| @@ -596,9 +591,26 @@ fn main() { | |||
| 596 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { | 591 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { |
| 597 | #before_enable | 592 | #before_enable |
| 598 | #incr_stop_refcount | 593 | #incr_stop_refcount |
| 594 | |||
| 595 | #start_rst | ||
| 596 | |||
| 599 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 597 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| 600 | #after_enable | 598 | // dummy read to ensure write is completed |
| 601 | #rst | 599 | let _ = crate::pac::RCC.#en_reg().read(); |
| 600 | |||
| 601 | // wait two peripheral clock cycles before the clock is active | ||
| 602 | // accomplish this with two dummy reads from the peripheral. this shouldn't | ||
| 603 | // cause any side effects since the peripheral is in reset | ||
| 604 | unsafe { | ||
| 605 | //apparently volatile accesses to ZST like () can be optimized out. lol | ||
| 606 | let ptr = crate::pac::#pname.as_ptr() as *const usize; | ||
| 607 | let _ = ::core::ptr::read_volatile(ptr); | ||
| 608 | let _ = ::core::ptr::read_volatile(ptr); | ||
| 609 | // wait for memory accesses to finish | ||
| 610 | ::core::arch::asm!("dmb"); | ||
| 611 | } | ||
| 612 | |||
| 613 | #end_rst | ||
| 602 | } | 614 | } |
| 603 | fn disable_with_cs(_cs: critical_section::CriticalSection) { | 615 | fn disable_with_cs(_cs: critical_section::CriticalSection) { |
| 604 | #before_disable | 616 | #before_disable |
