stm32: add initial rcc mux for h5
This commit is contained in:
parent
ac84631a2a
commit
57ccc1051a
@ -5,7 +5,8 @@ use std::{env, fs};
|
|||||||
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use stm32_metapac::metadata::{MemoryRegionKind, METADATA};
|
use stm32_metapac::metadata::ir::{BlockItemInner, Enum};
|
||||||
|
use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let target = env::var("TARGET").unwrap();
|
let target = env::var("TARGET").unwrap();
|
||||||
@ -387,6 +388,51 @@ fn main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========
|
||||||
|
// Generate rcc fieldset and enum maps
|
||||||
|
let rcc_enum_map: HashMap<&str, HashMap<&str, &Enum>> = {
|
||||||
|
let rcc_registers = METADATA
|
||||||
|
.peripherals
|
||||||
|
.iter()
|
||||||
|
.filter_map(|p| p.registers.as_ref())
|
||||||
|
.find(|r| r.kind == "rcc")
|
||||||
|
.unwrap()
|
||||||
|
.ir;
|
||||||
|
|
||||||
|
let rcc_blocks = rcc_registers.blocks.iter().find(|b| b.name == "Rcc").unwrap().items;
|
||||||
|
|
||||||
|
let rcc_block_item_map: HashMap<&str, &str> = rcc_blocks
|
||||||
|
.iter()
|
||||||
|
.filter_map(|b| match &b.inner {
|
||||||
|
BlockItemInner::Register(register) => register.fieldset.map(|f| (f, b.name)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let rcc_enum_map: HashMap<&str, &Enum> = rcc_registers.enums.iter().map(|e| (e.name, e)).collect();
|
||||||
|
|
||||||
|
rcc_registers
|
||||||
|
.fieldsets
|
||||||
|
.iter()
|
||||||
|
.filter_map(|f| {
|
||||||
|
rcc_block_item_map.get(f.name).map(|b| {
|
||||||
|
(
|
||||||
|
*b,
|
||||||
|
f.fields
|
||||||
|
.iter()
|
||||||
|
.filter_map(|f| {
|
||||||
|
let enumm = f.enumm?;
|
||||||
|
let enumm = rcc_enum_map.get(enumm)?;
|
||||||
|
|
||||||
|
Some((f.name, *enumm))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
// ========
|
// ========
|
||||||
// Generate RccPeripheral impls
|
// Generate RccPeripheral impls
|
||||||
|
|
||||||
@ -454,10 +500,61 @@ fn main() {
|
|||||||
(TokenStream::new(), TokenStream::new())
|
(TokenStream::new(), TokenStream::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
|
||||||
|
// temporary hack to restrict the scope of the implementation to h5
|
||||||
|
if !&chip_name.starts_with("stm32h5") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mux = mux?;
|
||||||
|
let fieldset = rcc_enum_map.get(mux.register)?;
|
||||||
|
let enumm = fieldset.get(mux.field)?;
|
||||||
|
|
||||||
|
Some((mux, *enumm))
|
||||||
|
};
|
||||||
|
|
||||||
|
let clock_frequency = match mux_for(rcc.mux.as_ref()) {
|
||||||
|
Some((mux, rcc_enumm)) => {
|
||||||
|
let fieldset_name = format_ident!("{}", mux.register);
|
||||||
|
let field_name = format_ident!("{}", mux.field);
|
||||||
|
let enum_name = format_ident!("{}", rcc_enumm.name);
|
||||||
|
|
||||||
|
let match_arms: TokenStream = rcc_enumm
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
|
.filter(|v| v.name != "DISABLE")
|
||||||
|
.map(|v| {
|
||||||
|
let variant_name = format_ident!("{}", v.name);
|
||||||
|
|
||||||
|
// temporary hack to restrict the scope of the implementation until clock names can be stabilized
|
||||||
|
let clock_name = format_ident!("mux_{}", v.name.to_ascii_lowercase());
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
use crate::pac::rcc::vals::#enum_name;
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
match crate::pac::RCC.#fieldset_name().read().#field_name() {
|
||||||
|
#match_arms
|
||||||
|
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => quote! {
|
||||||
|
unsafe { crate::rcc::get_freqs().#clk }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
g.extend(quote! {
|
g.extend(quote! {
|
||||||
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
||||||
fn frequency() -> crate::time::Hertz {
|
fn frequency() -> crate::time::Hertz {
|
||||||
unsafe { crate::rcc::get_freqs().#clk }
|
#clock_frequency
|
||||||
}
|
}
|
||||||
fn enable() {
|
fn enable() {
|
||||||
critical_section::with(|_cs| {
|
critical_section::with(|_cs| {
|
||||||
@ -486,12 +583,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut refcount_mod = TokenStream::new();
|
let refcount_mod: TokenStream = refcount_statics
|
||||||
for refcount_static in refcount_statics {
|
.iter()
|
||||||
refcount_mod.extend(quote! {
|
.map(|refcount_static| {
|
||||||
pub(crate) static mut #refcount_static: u8 = 0;
|
quote! {
|
||||||
});
|
pub(crate) static mut #refcount_static: u8 = 0;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
g.extend(quote! {
|
g.extend(quote! {
|
||||||
mod refcount_statics {
|
mod refcount_statics {
|
||||||
|
@ -388,7 +388,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
let pll1 = init_pll(0, config.pll1, &pll_input);
|
let pll1 = init_pll(0, config.pll1, &pll_input);
|
||||||
let pll2 = init_pll(1, config.pll2, &pll_input);
|
let pll2 = init_pll(1, config.pll2, &pll_input);
|
||||||
#[cfg(any(rcc_h5, stm32h7))]
|
#[cfg(any(rcc_h5, stm32h7))]
|
||||||
let _pll3 = init_pll(2, config.pll3, &pll_input);
|
let pll3 = init_pll(2, config.pll3, &pll_input);
|
||||||
|
|
||||||
// Configure sysclk
|
// Configure sysclk
|
||||||
let (sys, sw) = match config.sys {
|
let (sys, sw) = match config.sys {
|
||||||
@ -447,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
#[cfg(stm32h7)]
|
#[cfg(stm32h7)]
|
||||||
let adc = match config.adc_clock_source {
|
let adc = match config.adc_clock_source {
|
||||||
AdcClockSource::PLL2_P => pll2.p,
|
AdcClockSource::PLL2_P => pll2.p,
|
||||||
AdcClockSource::PLL3_R => _pll3.r,
|
AdcClockSource::PLL3_R => pll3.r,
|
||||||
AdcClockSource::PER => _per_ck,
|
AdcClockSource::PER => _per_ck,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
@ -545,6 +545,53 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
apb2_tim,
|
apb2_tim,
|
||||||
adc,
|
adc,
|
||||||
rtc,
|
rtc,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_rcc_pclk1: Some(apb1),
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll2_q: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll3_q: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_hsi_ker: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_csi_ker: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_lse: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll1_q: pll1.q,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll2_p: pll2.p,
|
||||||
|
#[cfg(rcc_h5)]
|
||||||
|
mux_pll3_p: pll3.p,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_audioclk: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_per: None,
|
||||||
|
|
||||||
|
#[cfg(rcc_h5)]
|
||||||
|
mux_pll3_r: pll3.r,
|
||||||
|
#[cfg(all(not(rcc_h5), stm32h5))]
|
||||||
|
mux_pll3_r: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_rcc_pclk3: Some(apb3),
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll3_1: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_hsi48_ker: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_lsi_ker: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_pll2_r: pll2.r,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_rcc_pclk2: Some(apb2),
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_rcc_pclk4: None,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_hse: hse,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
mux_hsi48: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +134,52 @@ pub struct Clocks {
|
|||||||
pub hrtim: Option<Hertz>,
|
pub hrtim: Option<Hertz>,
|
||||||
|
|
||||||
pub rtc: Option<Hertz>,
|
pub rtc: Option<Hertz>,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_rcc_pclk1: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll2_q: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll3_q: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_hsi_ker: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_csi_ker: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_lse: Option<Hertz>,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll1_q: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll2_p: Option<Hertz>,
|
||||||
|
#[cfg(rcc_h5)]
|
||||||
|
pub mux_pll3_p: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_audioclk: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_per: Option<Hertz>,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll3_r: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_rcc_pclk3: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll3_1: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_hsi48_ker: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_lsi_ker: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_pll2_r: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_rcc_pclk2: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_rcc_pclk4: Option<Hertz>,
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_hse: Option<Hertz>,
|
||||||
|
|
||||||
|
#[cfg(stm32h5)]
|
||||||
|
pub mux_hsi48: Option<Hertz>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
|
Loading…
Reference in New Issue
Block a user