Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: hil/rcc mux #2047

Closed
wants to merge 14 commits into from
Closed
115 changes: 107 additions & 8 deletions embassy-stm32/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::{env, fs};

use proc_macro2::{Ident, TokenStream};
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() {
let target = env::var("TARGET").unwrap();
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -454,10 +500,61 @@ fn main() {
(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! {
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
fn frequency() -> crate::time::Hertz {
unsafe { crate::rcc::get_freqs().#clk }
#clock_frequency
}
fn enable() {
critical_section::with(|_cs| {
Expand Down Expand Up @@ -486,12 +583,14 @@ fn main() {
}
}

let mut refcount_mod = TokenStream::new();
for refcount_static in refcount_statics {
refcount_mod.extend(quote! {
pub(crate) static mut #refcount_static: u8 = 0;
});
}
let refcount_mod: TokenStream = refcount_statics
.iter()
.map(|refcount_static| {
quote! {
pub(crate) static mut #refcount_static: u8 = 0;
}
})
.collect();

g.extend(quote! {
mod refcount_statics {
Expand Down
51 changes: 49 additions & 2 deletions embassy-stm32/src/rcc/h.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ pub(crate) unsafe fn init(config: Config) {
let pll1 = init_pll(0, config.pll1, &pll_input);
let pll2 = init_pll(1, config.pll2, &pll_input);
#[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
let (sys, sw) = match config.sys {
Expand Down Expand Up @@ -447,7 +447,7 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32h7)]
let adc = match config.adc_clock_source {
AdcClockSource::PLL2_P => pll2.p,
AdcClockSource::PLL3_R => _pll3.r,
AdcClockSource::PLL3_R => pll3.r,
AdcClockSource::PER => _per_ck,
_ => unreachable!(),
};
Expand Down Expand Up @@ -545,6 +545,53 @@ pub(crate) unsafe fn init(config: Config) {
apb2_tim,
adc,
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,
});
}

Expand Down
46 changes: 46 additions & 0 deletions embassy-stm32/src/rcc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,52 @@ pub struct Clocks {
pub hrtim: 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")]
Expand Down