Merge pull request #2521 from embassy-rs/rcc-mux

stm32: autogenerate clocks struct, enable mux for all chips.
This commit is contained in:
Dario Nieuwenhuis 2024-02-02 23:42:17 +01:00 committed by GitHub
commit 88e7e1ceb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 284 additions and 450 deletions

View File

@ -68,7 +68,7 @@ rand_core = "0.6.3"
sdio-host = "0.5.0"
critical-section = "1.1"
#stm32-metapac = { version = "15" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-768b3e8e3199e03de0acd0d4590d06f51eebb7dd" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3e3b53df78b4c90ae9c44a58b4f9f93c93a415b7" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
proc-macro2 = "1.0.36"
quote = "1.0.15"
#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-768b3e8e3199e03de0acd0d4590d06f51eebb7dd", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3e3b53df78b4c90ae9c44a58b4f9f93c93a415b7", default-features = false, features = ["metadata"]}
[features]

View File

@ -461,6 +461,8 @@ fn main() {
let force_refcount = HashSet::from(["usart"]);
let mut refcount_statics = BTreeSet::new();
let mut clock_names = BTreeSet::new();
for p in METADATA.peripherals {
if !singletons.contains(&p.name.to_string()) {
continue;
@ -492,7 +494,6 @@ fn main() {
let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
let pname = format_ident!("{}", p.name);
let clk = format_ident!("{}", rcc.clock);
let en_reg = format_ident!("{}", en.register);
let set_en_field = format_ident!("set_{}", en.field);
@ -522,14 +523,7 @@ fn main() {
(TokenStream::new(), TokenStream::new())
};
let mux_supported = HashSet::from(["c0", "h5", "h50", "h7", "h7ab", "h7rm0433", "g0", "g4", "l4"])
.contains(rcc_registers.version);
let mux_for = |mux: Option<&'static PeripheralRccRegister>| {
// restrict mux implementation to supported versions
if !mux_supported {
return None;
}
let mux = mux?;
let fieldset = rcc_enum_map.get(mux.register)?;
let enumm = fieldset.get(mux.field)?;
@ -550,15 +544,9 @@ fn main() {
.map(|v| {
let variant_name = format_ident!("{}", v.name);
let clock_name = format_ident!("{}", v.name.to_ascii_lowercase());
if v.name.starts_with("HCLK") || v.name.starts_with("PCLK") || v.name == "SYS" {
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name },
}
} else {
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
}
clock_names.insert(v.name.to_ascii_lowercase());
quote! {
#enum_name::#variant_name => unsafe { crate::rcc::get_freqs().#clock_name.unwrap() },
}
})
.collect();
@ -569,19 +557,21 @@ fn main() {
#[allow(unreachable_patterns)]
match crate::pac::RCC.#fieldset_name().read().#field_name() {
#match_arms
_ => unreachable!(),
}
}
}
None => quote! {
unsafe { crate::rcc::get_freqs().#clk }
},
None => {
let clock_name = format_ident!("{}", rcc.clock);
clock_names.insert(rcc.clock.to_string());
quote! {
unsafe { crate::rcc::get_freqs().#clock_name.unwrap() }
}
}
};
/*
A refcount leak can result if the same field is shared by peripherals with different stop modes
This condition should be checked in stm32-data
*/
let stop_refcount = match rcc.stop_mode {
@ -628,6 +618,39 @@ fn main() {
}
}
// Generate RCC
clock_names.insert("sys".to_string());
clock_names.insert("rtc".to_string());
let clock_idents: Vec<_> = clock_names.iter().map(|n| format_ident!("{}", n)).collect();
g.extend(quote! {
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Clocks {
#(
pub #clock_idents: Option<crate::time::Hertz>,
)*
}
});
let clocks_macro = quote!(
macro_rules! set_clocks {
($($(#[$m:meta])* $k:ident: $v:expr,)*) => {
{
#[allow(unused)]
struct Temp {
$($(#[$m])* $k: Option<crate::time::Hertz>,)*
}
let all = Temp {
$($(#[$m])* $k: $v,)*
};
crate::rcc::set_freqs(crate::rcc::Clocks {
#( #clock_idents: all.#clock_idents, )*
});
}
};
}
);
let refcount_mod: TokenStream = refcount_statics
.iter()
.map(|refcount_static| {
@ -1349,7 +1372,7 @@ fn main() {
}
}
let mut m = String::new();
let mut m = clocks_macro.to_string();
// DO NOT ADD more macros like these.
// These turned to be a bad idea!

View File

@ -6,7 +6,6 @@ use embassy_hal_internal::into_ref;
use embedded_hal_02::blocking::delay::DelayUs;
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
use crate::rcc::get_freqs;
use crate::time::Hertz;
use crate::{interrupt, Peripheral};
@ -80,7 +79,7 @@ impl<'d, T: Instance> Adc<'d, T> {
}
fn freq() -> Hertz {
unsafe { get_freqs() }.adc.unwrap()
T::frequency()
}
pub fn sample_time_for_us(&self, us: u32) -> SampleTime {

View File

@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> {
}
fn freq() -> Hertz {
<T as crate::adc::sealed::Instance>::frequency()
<T as crate::rcc::sealed::RccPeripheral>::frequency()
}
pub fn sample_time_for_us(&self, us: u32) -> SampleTime {

View File

@ -61,8 +61,6 @@ pub(crate) mod sealed {
fn regs() -> crate::pac::adc::Adc;
#[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
fn common_regs() -> crate::pac::adccommon::AdcCommon;
#[cfg(adc_f3)]
fn frequency() -> crate::time::Hertz;
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
fn state() -> &'static State;
}
@ -103,11 +101,6 @@ foreach_adc!(
return crate::pac::$common_inst
}
#[cfg(adc_f3)]
fn frequency() -> crate::time::Hertz {
unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
}
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
fn state() -> &'static sealed::State {
static STATE: sealed::State = sealed::State::new();

View File

@ -13,6 +13,7 @@ use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
use embassy_sync::waitqueue::AtomicWaker;
pub use self::_version::{InterruptHandler, *};
use crate::rcc::RccPeripheral;
#[allow(unused)]
const MTU: usize = 1514;
@ -183,7 +184,7 @@ pub(crate) mod sealed {
}
/// Ethernet instance.
pub trait Instance: sealed::Instance + Send + 'static {}
pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {}
impl sealed::Instance for crate::peripherals::ETH {
fn regs() -> crate::pac::eth::Eth {

View File

@ -20,6 +20,7 @@ use crate::pac::AFIO;
#[cfg(any(eth_v1b, eth_v1c))]
use crate::pac::SYSCFG;
use crate::pac::{ETH, RCC};
use crate::rcc::sealed::RccPeripheral;
use crate::{interrupt, Peripheral};
/// Interrupt handler.
@ -191,8 +192,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
// TODO MTU size setting not found for v1 ethernet, check if correct
// NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
let hclk = <T as RccPeripheral>::frequency();
let hclk_mhz = hclk.0 / 1_000_000;
// Set the MDC clock frequency in the range 1MHz - 2.5MHz

View File

@ -11,6 +11,7 @@ use crate::gpio::sealed::{AFType, Pin as _};
use crate::gpio::{AnyPin, Speed};
use crate::interrupt::InterruptExt;
use crate::pac::ETH;
use crate::rcc::sealed::RccPeripheral;
use crate::{interrupt, Peripheral};
/// Interrupt handler.
@ -264,8 +265,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
w.set_rbsz(RX_BUFFER_SIZE as u16);
});
// NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
let hclk = unsafe { crate::rcc::get_freqs() }.hclk1;
let hclk = <T as RccPeripheral>::frequency();
let hclk_mhz = hclk.0 / 1_000_000;
// Set the MDC clock frequency in the range 1MHz - 2.5MHz

View File

@ -10,8 +10,6 @@ pub use traits::Instance;
#[allow(unused_imports)]
use crate::gpio::sealed::{AFType, Pin};
use crate::gpio::AnyPin;
#[cfg(stm32f334)]
use crate::rcc::get_freqs;
use crate::time::Hertz;
use crate::Peripheral;
@ -182,7 +180,7 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
T::enable_and_reset();
#[cfg(stm32f334)]
if unsafe { get_freqs() }.hrtim.is_some() {
if crate::pac::RCC.cfgr3().read().hrtim1sw() == crate::pac::rcc::vals::Timsw::PLL1_P {
// Enable and and stabilize the DLL
T::regs().dllcr().modify(|w| {
w.set_cal(true);

View File

@ -80,10 +80,12 @@ pub(crate) mod sealed {
fn set_master_frequency(frequency: Hertz) {
let f = frequency.0;
#[cfg(not(stm32f334))]
// TODO: wire up HRTIM to the RCC mux infra.
//#[cfg(stm32f334)]
//let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
//#[cfg(not(stm32f334))]
let timer_f = Self::frequency().0;
#[cfg(stm32f334)]
let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
let psc = if Self::regs().isr().read().dllrdy() {
@ -103,10 +105,12 @@ pub(crate) mod sealed {
fn set_channel_frequency(channel: usize, frequency: Hertz) {
let f = frequency.0;
#[cfg(not(stm32f334))]
// TODO: wire up HRTIM to the RCC mux infra.
//#[cfg(stm32f334)]
//let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
//#[cfg(not(stm32f334))]
let timer_f = Self::frequency().0;
#[cfg(stm32f334)]
let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
let psc = if Self::regs().isr().read().dllrdy() {

View File

@ -4,7 +4,6 @@ use embassy_hal_internal::into_ref;
use crate::gpio::sealed::{AFType, Pin as _};
use crate::gpio::AnyPin;
use crate::pac::spi::vals;
use crate::rcc::get_freqs;
use crate::spi::{Config as SpiConfig, *};
use crate::time::Hertz;
use crate::{Peripheral, PeripheralRef};
@ -193,10 +192,10 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> {
spi_cfg.frequency = freq;
let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg);
#[cfg(all(rcc_f4, not(stm32f410)))]
let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap();
#[cfg(stm32f410)]
// TODO move i2s to the new mux infra.
//#[cfg(all(rcc_f4, not(stm32f410)))]
//let pclk = unsafe { get_freqs() }.plli2s1_q.unwrap();
//#[cfg(stm32f410)]
let pclk = T::frequency();
let (odd, div) = compute_baud_rate(pclk, freq, config.master_clock, config.format);

View File

@ -2,7 +2,6 @@ use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::Sw;
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Ppre as APBPrescaler};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -133,13 +132,13 @@ pub(crate) unsafe fn init(config: Config) {
}
};
set_freqs(Clocks {
set_clocks!(
hsi: None,
lse: None,
sys: sys_clk,
hclk1: ahb_freq,
pclk1: apb_freq,
pclk1_tim: apb_tim_freq,
rtc,
});
sys: Some(sys_clk),
hclk1: Some(ahb_freq),
pclk1: Some(apb_freq),
pclk1_tim: Some(apb_tim_freq),
rtc: rtc,
);
}

View File

@ -7,7 +7,6 @@ pub use crate::pac::rcc::vals::{
#[cfg(any(stm32f4, stm32f7))]
use crate::pac::PWR;
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
// TODO: on some F4s, PLLM is shared between all PLLs. Enforce that.
@ -183,9 +182,9 @@ pub(crate) unsafe fn init(config: Config) {
};
let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
let plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
let pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
// Configure sysclk
let sys = match config.sys {
@ -257,27 +256,41 @@ pub(crate) unsafe fn init(config: Config) {
});
while RCC.cfgr().read().sws() != config.sys {}
set_freqs(Clocks {
sys,
hclk1: hclk,
hclk2: hclk,
hclk3: hclk,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
rtc,
set_clocks!(
hsi: hsi,
hse: hse,
lse: None, // TODO
lsi: None, // TODO
sys: Some(sys),
hclk1: Some(hclk),
hclk2: Some(hclk),
hclk3: Some(hclk),
pclk1: Some(pclk1),
pclk2: Some(pclk2),
pclk1_tim: Some(pclk1_tim),
pclk2_tim: Some(pclk2_tim),
rtc: rtc,
pll1_q: pll.q,
#[cfg(all(rcc_f4, not(stm32f410)))]
plli2s1_q: _plli2s.q,
#[cfg(all(rcc_f4, not(stm32f410)))]
plli2s1_r: _plli2s.r,
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pllsai1_q: _pllsai.q,
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pllsai1_r: _pllsai.r,
});
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
plli2s1_p: plli2s.p,
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
plli2s1_q: plli2s.q,
#[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))]
plli2s1_r: plli2s.r,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pllsai1_p: pllsai.p,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pllsai1_q: pllsai.q,
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pllsai1_r: pllsai.r,
clk48: pll.q,
hsi_hse: None,
afif: None,
);
}
struct PllInput {

View File

@ -1,6 +1,5 @@
use stm32_metapac::flash::vals::Latency;
use super::{set_freqs, Clocks};
use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Sw, Usbsw};
use crate::pac::{FLASH, RCC};
use crate::time::Hertz;
@ -160,13 +159,15 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
set_freqs(Clocks {
sys: Hertz(real_sysclk),
pclk1: Hertz(pclk),
pclk2: Hertz(pclk),
pclk1_tim: Hertz(pclk * timer_mul),
pclk2_tim: Hertz(pclk * timer_mul),
hclk1: Hertz(hclk),
rtc,
});
set_clocks!(
hsi: None,
lse: None,
sys: Some(Hertz(real_sysclk)),
pclk1: Some(Hertz(pclk)),
pclk2: Some(Hertz(pclk)),
pclk1_tim: Some(Hertz(pclk * timer_mul)),
pclk2_tim: Some(Hertz(pclk * timer_mul)),
hclk1: Some(Hertz(hclk)),
rtc: rtc,
);
}

View File

@ -1,6 +1,5 @@
use core::convert::TryFrom;
use super::{set_freqs, Clocks};
use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::*;
use crate::pac::{FLASH, RCC};
@ -179,14 +178,14 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
set_freqs(Clocks {
sys: Hertz(real_sysclk),
pclk1: Hertz(pclk1),
pclk2: Hertz(pclk2),
pclk1_tim: Hertz(pclk1 * timer_mul1),
pclk2_tim: Hertz(pclk2 * timer_mul2),
hclk1: Hertz(hclk),
set_clocks!(
sys: Some(Hertz(real_sysclk)),
pclk1: Some(Hertz(pclk1)),
pclk2: Some(Hertz(pclk2)),
pclk1_tim: Some(Hertz(pclk1 * timer_mul1)),
pclk2_tim: Some(Hertz(pclk2 * timer_mul2)),
hclk1: Some(Hertz(hclk)),
adc: Some(Hertz(adcclk)),
rtc,
});
rtc: rtc,
);
}

View File

@ -4,7 +4,6 @@ use crate::pac::flash::vals::Latency;
pub use crate::pac::rcc::vals::Adcpres;
use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -279,13 +278,16 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sysclk,
pclk1: pclk1,
pclk2: pclk2,
pclk1_tim: pclk1 * timer_mul1,
pclk2_tim: pclk2 * timer_mul2,
hclk1: hclk,
set_clocks!(
hsi: None,
lse: None,
pll1_p: None,
sys: Some(sysclk),
pclk1: Some(pclk1),
pclk2: Some(pclk2),
pclk1_tim: Some(pclk1 * timer_mul1),
pclk2_tim: Some(pclk2 * timer_mul2),
hclk1: Some(hclk),
#[cfg(rcc_f3)]
adc: adc,
#[cfg(all(rcc_f3, adc3_common))]
@ -294,8 +296,8 @@ pub(crate) unsafe fn init(config: Config) {
adc34: None,
#[cfg(stm32f334)]
hrtim: hrtim,
rtc,
});
rtc: rtc,
);
}
#[inline]

View File

@ -4,7 +4,6 @@ pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler,
};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -352,11 +351,11 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(not(any(stm32g0b1, stm32g0c1, stm32g0b0)))]
let hsi48_freq: Option<Hertz> = None;
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
pclk1: apb_freq,
pclk1_tim: apb_tim_freq,
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(ahb_freq),
pclk1: Some(apb_freq),
pclk1_tim: Some(apb_tim_freq),
hsi: hsi_freq,
hsi48: hsi48_freq,
hsi_div_8: hsi_div_8_freq,
@ -365,6 +364,6 @@ pub(crate) unsafe fn init(config: Config) {
lsi: lsi_freq,
pll1_q: pll1_q_freq,
pll1_p: pll1_p_freq,
rtc,
});
rtc: rtc,
);
}

View File

@ -7,7 +7,6 @@ pub use crate::pac::rcc::vals::{
Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
};
use crate::pac::{PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -307,20 +306,20 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
hclk3: ahb_freq,
pclk1: apb1_freq,
pclk1_tim: apb1_tim_freq,
pclk2: apb2_freq,
pclk2_tim: apb2_tim_freq,
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(ahb_freq),
hclk2: Some(ahb_freq),
hclk3: Some(ahb_freq),
pclk1: Some(apb1_freq),
pclk1_tim: Some(apb1_tim_freq),
pclk2: Some(apb2_freq),
pclk2_tim: Some(apb2_tim_freq),
adc: adc12_ck,
adc34: adc345_ck,
pll1_p: None,
pll1_q: None, // TODO
hse: None, // TODO
rtc,
});
rtc: rtc,
);
}

View File

@ -12,7 +12,6 @@ pub use crate::pac::rcc::vals::{
};
use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -430,7 +429,7 @@ pub(crate) unsafe fn init(config: Config) {
};
// Configure HSI48.
let _hsi48 = config.hsi48.map(super::init_hsi48);
let hsi48 = config.hsi48.map(super::init_hsi48);
// Configure CSI.
RCC.cr().modify(|w| w.set_csion(config.csi));
@ -614,45 +613,33 @@ pub(crate) unsafe fn init(config: Config) {
while !pac::SYSCFG.cccsr().read().ready() {}
}
set_freqs(Clocks {
sys,
hclk1: hclk,
hclk2: hclk,
hclk3: hclk,
hclk4: hclk,
pclk1: apb1,
pclk2: apb2,
pclk3: apb3,
set_clocks!(
sys: Some(sys),
hclk1: Some(hclk),
hclk2: Some(hclk),
hclk3: Some(hclk),
hclk4: Some(hclk),
pclk1: Some(apb1),
pclk2: Some(apb2),
pclk3: Some(apb3),
#[cfg(stm32h7)]
pclk4: apb4,
#[cfg(stm32h5)]
pclk4: Hertz(1),
pclk1_tim: apb1_tim,
pclk2_tim: apb2_tim,
adc,
rtc,
pclk4: Some(apb4),
pclk1_tim: Some(apb1_tim),
pclk2_tim: Some(apb2_tim),
adc: adc,
rtc: rtc,
#[cfg(any(stm32h5, stm32h7))]
hsi: None,
#[cfg(stm32h5)]
hsi48: None,
#[cfg(stm32h5)]
lsi: None,
#[cfg(any(stm32h5, stm32h7))]
csi: None,
hsi: hsi,
hsi48: hsi48,
csi: csi,
hse: hse,
#[cfg(any(stm32h5, stm32h7))]
lse: None,
#[cfg(any(stm32h5, stm32h7))]
hse: None,
lsi: None,
#[cfg(any(stm32h5, stm32h7))]
pll1_q: pll1.q,
#[cfg(any(stm32h5, stm32h7))]
pll2_p: pll2.p,
#[cfg(any(stm32h5, stm32h7))]
pll2_q: pll2.q,
#[cfg(any(stm32h5, stm32h7))]
pll2_r: pll2.r,
#[cfg(any(rcc_h5, stm32h7))]
pll3_p: pll3.p,
@ -670,12 +657,8 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32h5)]
audioclk: None,
#[cfg(any(stm32h5, stm32h7))]
per: None,
#[cfg(stm32h7)]
rcc_pclk_d3: None,
});
);
}
struct PllInput {

View File

@ -9,7 +9,6 @@ pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
pub use crate::pac::rcc::vals::Hsepre as HsePrescaler;
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -262,7 +261,7 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
let pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
let sys_clk = match config.mux {
ClockSrc::HSE => hse.unwrap(),
@ -274,12 +273,12 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(any(rcc_l0_v2))]
let _clk48 = match config.clk48_src {
let clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48,
Clk48Src::PLL1_VCO_DIV_2 => pll.clk48,
};
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let _clk48 = match config.clk48_src {
let clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48,
Clk48Src::MSI => msi,
Clk48Src::PLLSAI1_Q => pllsai1.q,
@ -376,37 +375,53 @@ pub(crate) unsafe fn init(config: Config) {
while !RCC.extcfgr().read().c2hpref() {}
}
set_freqs(Clocks {
sys: sys_clk,
hclk1,
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(hclk1),
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk2,
hclk2: Some(hclk2),
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk3,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
hclk3: Some(hclk3),
pclk1: Some(pclk1),
pclk2: Some(pclk2),
pclk1_tim: Some(pclk1_tim),
pclk2_tim: Some(pclk2_tim),
#[cfg(stm32wl)]
pclk3: hclk3,
#[cfg(rcc_l4)]
hsi: None,
#[cfg(rcc_l4)]
lse: None,
#[cfg(rcc_l4)]
pllsai1_p: None,
#[cfg(rcc_l4)]
pllsai2_p: None,
#[cfg(rcc_l4)]
pll1_p: None,
#[cfg(rcc_l4)]
pll1_q: None,
#[cfg(rcc_l4)]
pclk3: Some(hclk3),
hsi: hsi,
hse: hse,
msi: msi,
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
clk48: clk48,
#[cfg(not(any(stm32l0, stm32l1)))]
pll1_p: pll.p,
#[cfg(not(any(stm32l0, stm32l1)))]
pll1_q: pll.q,
pll1_r: pll.r,
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pllsai1_p: pllsai1.p,
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pllsai1_q: pllsai1.q,
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pllsai1_r: pllsai1.r,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2_p: pllsai2.p,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2_q: pllsai2.q,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2_r: pllsai2.r,
rtc: rtc,
// TODO
sai1_extclk: None,
#[cfg(rcc_l4)]
sai2_extclk: None,
rtc,
});
lsi: None,
lse: None,
);
}
#[cfg(any(stm32l0, stm32l1))]

View File

@ -5,8 +5,6 @@
use core::mem::MaybeUninit;
use crate::time::Hertz;
mod bd;
mod mco;
pub use bd::*;
@ -32,162 +30,7 @@ mod _version;
pub use _version::*;
// Model Clock Configuration
//
// pub struct Clocks {
// hse: Option<Hertz>,
// hsi: bool,
// lse: Option<Hertz>,
// lsi: bool,
// rtc: RtcSource,
// }
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Clocks {
pub sys: Hertz,
// APB
pub pclk1: Hertz,
pub pclk1_tim: Hertz,
#[cfg(not(any(rcc_c0, rcc_g0)))]
pub pclk2: Hertz,
#[cfg(not(any(rcc_c0, rcc_g0)))]
pub pclk2_tim: Hertz,
#[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))]
pub pclk3: Hertz,
#[cfg(any(rcc_h7, rcc_h7rm0433, rcc_h7ab, stm32h5))]
pub pclk4: Hertz,
#[cfg(any(rcc_wba))]
pub pclk7: Hertz,
// AHB
pub hclk1: Hertz,
#[cfg(any(
rcc_l4,
rcc_l4plus,
rcc_l5,
rcc_f2,
rcc_f4,
rcc_f410,
rcc_f7,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_g4,
rcc_u5,
rcc_wb,
rcc_wba,
rcc_wl5,
rcc_wle
))]
pub hclk2: Hertz,
#[cfg(any(
rcc_l4,
rcc_l4plus,
rcc_l5,
rcc_f2,
rcc_f4,
rcc_f410,
rcc_f7,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_u5,
rcc_g4,
rcc_wb,
rcc_wl5,
rcc_wle
))]
pub hclk3: Hertz,
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))]
pub hclk4: Hertz,
#[cfg(all(rcc_f4, not(stm32f410)))]
pub plli2s1_q: Option<Hertz>,
#[cfg(all(rcc_f4, not(stm32f410)))]
pub plli2s1_r: Option<Hertz>,
#[cfg(rcc_l4)]
pub pllsai1_p: Option<Hertz>,
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pub pllsai1_q: Option<Hertz>,
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pub pllsai1_r: Option<Hertz>,
#[cfg(rcc_l4)]
pub pllsai2_p: Option<Hertz>,
#[cfg(any(stm32g0, stm32g4, rcc_l4))]
pub pll1_p: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7, stm32f2, stm32f4, stm32f7, rcc_l4, stm32g0, stm32g4))]
pub pll1_q: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll2_p: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll2_q: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll2_r: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll3_p: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll3_q: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub pll3_r: Option<Hertz>,
#[cfg(any(
rcc_f1,
rcc_f100,
rcc_f1cl,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_f3,
rcc_g4
))]
pub adc: Option<Hertz>,
#[cfg(any(rcc_f3, rcc_g4))]
pub adc34: Option<Hertz>,
#[cfg(stm32f334)]
pub hrtim: Option<Hertz>,
pub rtc: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0, stm32g0))]
pub hsi: Option<Hertz>,
#[cfg(any(stm32h5, stm32g0))]
pub hsi48: Option<Hertz>,
#[cfg(stm32g0)]
pub hsi_div_8: Option<Hertz>,
#[cfg(any(stm32g0, stm32h5))]
pub lsi: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub csi: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7, rcc_l4, rcc_c0, stm32g0))]
pub lse: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7, stm32g0, stm32g4))]
pub hse: Option<Hertz>,
#[cfg(stm32h5)]
pub audioclk: Option<Hertz>,
#[cfg(any(stm32h5, stm32h7))]
pub per: Option<Hertz>,
#[cfg(stm32h7)]
pub rcc_pclk_d3: Option<Hertz>,
#[cfg(rcc_l4)]
pub sai1_extclk: Option<Hertz>,
#[cfg(rcc_l4)]
pub sai2_extclk: Option<Hertz>,
}
pub use crate::_generated::Clocks;
#[cfg(feature = "low-power")]
/// Must be written within a critical section

