diff options
| author | xoviat <[email protected]> | 2023-10-12 02:01:27 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-12 02:01:27 +0000 |
| commit | eb368f77a46682f76dcc4d75f9ba4ce80dfb4193 (patch) | |
| tree | 28e7e476b0a620142c538c469f88f55c775538d1 | |
| parent | ac84631a2aa0243b8e7dccbe8af324f3f5cd19e0 (diff) | |
| parent | 57ccc1051a2790073f3963a8ab079bc072d0014f (diff) | |
Merge pull request #2023 from xoviat/rcc-mux
stm32: add rcc mux for h5
| -rw-r--r-- | embassy-stm32/build.rs | 115 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/h.rs | 51 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 46 |
3 files changed, 202 insertions, 10 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index fa10b7f77..5b6b22ea1 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -5,7 +5,8 @@ use std::{env, fs}; | |||
| 5 | 5 | ||
| 6 | use proc_macro2::{Ident, TokenStream}; | 6 | use proc_macro2::{Ident, TokenStream}; |
| 7 | use quote::{format_ident, quote}; | 7 | use quote::{format_ident, quote}; |
| 8 | use stm32_metapac::metadata::{MemoryRegionKind, METADATA}; | 8 | use stm32_metapac::metadata::ir::{BlockItemInner, Enum}; |
| 9 | use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA}; | ||
| 9 | 10 | ||
| 10 | fn main() { | 11 | fn main() { |
| 11 | let target = env::var("TARGET").unwrap(); | 12 | let target = env::var("TARGET").unwrap(); |
| @@ -388,6 +389,51 @@ fn main() { | |||
| 388 | } | 389 | } |
| 389 | 390 | ||
| 390 | // ======== | 391 | // ======== |
| 392 | // Generate rcc fieldset and enum maps | ||
| 393 | let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = { | ||
| 394 | let rcc_registers = METADATA | ||
| 395 | .peripherals | ||
| 396 | .iter() | ||
| 397 | .filter_map(|p| p.registers.as_ref()) | ||
| 398 | .find(|r| r.kind == "rcc") | ||
| 399 | .unwrap() | ||
| 400 | .ir; | ||
| 401 | |||
| 402 | let rcc_blocks = rcc_registers.blocks.iter().find(|b| b.name == "Rcc").unwrap().items; | ||
| 403 | |||
| 404 | let rcc_block_item_map: HashMap<&str, &str> = rcc_blocks | ||
| 405 | .iter() | ||
| 406 | .filter_map(|b| match &b.inner { | ||
| 407 | BlockItemInner::Register(register) => register.fieldset.map(|f| (f, b.name)), | ||
| 408 | _ => None, | ||
| 409 | }) | ||
| 410 | .collect(); | ||
| 411 | |||
| 412 | let rcc_enum_map: HashMap<&str, &Enum> = rcc_registers.enums.iter().map(|e| (e.name, e)).collect(); | ||
| 413 | |||
| 414 | rcc_registers | ||
| 415 | .fieldsets | ||
| 416 | .iter() | ||
| 417 | .filter_map(|f| { | ||
| 418 | rcc_block_item_map.get(f.name).map(|b| { | ||
| 419 | ( | ||
| 420 | *b, | ||
| 421 | f.fields | ||
| 422 | .iter() | ||
| 423 | .filter_map(|f| { | ||
| 424 | let enumm = f.enumm?; | ||
| 425 | let enumm = rcc_enum_map.get(enumm)?; | ||
| 426 | |||
| 427 | Some((f.name, *enumm)) | ||
| 428 | }) | ||
| 429 | .collect(), | ||
| 430 | ) | ||
| 431 | }) | ||
| 432 | }) | ||
| 433 | .collect() | ||
| 434 | }; | ||
| 435 | |||
| 436 | // ======== | ||
| 391 | // Generate RccPeripheral impls | 437 | // Generate RccPeripheral impls |
| 392 | 438 | ||
| 393 | let refcounted_peripherals = HashSet::from(["usart", "adc"]); | 439 | let refcounted_peripherals = HashSet::from(["usart", "adc"]); |
| @@ -454,10 +500,61 @@ fn main() { | |||
| 454 | (TokenStream::new(), TokenStream::new()) | 500 | (TokenStream::new(), TokenStream::new()) |
| 455 | }; | 501 | }; |
| 456 | 502 | ||
| 503 | let mux_for = |mux: Option<&'static PeripheralRccRegister>| { | ||
| 504 | // temporary hack to restrict the scope of the implementation to h5 | ||
| 505 | if !&chip_name.starts_with("stm32h5") { | ||
| 506 | return None; | ||
| 507 | } | ||
| 508 | |||
| 509 | let mux = mux?; | ||
| 510 | let fieldset = rcc_enum_map.get(mux.register)?; | ||
| 511 | let enumm = fieldset.get(mux.field)?; | ||
| 512 | |||
| 513 | Some((mux, *enumm)) | ||
| 514 | }; | ||
| 515 | |||
| 516 | let clock_frequency = match mux_for(rcc.mux.as_ref()) { | ||
| 517 | Some((mux, rcc_enumm)) => { | ||
| 518 | let fieldset_name = format_ident!("{}", mux.register); | ||
| 519 | let field_name = format_ident!("{}", mux.field); | ||
| 520 | let enum_name = format_ident!("{}", rcc_enumm.name); | ||
| 521 | |||
| 522 | let match_arms: TokenStream = rcc_enumm | ||
| 523 | .variants | ||
| 524 | .iter() | ||
| 525 | .filter(|v| v.name != "DISABLE") | ||
| 526 | .map(|v| { | ||
| 527 | let variant_name = format_ident!("{}", v.name); | ||
| 528 | |||
| 529 | // temporary hack to restrict the scope of the implementation until clock names can be stabilized | ||
| 530 | let clock_name = format_ident!("mux_{}", v.name.to_ascii_lowercase()); | ||
| 531 | |||
| 532 | quote! { | ||
| 533 | #enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() }, | ||
| 534 | } | ||
| 535 | }) | ||
| 536 | .collect(); | ||
| 537 | |||
| 538 | quote! { | ||
| 539 | use crate::pac::rcc::vals::#enum_name; | ||
| 540 | |||
| 541 | #[allow(unreachable_patterns)] | ||
| 542 | match crate::pac::RCC.#fieldset_name().read().#field_name() { | ||
| 543 | #match_arms | ||
| 544 | |||
| 545 | _ => unreachable!(), | ||
| 546 | } | ||
| 547 | } | ||
| 548 | } | ||
| 549 | None => quote! { | ||
| 550 | unsafe { crate::rcc::get_freqs().#clk } | ||
| 551 | }, | ||
| 552 | }; | ||
| 553 | |||
| 457 | g.extend(quote! { | 554 | g.extend(quote! { |
| 458 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { | 555 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { |
| 459 | fn frequency() -> crate::time::Hertz { | 556 | fn frequency() -> crate::time::Hertz { |
| 460 | unsafe { crate::rcc::get_freqs().#clk } | 557 | #clock_frequency |
| 461 | } | 558 | } |
| 462 | fn enable() { | 559 | fn enable() { |
| 463 | critical_section::with(|_cs| { | 560 | critical_section::with(|_cs| { |
| @@ -486,12 +583,14 @@ fn main() { | |||
| 486 | } | 583 | } |
| 487 | } | 584 | } |
| 488 | 585 | ||
| 489 | let mut refcount_mod = TokenStream::new(); | 586 | let refcount_mod: TokenStream = refcount_statics |
| 490 | for refcount_static in refcount_statics { | 587 | .iter() |
| 491 | refcount_mod.extend(quote! { | 588 | .map(|refcount_static| { |
| 492 | pub(crate) static mut #refcount_static: u8 = 0; | 589 | quote! { |
| 493 | }); | 590 | pub(crate) static mut #refcount_static: u8 = 0; |
| 494 | } | 591 | } |
| 592 | }) | ||
| 593 | .collect(); | ||
| 495 | 594 | ||
| 496 | g.extend(quote! { | 595 | g.extend(quote! { |
| 497 | mod refcount_statics { | 596 | mod refcount_statics { |
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 7236d82ff..d37dd45d4 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs | |||
| @@ -388,7 +388,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 388 | let pll1 = init_pll(0, config.pll1, &pll_input); | 388 | let pll1 = init_pll(0, config.pll1, &pll_input); |
| 389 | let pll2 = init_pll(1, config.pll2, &pll_input); | 389 | let pll2 = init_pll(1, config.pll2, &pll_input); |
| 390 | #[cfg(any(rcc_h5, stm32h7))] | 390 | #[cfg(any(rcc_h5, stm32h7))] |
| 391 | let _pll3 = init_pll(2, config.pll3, &pll_input); | 391 | let pll3 = init_pll(2, config.pll3, &pll_input); |
| 392 | 392 | ||
| 393 | // Configure sysclk | 393 | // Configure sysclk |
| 394 | let (sys, sw) = match config.sys { | 394 | let (sys, sw) = match config.sys { |
| @@ -447,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 447 | #[cfg(stm32h7)] | 447 | #[cfg(stm32h7)] |
| 448 | let adc = match config.adc_clock_source { | 448 | let adc = match config.adc_clock_source { |
| 449 | AdcClockSource::PLL2_P => pll2.p, | 449 | AdcClockSource::PLL2_P => pll2.p, |
| 450 | AdcClockSource::PLL3_R => _pll3.r, | 450 | AdcClockSource::PLL3_R => pll3.r, |
| 451 | AdcClockSource::PER => _per_ck, | 451 | AdcClockSource::PER => _per_ck, |
| 452 | _ => unreachable!(), | 452 | _ => unreachable!(), |
| 453 | }; | 453 | }; |
| @@ -545,6 +545,53 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 545 | apb2_tim, | 545 | apb2_tim, |
| 546 | adc, | 546 | adc, |
| 547 | rtc, | 547 | rtc, |
| 548 | |||
| 549 | #[cfg(stm32h5)] | ||
| 550 | mux_rcc_pclk1: Some(apb1), | ||
| 551 | #[cfg(stm32h5)] | ||
| 552 | mux_pll2_q: None, | ||
| 553 | #[cfg(stm32h5)] | ||
| 554 | mux_pll3_q: None, | ||
| 555 | #[cfg(stm32h5)] | ||
| 556 | mux_hsi_ker: None, | ||
| 557 | #[cfg(stm32h5)] | ||
| 558 | mux_csi_ker: None, | ||
| 559 | #[cfg(stm32h5)] | ||
| 560 | mux_lse: None, | ||
| 561 | #[cfg(stm32h5)] | ||
| 562 | mux_pll1_q: pll1.q, | ||
| 563 | #[cfg(stm32h5)] | ||
| 564 | mux_pll2_p: pll2.p, | ||
| 565 | #[cfg(rcc_h5)] | ||
| 566 | mux_pll3_p: pll3.p, | ||
| 567 | #[cfg(stm32h5)] | ||
| 568 | mux_audioclk: None, | ||
| 569 | #[cfg(stm32h5)] | ||
| 570 | mux_per: None, | ||
| 571 | |||
| 572 | #[cfg(rcc_h5)] | ||
| 573 | mux_pll3_r: pll3.r, | ||
| 574 | #[cfg(all(not(rcc_h5), stm32h5))] | ||
| 575 | mux_pll3_r: None, | ||
| 576 | #[cfg(stm32h5)] | ||
| 577 | mux_rcc_pclk3: Some(apb3), | ||
| 578 | #[cfg(stm32h5)] | ||
| 579 | mux_pll3_1: None, | ||
| 580 | #[cfg(stm32h5)] | ||
| 581 | mux_hsi48_ker: None, | ||
| 582 | #[cfg(stm32h5)] | ||
| 583 | mux_lsi_ker: None, | ||
| 584 | #[cfg(stm32h5)] | ||
| 585 | mux_pll2_r: pll2.r, | ||
| 586 | #[cfg(stm32h5)] | ||
| 587 | mux_rcc_pclk2: Some(apb2), | ||
| 588 | #[cfg(stm32h5)] | ||
| 589 | mux_rcc_pclk4: None, | ||
| 590 | #[cfg(stm32h5)] | ||
| 591 | mux_hse: hse, | ||
| 592 | |||
| 593 | #[cfg(stm32h5)] | ||
| 594 | mux_hsi48: None, | ||
| 548 | }); | 595 | }); |
| 549 | } | 596 | } |
| 550 | 597 | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index abb53fd10..695d41589 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -134,6 +134,52 @@ pub struct Clocks { | |||
| 134 | pub hrtim: Option<Hertz>, | 134 | pub hrtim: Option<Hertz>, |
| 135 | 135 | ||
| 136 | pub rtc: Option<Hertz>, | 136 | pub rtc: Option<Hertz>, |
| 137 | |||
| 138 | #[cfg(stm32h5)] | ||
| 139 | pub mux_rcc_pclk1: Option<Hertz>, | ||
| 140 | #[cfg(stm32h5)] | ||
| 141 | pub mux_pll2_q: Option<Hertz>, | ||
| 142 | #[cfg(stm32h5)] | ||
| 143 | pub mux_pll3_q: Option<Hertz>, | ||
| 144 | #[cfg(stm32h5)] | ||
| 145 | pub mux_hsi_ker: Option<Hertz>, | ||
| 146 | #[cfg(stm32h5)] | ||
| 147 | pub mux_csi_ker: Option<Hertz>, | ||
| 148 | #[cfg(stm32h5)] | ||
| 149 | pub mux_lse: Option<Hertz>, | ||
| 150 | |||
| 151 | #[cfg(stm32h5)] | ||
| 152 | pub mux_pll1_q: Option<Hertz>, | ||
| 153 | #[cfg(stm32h5)] | ||
| 154 | pub mux_pll2_p: Option<Hertz>, | ||
| 155 | #[cfg(rcc_h5)] | ||
| 156 | pub mux_pll3_p: Option<Hertz>, | ||
| 157 | #[cfg(stm32h5)] | ||
| 158 | pub mux_audioclk: Option<Hertz>, | ||
| 159 | #[cfg(stm32h5)] | ||
| 160 | pub mux_per: Option<Hertz>, | ||
| 161 | |||
| 162 | #[cfg(stm32h5)] | ||
| 163 | pub mux_pll3_r: Option<Hertz>, | ||
| 164 | #[cfg(stm32h5)] | ||
| 165 | pub mux_rcc_pclk3: Option<Hertz>, | ||
| 166 | #[cfg(stm32h5)] | ||
| 167 | pub mux_pll3_1: Option<Hertz>, | ||
| 168 | #[cfg(stm32h5)] | ||
| 169 | pub mux_hsi48_ker: Option<Hertz>, | ||
| 170 | #[cfg(stm32h5)] | ||
| 171 | pub mux_lsi_ker: Option<Hertz>, | ||
| 172 | #[cfg(stm32h5)] | ||
| 173 | pub mux_pll2_r: Option<Hertz>, | ||
| 174 | #[cfg(stm32h5)] | ||
| 175 | pub mux_rcc_pclk2: Option<Hertz>, | ||
| 176 | #[cfg(stm32h5)] | ||
| 177 | pub mux_rcc_pclk4: Option<Hertz>, | ||
| 178 | #[cfg(stm32h5)] | ||
| 179 | pub mux_hse: Option<Hertz>, | ||
| 180 | |||
| 181 | #[cfg(stm32h5)] | ||
| 182 | pub mux_hsi48: Option<Hertz>, | ||
| 137 | } | 183 | } |
| 138 | 184 | ||
| 139 | #[cfg(feature = "low-power")] | 185 | #[cfg(feature = "low-power")] |