View File

@ -1,7 +1,6 @@
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler};
use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -338,7 +337,7 @@ pub(crate) unsafe fn init(config: Config) {
}
};
let _hsi48 = config.hsi48.map(super::init_hsi48);
let hsi48 = config.hsi48.map(super::init_hsi48);
// The clock source is ready
// Calculate and set the flash wait states
@ -448,18 +447,37 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
hclk3: ahb_freq,
pclk1: apb1_freq,
pclk2: apb2_freq,
pclk3: apb3_freq,
pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq,
rtc,
});
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(ahb_freq),
hclk2: Some(ahb_freq),
hclk3: Some(ahb_freq),
pclk1: Some(apb1_freq),
pclk2: Some(apb2_freq),
pclk3: Some(apb3_freq),
pclk1_tim: Some(apb1_tim_freq),
pclk2_tim: Some(apb2_tim_freq),
hsi48: hsi48,
rtc: rtc,
// TODO
hse: None,
hsi: None,
audioclk: None,
hsi48_div_2: None,
lse: None,
lsi: None,
msik: None,
pll1_p: None,
pll1_q: None,
pll1_r: None,
pll2_p: None,
pll2_q: None,
pll2_r: None,
pll3_p: None,
pll3_q: None,
pll3_r: None,
);
}
fn msirange_to_hertz(range: Msirange) -> Hertz {

View File

@ -4,7 +4,6 @@ pub use crate::pac::rcc::vals::{
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as ClockSrc,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
@ -155,16 +154,23 @@ pub(crate) unsafe fn init(config: Config) {
RCC.ccipr3().modify(|w| w.set_adcsel(config.adc_clock_source));
set_freqs(Clocks {
sys: sys_clk,
hclk1,
hclk2,
hclk4,
pclk1,
pclk2,
pclk7,
pclk1_tim,
pclk2_tim,
rtc,
});
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(hclk1),
hclk2: Some(hclk2),
hclk4: Some(hclk4),
pclk1: Some(pclk1),
pclk2: Some(pclk2),
pclk7: Some(pclk7),
pclk1_tim: Some(pclk1_tim),
pclk2_tim: Some(pclk2_tim),
rtc: rtc,
hse: hse,
hsi: hsi,
// TODO
lse: None,
lsi: None,
pll1_q: None,
);
}

View File

@ -670,7 +670,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
_ => panic!("Invalid Bus Width"),
};
let ker_ck = T::kernel_clk();
let ker_ck = T::frequency();
let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?;
// Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7
@ -1023,7 +1023,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
/// specified frequency.
pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> {
let regs = T::regs();
let ker_ck = T::kernel_clk();
let ker_ck = T::frequency();
let bus_width = match self.d3.is_some() {
true => BusWidth::Four,
@ -1429,7 +1429,6 @@ pub(crate) mod sealed {
fn regs() -> RegBlock;
fn state() -> &'static AtomicWaker;
fn kernel_clk() -> Hertz;
}
pub trait Pins<T: Instance> {}
@ -1461,61 +1460,6 @@ pub trait SdmmcDma<T: Instance> {}
#[cfg(sdmmc_v2)]
impl<T: Instance> SdmmcDma<T> for NoDma {}
cfg_if::cfg_if! {
// TODO, these could not be implemented, because required clocks are not exposed in RCC:
// - H7 uses pll1_q_ck or pll2_r_ck depending on SDMMCSEL
// - L1 uses pll48
// - L4 uses clk48(pll48)
// - L4+, L5, U5 uses clk48(pll48) or PLLSAI3CLK(PLLP) depending on SDMMCSEL
if #[cfg(stm32f1)] {
// F1 uses AHB1(HCLK), which is correct in PAC
macro_rules! kernel_clk {
($inst:ident) => {
<peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
}
}
} else if #[cfg(any(stm32f2, stm32f4))] {
// F2, F4 always use pll48
macro_rules! kernel_clk {
($inst:ident) => {
critical_section::with(|_| unsafe {
unwrap!(crate::rcc::get_freqs().pll1_q)
})
}
}
} else if #[cfg(stm32f7)] {
macro_rules! kernel_clk {
(SDMMC1) => {
critical_section::with(|_| unsafe {
let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc1sel();
if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYS {
crate::rcc::get_freqs().sys
} else {
unwrap!(crate::rcc::get_freqs().pll1_q)
}
})
};
(SDMMC2) => {
critical_section::with(|_| unsafe {
let sdmmcsel = crate::pac::RCC.dckcfgr2().read().sdmmc2sel();
if sdmmcsel == crate::pac::rcc::vals::Sdmmcsel::SYS {
crate::rcc::get_freqs().sys
} else {
unwrap!(crate::rcc::get_freqs().pll1_q)
}
})
};
}
} else {
// Use default peripheral clock and hope it works
macro_rules! kernel_clk {
($inst:ident) => {
<peripherals::$inst as crate::rcc::sealed::RccPeripheral>::frequency()
}
}
}
}
foreach_peripheral!(
(sdmmc, $inst:ident) => {
impl sealed::Instance for peripherals::$inst {
@ -1529,10 +1473,6 @@ foreach_peripheral!(
static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
&WAKER
}
fn kernel_clk() -> Hertz {
kernel_clk!($inst)
}
}
impl Instance for peripherals::$inst {}

View File

@ -280,7 +280,7 @@ impl<'d, T: Instance> Driver<'d, T> {
#[cfg(time)]
embassy_time::block_for(embassy_time::Duration::from_millis(100));
#[cfg(not(time))]
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.0 / 10);
cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.unwrap().0 / 10);
#[cfg(not(usb_v4))]
regs.btable().write(|w| w.set_btable(0));