stm32: autogenerate mux config for all chips.

This commit is contained in:
Dario Nieuwenhuis 2024-02-26 03:28:27 +01:00
parent d5c9c611fa
commit 95234cddba
30 changed files with 412 additions and 518 deletions

View file

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

View file

@ -5,7 +5,9 @@ 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, PeripheralRccKernelClock, StopMode, METADATA}; use stm32_metapac::metadata::{
MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA,
};
fn main() { fn main() {
let target = env::var("TARGET").unwrap(); let target = env::var("TARGET").unwrap();
@ -374,12 +376,130 @@ fn main() {
} }
} }
let force_refcount = HashSet::from(["usart"]); struct ClockGen<'a> {
let mut refcount_statics = BTreeSet::new(); rcc_registers: &'a PeripheralRegisters,
chained_muxes: HashMap<&'a str, &'a PeripheralRccRegister>,
force_refcount: HashSet<&'a str>,
let mut clock_names = BTreeSet::new(); refcount_statics: BTreeSet<Ident>,
clock_names: BTreeSet<String>,
muxes: BTreeSet<(Ident, Ident, Ident)>,
}
let mut rcc_cfgr_regs = BTreeSet::new(); let mut clock_gen = ClockGen {
rcc_registers,
chained_muxes: HashMap::new(),
force_refcount: HashSet::from(["usart"]),
refcount_statics: BTreeSet::new(),
clock_names: BTreeSet::new(),
muxes: BTreeSet::new(),
};
if chip_name.starts_with("stm32h5") {
clock_gen.chained_muxes.insert(
"PER",
&PeripheralRccRegister {
register: "CCIPR5",
field: "PERSEL",
},
);
}
if chip_name.starts_with("stm32h7") {
clock_gen.chained_muxes.insert(
"PER",
&PeripheralRccRegister {
register: "D1CCIPR",
field: "PERSEL",
},
);
}
if chip_name.starts_with("stm32u5") {
clock_gen.chained_muxes.insert(
"ICLK",
&PeripheralRccRegister {
register: "CCIPR1",
field: "ICLKSEL",
},
);
}
if chip_name.starts_with("stm32wb") && !chip_name.starts_with("stm32wba") {
clock_gen.chained_muxes.insert(
"CLK48",
&PeripheralRccRegister {
register: "CCIPR",
field: "CLK48SEL",
},
);
}
if chip_name.starts_with("stm32f7") {
clock_gen.chained_muxes.insert(
"CLK48",
&PeripheralRccRegister {
register: "DCKCFGR2",
field: "CLK48SEL",
},
);
}
if chip_name.starts_with("stm32f4") && !chip_name.starts_with("stm32f410") {
clock_gen.chained_muxes.insert(
"CLK48",
&PeripheralRccRegister {
register: "DCKCFGR",
field: "CLK48SEL",
},
);
}
impl<'a> ClockGen<'a> {
fn gen_clock(&mut self, name: &str) -> TokenStream {
let clock_name = format_ident!("{}", name.to_ascii_lowercase());
self.clock_names.insert(name.to_ascii_lowercase());
quote!( unsafe { crate::rcc::get_freqs().#clock_name.unwrap() } )
}
fn gen_mux(&mut self, mux: &PeripheralRccRegister) -> TokenStream {
let ir = &self.rcc_registers.ir;
let fieldset_name = mux.register.to_ascii_lowercase();
let fieldset = ir
.fieldsets
.iter()
.find(|i| i.name.eq_ignore_ascii_case(&fieldset_name))
.unwrap();
let field_name = mux.field.to_ascii_lowercase();
let field = fieldset.fields.iter().find(|i| i.name == field_name).unwrap();
let enum_name = field.enumm.unwrap();
let enumm = ir.enums.iter().find(|i| i.name == enum_name).unwrap();
let fieldset_name = format_ident!("{}", fieldset_name);
let field_name = format_ident!("{}", field_name);
let enum_name = format_ident!("{}", enum_name);
self.muxes
.insert((fieldset_name.clone(), field_name.clone(), enum_name.clone()));
let mut match_arms = TokenStream::new();
for v in enumm.variants.iter().filter(|v| v.name != "DISABLE") {
let variant_name = format_ident!("{}", v.name);
let expr = if let Some(mux) = self.chained_muxes.get(&v.name) {
self.gen_mux(mux)
} else {
self.gen_clock(&v.name)
};
match_arms.extend(quote! {
crate::pac::rcc::vals::#enum_name::#variant_name => #expr,
});
}
quote! {
match crate::pac::RCC.#fieldset_name().read().#field_name() {
#match_arms
#[allow(unreachable_patterns)]
_ => unreachable!(),
}
}
}
}
for p in METADATA.peripherals { for p in METADATA.peripherals {
if !singletons.contains(&p.name.to_string()) { if !singletons.contains(&p.name.to_string()) {
@ -416,12 +536,12 @@ fn main() {
let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
let refcount = let refcount =
force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1; clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1;
let (before_enable, before_disable) = if refcount { let (before_enable, before_disable) = if refcount {
let refcount_static = let refcount_static =
format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());
refcount_statics.insert(refcount_static.clone()); clock_gen.refcount_statics.insert(refcount_static.clone());
( (
quote! { quote! {
@ -442,63 +562,12 @@ fn main() {
}; };
let clock_frequency = match &rcc.kernel_clock { let clock_frequency = match &rcc.kernel_clock {
PeripheralRccKernelClock::Mux(mux) => { PeripheralRccKernelClock::Mux(mux) => clock_gen.gen_mux(mux),
let ir = &rcc_registers.ir; PeripheralRccKernelClock::Clock(clock) => clock_gen.gen_clock(clock),
let fieldset_name = mux.register.to_ascii_lowercase();
let fieldset = ir
.fieldsets
.iter()
.find(|i| i.name.eq_ignore_ascii_case(&fieldset_name))
.unwrap();
let field_name = mux.field.to_ascii_lowercase();
let field = fieldset.fields.iter().find(|i| i.name == field_name).unwrap();
let enum_name = field.enumm.unwrap();
let enumm = ir.enums.iter().find(|i| i.name == enum_name).unwrap();
let fieldset_name = format_ident!("{}", fieldset_name);
let field_name = format_ident!("{}", field_name);
let enum_name = format_ident!("{}", enum_name);
rcc_cfgr_regs.insert((fieldset_name.clone(), field_name.clone(), enum_name.clone()));
let match_arms: TokenStream = enumm
.variants
.iter()
.filter(|v| v.name != "DISABLE")
.map(|v| {
let variant_name = format_ident!("{}", v.name);
let clock_name = format_ident!("{}", v.name.to_ascii_lowercase());
clock_names.insert(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!(),
}
}
}
PeripheralRccKernelClock::Clock(clock) => {
let clock = clock.to_ascii_lowercase();
let clock_name = format_ident!("{}", clock);
clock_names.insert(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
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
This condition should be checked in stm32-data
*/
let stop_refcount = match rcc.stop_mode { let stop_refcount = match rcc.stop_mode {
StopMode::Standby => None, StopMode::Standby => None,
StopMode::Stop2 => Some(quote! { REFCOUNT_STOP2 }), StopMode::Stop2 => Some(quote! { REFCOUNT_STOP2 }),
@ -543,74 +612,79 @@ fn main() {
} }
} }
if !rcc_cfgr_regs.is_empty() { let struct_fields: Vec<_> = clock_gen
println!("cargo:rustc-cfg=clock_mux"); .muxes
.iter()
.map(|(_fieldset, fieldname, enum_name)| {
quote! {
pub #fieldname: #enum_name
}
})
.collect();
let struct_fields: Vec<_> = rcc_cfgr_regs let mut inits = TokenStream::new();
for fieldset in clock_gen
.muxes
.iter()
.map(|(f, _, _)| f)
.collect::<BTreeSet<_>>()
.into_iter()
{
let setters: Vec<_> = clock_gen
.muxes
.iter() .iter()
.map(|(_fieldset, fieldname, enum_name)| { .filter(|(f, _, _)| f == fieldset)
quote! { .map(|(_, fieldname, _)| {
pub #fieldname: Option<#enum_name>
}
})
.collect();
let field_names: Vec<_> = rcc_cfgr_regs
.iter()
.map(|(_fieldset, fieldname, _enum_name)| fieldname)
.collect();
let inits: Vec<_> = rcc_cfgr_regs
.iter()
.map(|(fieldset, fieldname, _enum_name)| {
let setter = format_ident!("set_{}", fieldname); let setter = format_ident!("set_{}", fieldname);
quote! { quote! {
match self.#fieldname { w.#setter(self.#fieldname);
None => {}
Some(val) => {
crate::pac::RCC.#fieldset()
.modify(|w| w.#setter(val));
}
};
} }
}) })
.collect(); .collect();
let enum_names: BTreeSet<_> = rcc_cfgr_regs inits.extend(quote! {
.iter() crate::pac::RCC.#fieldset().modify(|w| {
.map(|(_fieldset, _fieldname, enum_name)| enum_name) #(#setters)*
.collect(); });
})
g.extend(quote! {
pub mod mux {
#(pub use crate::pac::rcc::vals::#enum_names as #enum_names; )*
#[derive(Clone, Copy)]
pub struct ClockMux {
#( #struct_fields, )*
}
impl Default for ClockMux {
fn default() -> Self {
Self {
#( #field_names: None, )*
}
}
}
impl ClockMux {
pub fn init(self) {
#( #inits )*
}
}
}
});
} }
let enum_names: BTreeSet<_> = clock_gen.muxes.iter().map(|(_, _, enum_name)| enum_name).collect();
g.extend(quote! {
pub mod mux {
#(pub use crate::pac::rcc::vals::#enum_names as #enum_names; )*
#[derive(Clone, Copy)]
pub struct ClockMux {
#( #struct_fields, )*
}
impl ClockMux {
pub(crate) const fn default() -> Self {
// safety: zero value is valid for all PAC enums.
unsafe { ::core::mem::zeroed() }
}
}
impl Default for ClockMux {
fn default() -> Self {
Self::default()
}
}
impl ClockMux {
pub(crate) fn init(&self) {
#inits
}
}
}
});
// Generate RCC // Generate RCC
clock_names.insert("sys".to_string()); clock_gen.clock_names.insert("sys".to_string());
clock_names.insert("rtc".to_string()); clock_gen.clock_names.insert("rtc".to_string());
let clock_idents: Vec<_> = clock_names.iter().map(|n| format_ident!("{}", n)).collect(); let clock_idents: Vec<_> = clock_gen.clock_names.iter().map(|n| format_ident!("{}", n)).collect();
g.extend(quote! { g.extend(quote! {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -640,7 +714,8 @@ fn main() {
} }
); );
let refcount_mod: TokenStream = refcount_statics let refcount_mod: TokenStream = clock_gen
.refcount_statics
.iter() .iter()
.map(|refcount_static| { .map(|refcount_static| {
quote! { quote! {

View file

@ -7,7 +7,6 @@ use core::task::Poll;
use self::sealed::Instance; use self::sealed::Instance;
use crate::interrupt; use crate::interrupt;
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::typelevel::Interrupt;
use crate::pac::rcc::vals::{Lptim1sel, Lptim2sel};
use crate::peripherals::IPCC; use crate::peripherals::IPCC;
use crate::rcc::sealed::RccPeripheral; use crate::rcc::sealed::RccPeripheral;
@ -105,7 +104,8 @@ impl Ipcc {
IPCC::enable_and_reset(); IPCC::enable_and_reset();
IPCC::set_cpu2(true); IPCC::set_cpu2(true);
_configure_pwr(); // set RF wake-up clock = LSE
crate::pac::RCC.csr().modify(|w| w.set_rfwkpsel(0b01));
let regs = IPCC::regs(); let regs = IPCC::regs();
@ -271,18 +271,3 @@ pub(crate) mod sealed {
fn state() -> &'static State; fn state() -> &'static State;
} }
} }
fn _configure_pwr() {
// TODO: move the rest of this to rcc
let rcc = crate::pac::RCC;
// TODO: required
// set RF wake-up clock = LSE
rcc.csr().modify(|w| w.set_rfwkpsel(0b01));
// set LPTIM1 & LPTIM2 clock source
rcc.ccipr().modify(|w| {
w.set_lptim1sel(Lptim1sel::PCLK1);
w.set_lptim2sel(Lptim2sel::PCLK1);
});
}

View file

@ -21,6 +21,9 @@ pub struct Config {
pub ahb_pre: AHBPrescaler, pub ahb_pre: AHBPrescaler,
pub apb_pre: APBPrescaler, pub apb_pre: APBPrescaler,
pub ls: super::LsConfig, pub ls: super::LsConfig,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -31,6 +34,7 @@ impl Default for Config {
ahb_pre: AHBPrescaler::DIV1, ahb_pre: AHBPrescaler::DIV1,
apb_pre: APBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1,
ls: Default::default(), ls: Default::default(),
mux: Default::default(),
} }
} }
} }
@ -97,28 +101,25 @@ pub(crate) unsafe fn init(config: Config) {
if !set_flash_latency_after { if !set_flash_latency_after {
// Spin until the effective flash latency is compatible with the clock change // Spin until the effective flash latency is compatible with the clock change
while FLASH.acr().read().latency().to_bits() < target_flash_latency.to_bits() {} while FLASH.acr().read().latency() < target_flash_latency {}
} }
// Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once
let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
RCC.cfgr().modify(|w| { RCC.cfgr().modify(|w| {
w.set_sw(sw); w.set_sw(sw);
w.set_hpre(hpre); w.set_hpre(config.ahb_pre);
w.set_ppre(ppre); w.set_ppre(config.apb_pre);
}); });
// Spin until the SYSCLK changes have taken effect
if set_flash_latency_after { loop {
// We can make the flash require fewer wait states let cfgr = RCC.cfgr().read();
// Spin until the SYSCLK changes have taken effect if cfgr.sw() == sw && cfgr.hpre() == config.ahb_pre && cfgr.ppre() == config.apb_pre {
loop { break;
let cfgr = RCC.cfgr().read();
if cfgr.sw() == sw && cfgr.hpre() == hpre && cfgr.ppre() == ppre {
break;
}
} }
}
// Set the flash latency to require fewer wait states // Set the flash latency to require fewer wait states
if set_flash_latency_after {
FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
} }
@ -132,6 +133,11 @@ pub(crate) unsafe fn init(config: Config) {
} }
}; };
config.mux.init();
// without this, the ringbuffered uart test fails.
cortex_m::asm::dsb();
set_clocks!( set_clocks!(
hsi: None, hsi: None,
lse: None, lse: None,

View file

@ -98,8 +98,8 @@ pub struct Config {
#[cfg(all(stm32f3, not(rcc_f37), adc3_common))] #[cfg(all(stm32f3, not(rcc_f37), adc3_common))]
pub adc34: AdcClockSource, pub adc34: AdcClockSource,
#[cfg(clock_mux)] /// Per-peripheral kernel clock selection muxes
pub mux: crate::rcc::mux::ClockMux, pub mux: super::mux::ClockMux,
pub ls: super::LsConfig, pub ls: super::LsConfig,
} }
@ -128,7 +128,6 @@ impl Default for Config {
#[cfg(all(stm32f3, not(rcc_f37), adc3_common))] #[cfg(all(stm32f3, not(rcc_f37), adc3_common))]
adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
#[cfg(clock_mux)]
mux: Default::default(), mux: Default::default(),
} }
} }
@ -370,7 +369,6 @@ pub(crate) unsafe fn init(config: Config) {
}; };
*/ */
#[cfg(clock_mux)]
config.mux.init(); config.mux.init();
set_clocks!( set_clocks!(

View file

@ -95,6 +95,9 @@ pub struct Config {
pub ls: super::LsConfig, pub ls: super::LsConfig,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
#[cfg(stm32f2)] #[cfg(stm32f2)]
pub voltage: VoltageScale, pub voltage: VoltageScale,
} }
@ -120,6 +123,7 @@ impl Default for Config {
#[cfg(stm32f2)] #[cfg(stm32f2)]
voltage: VoltageScale::Range3, voltage: VoltageScale::Range3,
mux: Default::default(),
} }
} }
} }
@ -256,6 +260,8 @@ pub(crate) unsafe fn init(config: Config) {
}); });
while RCC.cfgr().read().sws() != config.sys {} while RCC.cfgr().read().sws() != config.sys {}
config.mux.init();
set_clocks!( set_clocks!(
hsi: hsi, hsi: hsi,
hse: hse, hse: hse,
@ -286,7 +292,9 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))] #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
pllsai1_r: pllsai.r, pllsai1_r: pllsai.r,
clk48: pll.q, // TODO workaround until f4 rcc is fixed in stm32-data
#[cfg(not(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7)))]
pllsai1_q: None,
hsi_div488: hsi.map(|hsi| hsi/488u32), hsi_div488: hsi.map(|hsi| hsi/488u32),
hsi_hse: None, hsi_hse: None,

View file

@ -71,22 +71,6 @@ pub enum PllSource {
HSE(Hertz, HseMode), HSE(Hertz, HseMode),
} }
/// Sets the source for the 48MHz clock to the USB peripheral.
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))]
pub enum UsbSrc {
/// Use the High Speed Internal Oscillator. The CRS must be used to calibrate the
/// oscillator to comply with the USB specification for oscillator tolerance.
#[cfg(any(stm32g0b1, stm32g0c1))]
Hsi48(super::Hsi48Config),
/// Use the PLLQ output. The PLL must be configured to output a 48MHz clock. The
/// PLL needs to be using the HSE source to comply with the USB specification for oscillator
/// tolerance.
PllQ,
/// Use the HSE source directly. The HSE must be a 48MHz source. The HSE source must comply
/// with the USB specification for oscillator tolerance.
HSE,
}
/// Clocks configutation /// Clocks configutation
pub struct Config { pub struct Config {
pub sys: Sysclk, pub sys: Sysclk,
@ -94,8 +78,10 @@ pub struct Config {
pub apb_pre: APBPrescaler, pub apb_pre: APBPrescaler,
pub low_power_run: bool, pub low_power_run: bool,
pub ls: super::LsConfig, pub ls: super::LsConfig,
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] #[cfg(crs)]
pub usb_src: Option<UsbSrc>, pub hsi48: Option<super::Hsi48Config>,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -107,8 +93,9 @@ impl Default for Config {
apb_pre: APBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1,
low_power_run: false, low_power_run: false,
ls: Default::default(), ls: Default::default(),
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] #[cfg(crs)]
usb_src: None, hsi48: Some(Default::default()),
mux: Default::default(),
} }
} }
} }
@ -322,34 +309,12 @@ pub(crate) unsafe fn init(config: Config) {
let lsi_freq = (sw == Sw::LSI).then_some(super::LSI_FREQ); let lsi_freq = (sw == Sw::LSI).then_some(super::LSI_FREQ);
let hse_freq = (sw == Sw::HSE).then_some(sys_clk); let hse_freq = (sw == Sw::HSE).then_some(sys_clk);
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] #[cfg(crs)]
let hsi48_freq = config.usb_src.and_then(|config| { let hsi48 = config.hsi48.map(super::init_hsi48);
match config { #[cfg(not(crs))]
UsbSrc::PllQ => { let hsi48: Option<Hertz> = None;
// Make sure the PLLQ is enabled and running at 48Mhz
assert!(pll1_q_freq.is_some() && pll1_q_freq.unwrap().0 == 48_000_000); config.mux.init();
RCC.ccipr2()
.modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::PLL1_Q));
None
}
UsbSrc::HSE => {
// Make sure the HSE is enabled and running at 48Mhz
assert!(hse_freq.is_some() && hse_freq.unwrap().0 == 48_000_000);
RCC.ccipr2()
.modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSE));
None
}
#[cfg(any(stm32g0b1, stm32g0c1))]
UsbSrc::Hsi48(config) => {
let freq = super::init_hsi48(config);
RCC.ccipr2()
.modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48));
Some(freq)
}
}
});
#[cfg(not(any(stm32g0b1, stm32g0c1, stm32g0b0)))]
let hsi48_freq: Option<Hertz> = None;
set_clocks!( set_clocks!(
sys: Some(sys_clk), sys: Some(sys_clk),
@ -357,7 +322,7 @@ pub(crate) unsafe fn init(config: Config) {
pclk1: Some(apb_freq), pclk1: Some(apb_freq),
pclk1_tim: Some(apb_tim_freq), pclk1_tim: Some(apb_tim_freq),
hsi: hsi_freq, hsi: hsi_freq,
hsi48: hsi48_freq, hsi48: hsi48,
hsi_div_8: hsi_div_8_freq, hsi_div_8: hsi_div_8_freq,
hse: hse_freq, hse: hse_freq,
lse: lse_freq, lse: lse_freq,

View file

@ -1,11 +1,10 @@
use stm32_metapac::flash::vals::Latency; use stm32_metapac::flash::vals::Latency;
use stm32_metapac::rcc::vals::{Adcsel, Sw}; use stm32_metapac::rcc::vals::Sw;
use stm32_metapac::FLASH; use stm32_metapac::FLASH;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Adcsel as AdcClockSource, Clk48sel as Clk48Src, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc,
Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc, Ppre as APBPrescaler, Ppre as APBPrescaler, Sw as Sysclk,
Sw as Sysclk,
}; };
use crate::pac::{PWR, RCC}; use crate::pac::{PWR, RCC};
use crate::time::Hertz; use crate::time::Hertz;
@ -82,24 +81,15 @@ pub struct Config {
pub low_power_run: bool, pub low_power_run: bool,
/// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals.
pub clk48_src: Clk48Src,
/// Low-Speed Clock Configuration /// Low-Speed Clock Configuration
pub ls: super::LsConfig, pub ls: super::LsConfig,
/// Clock Source for ADCs 1 and 2
pub adc12_clock_source: AdcClockSource,
/// Clock Source for ADCs 3, 4 and 5
pub adc345_clock_source: AdcClockSource,
/// Clock Source for FDCAN
pub fdcan_clock_source: FdCanClockSource,
/// Enable range1 boost mode /// Enable range1 boost mode
/// Recommended when the SYSCLK frequency is greater than 150MHz. /// Recommended when the SYSCLK frequency is greater than 150MHz.
pub boost: bool, pub boost: bool,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -115,12 +105,9 @@ impl Default for Config {
apb1_pre: APBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1,
low_power_run: false, low_power_run: false,
clk48_src: Clk48Src::HSI48,
ls: Default::default(), ls: Default::default(),
adc12_clock_source: Adcsel::DISABLE,
adc345_clock_source: Adcsel::DISABLE,
fdcan_clock_source: FdCanClockSource::PCLK1,
boost: false, boost: false,
mux: Default::default(),
} }
} }
} }
@ -165,9 +152,7 @@ pub(crate) unsafe fn init(config: Config) {
}; };
// Configure HSI48 if required // Configure HSI48 if required
if let Some(hsi48_config) = config.hsi48 { let hsi48 = config.hsi48.map(super::init_hsi48);
super::init_hsi48(hsi48_config);
}
let pll_freq = config.pll.map(|pll_config| { let pll_freq = config.pll.map(|pll_config| {
let src_freq = match pll_config.source { let src_freq = match pll_config.source {
@ -176,13 +161,13 @@ pub(crate) unsafe fn init(config: Config) {
_ => unreachable!(), _ => unreachable!(),
}; };
assert!(max::PLL_IN.contains(&src_freq));
// Disable PLL before configuration // Disable PLL before configuration
RCC.cr().modify(|w| w.set_pllon(false)); RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {} while RCC.cr().read().pllrdy() {}
let internal_freq = src_freq / pll_config.prediv * pll_config.mul; let in_freq = src_freq / pll_config.prediv;
assert!(max::PLL_IN.contains(&in_freq));
let internal_freq = in_freq * pll_config.mul;
assert!(max::PLL_VCO.contains(&internal_freq)); assert!(max::PLL_VCO.contains(&internal_freq));
@ -301,42 +286,6 @@ pub(crate) unsafe fn init(config: Config) {
let (apb1_freq, apb1_tim_freq) = super::util::calc_pclk(hclk, config.apb1_pre); let (apb1_freq, apb1_tim_freq) = super::util::calc_pclk(hclk, config.apb1_pre);
let (apb2_freq, apb2_tim_freq) = super::util::calc_pclk(hclk, config.apb2_pre); let (apb2_freq, apb2_tim_freq) = super::util::calc_pclk(hclk, config.apb2_pre);
// Configure the 48MHz clock source for USB and RNG peripherals.
RCC.ccipr().modify(|w| {
w.set_clk48sel(match config.clk48_src {
Clk48Src::PLL1_Q => {
// Not checking that PLL1_Q is 48MHz here so as not to require the user to have a 48MHz clock.
// Peripherals which require one (USB, RNG) should check that theyre driven by a valid 48MHz
// clock at init.
crate::pac::rcc::vals::Clk48sel::PLL1_Q
}
Clk48Src::HSI48 => {
// Make sure HSI48 is enabled
assert!(config.hsi48.is_some());
crate::pac::rcc::vals::Clk48sel::HSI48
}
_ => unreachable!(),
})
});
RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source));
RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source));
RCC.ccipr().modify(|w| w.set_fdcansel(config.fdcan_clock_source));
let adc12_ck = match config.adc12_clock_source {
AdcClockSource::DISABLE => None,
AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p,
AdcClockSource::SYS => Some(sys_clk),
_ => unreachable!(),
};
let adc345_ck = match config.adc345_clock_source {
AdcClockSource::DISABLE => None,
AdcClockSource::PLL1_P => pll_freq.as_ref().unwrap().pll_p,
AdcClockSource::SYS => Some(sys_clk),
_ => unreachable!(),
};
if config.low_power_run { if config.low_power_run {
assert!(sys_clk <= Hertz(2_000_000)); assert!(sys_clk <= Hertz(2_000_000));
PWR.cr1().modify(|w| w.set_lpr(true)); PWR.cr1().modify(|w| w.set_lpr(true));
@ -344,6 +293,8 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init(); let rtc = config.ls.init();
config.mux.init();
set_clocks!( set_clocks!(
sys: Some(sys_clk), sys: Some(sys_clk),
hclk1: Some(hclk), hclk1: Some(hclk),
@ -353,12 +304,11 @@ pub(crate) unsafe fn init(config: Config) {
pclk1_tim: Some(apb1_tim_freq), pclk1_tim: Some(apb1_tim_freq),
pclk2: Some(apb2_freq), pclk2: Some(apb2_freq),
pclk2_tim: Some(apb2_tim_freq), pclk2_tim: Some(apb2_tim_freq),
adc: adc12_ck,
adc34: adc345_ck,
pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p), pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p),
pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_q), pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_q),
pll1_r: pll_freq.as_ref().and_then(|pll| pll.pll_r), pll1_r: pll_freq.as_ref().and_then(|pll| pll.pll_r),
hse: hse, hse: hse,
hsi48: hsi48,
rtc: rtc, rtc: rtc,
); );
} }

View file

@ -2,15 +2,10 @@ use core::ops::RangeInclusive;
use crate::pac; use crate::pac;
use crate::pac::pwr::vals::Vos; use crate::pac::pwr::vals::Vos;
#[cfg(stm32h5)]
pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
#[cfg(stm32h7)]
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Ckpersel as PerClockSource, Fdcansel as FdCanClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
}; };
use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre}; use crate::pac::rcc::vals::{Pllrge, Pllvcosel, Timpre};
use crate::pac::{FLASH, PWR, RCC}; use crate::pac::{FLASH, PWR, RCC};
use crate::time::Hertz; use crate::time::Hertz;
@ -194,16 +189,15 @@ pub struct Config {
#[cfg(stm32h7)] #[cfg(stm32h7)]
pub apb4_pre: APBPrescaler, pub apb4_pre: APBPrescaler,
pub per_clock_source: PerClockSource,
pub adc_clock_source: AdcClockSource,
pub fdcan_clock_source: FdCanClockSource,
pub timer_prescaler: TimerPrescaler, pub timer_prescaler: TimerPrescaler,
pub voltage_scale: VoltageScale, pub voltage_scale: VoltageScale,
pub ls: super::LsConfig, pub ls: super::LsConfig,
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))] #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
pub supply_config: SupplyConfig, pub supply_config: SupplyConfig,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -227,21 +221,14 @@ impl Default for Config {
#[cfg(stm32h7)] #[cfg(stm32h7)]
apb4_pre: APBPrescaler::DIV1, apb4_pre: APBPrescaler::DIV1,
per_clock_source: PerClockSource::HSI,
#[cfg(stm32h5)]
adc_clock_source: AdcClockSource::HCLK1,
#[cfg(stm32h7)]
adc_clock_source: AdcClockSource::PER,
fdcan_clock_source: FdCanClockSource::from_bits(0), // HSE
timer_prescaler: TimerPrescaler::DefaultX2, timer_prescaler: TimerPrescaler::DefaultX2,
voltage_scale: VoltageScale::Scale0, voltage_scale: VoltageScale::Scale0,
ls: Default::default(), ls: Default::default(),
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))] #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
supply_config: SupplyConfig::Default, supply_config: SupplyConfig::Default,
mux: Default::default(),
} }
} }
} }
@ -504,31 +491,6 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32h7)] #[cfg(stm32h7)]
assert!(apb4 <= pclk_max); assert!(apb4 <= pclk_max);
let _per_ck = match config.per_clock_source {
Ckpersel::HSI => hsi,
Ckpersel::CSI => csi,
Ckpersel::HSE => hse,
_ => unreachable!(),
};
#[cfg(stm32h7)]
let adc = match config.adc_clock_source {
AdcClockSource::PLL2_P => pll2.p,
AdcClockSource::PLL3_R => pll3.r,
AdcClockSource::PER => _per_ck,
_ => unreachable!(),
};
#[cfg(stm32h5)]
let adc = match config.adc_clock_source {
AdcClockSource::HCLK1 => Some(hclk),
AdcClockSource::SYS => Some(sys),
AdcClockSource::PLL2_R => pll2.r,
AdcClockSource::HSE => hse,
AdcClockSource::HSI => hsi,
AdcClockSource::CSI => csi,
_ => unreachable!(),
};
flash_setup(hclk, config.voltage_scale); flash_setup(hclk, config.voltage_scale);
let rtc = config.ls.init(); let rtc = config.ls.init();
@ -550,16 +512,6 @@ pub(crate) unsafe fn init(config: Config) {
RCC.d3cfgr().modify(|w| { RCC.d3cfgr().modify(|w| {
w.set_d3ppre(config.apb4_pre); w.set_d3ppre(config.apb4_pre);
}); });
RCC.d1ccipr().modify(|w| {
w.set_ckpersel(config.per_clock_source);
});
RCC.d3ccipr().modify(|w| {
w.set_adcsel(config.adc_clock_source);
});
RCC.d2ccip1r().modify(|w| {
w.set_fdcansel(config.fdcan_clock_source);
});
} }
#[cfg(stm32h5)] #[cfg(stm32h5)]
{ {
@ -573,12 +525,6 @@ pub(crate) unsafe fn init(config: Config) {
w.set_ppre2(config.apb2_pre); w.set_ppre2(config.apb2_pre);
w.set_ppre3(config.apb3_pre); w.set_ppre3(config.apb3_pre);
}); });
RCC.ccipr5().modify(|w| {
w.set_ckpersel(config.per_clock_source);
w.set_adcdacsel(config.adc_clock_source);
w.set_fdcan12sel(config.fdcan_clock_source)
});
} }
RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into())); RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
@ -601,6 +547,8 @@ pub(crate) unsafe fn init(config: Config) {
while !pac::SYSCFG.cccsr().read().ready() {} while !pac::SYSCFG.cccsr().read().ready() {}
} }
config.mux.init();
set_clocks!( set_clocks!(
sys: Some(sys), sys: Some(sys),
hclk1: Some(hclk), hclk1: Some(hclk),
@ -614,7 +562,6 @@ pub(crate) unsafe fn init(config: Config) {
pclk4: Some(apb4), pclk4: Some(apb4),
pclk1_tim: Some(apb1_tim), pclk1_tim: Some(apb1_tim),
pclk2_tim: Some(apb2_tim), pclk2_tim: Some(apb2_tim),
adc: adc,
rtc: rtc, rtc: rtc,
hsi: hsi, hsi: hsi,
@ -646,7 +593,6 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32h5)] #[cfg(stm32h5)]
audioclk: None, audioclk: None,
per: None,
i2s_ckin: None, i2s_ckin: None,
); );
} }

View file

@ -1,10 +1,6 @@
#[cfg(any(stm32l0, stm32l1))] #[cfg(any(stm32l0, stm32l1))]
pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::regs::Cfgr; use crate::pac::rcc::regs::Cfgr;
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
#[cfg(any(stm32wb, stm32wl))] #[cfg(any(stm32wb, stm32wl))]
pub use crate::pac::rcc::vals::Hsepre as HsePrescaler; 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 Sysclk}; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as Sysclk};
@ -59,18 +55,14 @@ pub struct Config {
#[cfg(any(stm32wl, stm32wb))] #[cfg(any(stm32wl, stm32wb))]
pub shared_ahb_pre: AHBPrescaler, pub shared_ahb_pre: AHBPrescaler,
// muxes
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC // low speed LSI/LSE/RTC
pub ls: super::LsConfig, pub ls: super::LsConfig,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
pub adc_clock_source: AdcClockSource,
#[cfg(any(stm32l0, stm32l1))] #[cfg(any(stm32l0, stm32l1))]
pub voltage_scale: VoltageScale, pub voltage_scale: VoltageScale,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -95,13 +87,10 @@ impl Default for Config {
pllsai2: None, pllsai2: None,
#[cfg(crs)] #[cfg(crs)]
hsi48: Some(Default::default()), hsi48: Some(Default::default()),
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48,
ls: Default::default(), ls: Default::default(),
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
adc_clock_source: AdcClockSource::SYS,
#[cfg(any(stm32l0, stm32l1))] #[cfg(any(stm32l0, stm32l1))]
voltage_scale: VoltageScale::RANGE1, voltage_scale: VoltageScale::RANGE1,
mux: Default::default(),
} }
} }
} }
@ -118,7 +107,6 @@ pub const WPAN_DEFAULT: Config = Config {
hsi48: Some(super::Hsi48Config { sync_from_usb: false }), hsi48: Some(super::Hsi48Config { sync_from_usb: false }),
msi: None, msi: None,
hsi: false, hsi: false,
clk48_src: Clk48Src::PLL1_Q,
ls: super::LsConfig::default_lse(), ls: super::LsConfig::default_lse(),
@ -137,7 +125,8 @@ pub const WPAN_DEFAULT: Config = Config {
shared_ahb_pre: AHBPrescaler::DIV1, shared_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1,
adc_clock_source: AdcClockSource::SYS,
mux: super::mux::ClockMux::default(),
}; };
fn msi_enable(range: MSIRange) { fn msi_enable(range: MSIRange) {
@ -267,21 +256,6 @@ pub(crate) unsafe fn init(config: Config) {
Sysclk::PLL1_R => pll.r.unwrap(), Sysclk::PLL1_R => pll.r.unwrap(),
}; };
#[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 {
Clk48Src::HSI48 => hsi48,
Clk48Src::PLL1_VCO_DIV_2 => pll.clk48,
};
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let clk48 = match config.clk48_src {
Clk48Src::HSI48 => hsi48,
Clk48Src::MSI => msi,
Clk48Src::PLLSAI1_Q => pllsai1.q,
Clk48Src::PLL1_Q => pll.q,
};
#[cfg(rcc_l4plus)] #[cfg(rcc_l4plus)]
assert!(sys_clk.0 <= 120_000_000); assert!(sys_clk.0 <= 120_000_000);
#[cfg(all(stm32l4, not(rcc_l4plus)))] #[cfg(all(stm32l4, not(rcc_l4plus)))]
@ -357,9 +331,6 @@ pub(crate) unsafe fn init(config: Config) {
}); });
while RCC.cfgr().read().sws() != config.sys {} while RCC.cfgr().read().sws() != config.sys {}
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(any(stm32wl, stm32wb))] #[cfg(any(stm32wl, stm32wb))]
{ {
RCC.extcfgr().modify(|w| { RCC.extcfgr().modify(|w| {
@ -372,6 +343,8 @@ pub(crate) unsafe fn init(config: Config) {
while !RCC.extcfgr().read().c2hpref() {} while !RCC.extcfgr().read().c2hpref() {}
} }
config.mux.init();
set_clocks!( set_clocks!(
sys: Some(sys_clk), sys: Some(sys_clk),
hclk1: Some(hclk1), hclk1: Some(hclk1),
@ -388,10 +361,11 @@ pub(crate) unsafe fn init(config: Config) {
hsi: hsi, hsi: hsi,
hse: hse, hse: hse,
msi: msi, msi: msi,
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
clk48: clk48,
hsi48: hsi48, hsi48: hsi48,
#[cfg(any(stm32l0, stm32l1))]
pll1_vco_div_2: pll.vco.map(|c| c/2u32),
#[cfg(not(any(stm32l0, stm32l1)))] #[cfg(not(any(stm32l0, stm32l1)))]
pll1_p: pll.p, pll1_p: pll.p,
#[cfg(not(any(stm32l0, stm32l1)))] #[cfg(not(any(stm32l0, stm32l1)))]
@ -511,7 +485,7 @@ mod pll {
#[derive(Default)] #[derive(Default)]
pub(super) struct PllOutput { pub(super) struct PllOutput {
pub r: Option<Hertz>, pub r: Option<Hertz>,
pub clk48: Option<Hertz>, pub vco: Option<Hertz>,
} }
pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
@ -528,7 +502,6 @@ mod pll {
let vco_freq = pll_src * pll.mul; let vco_freq = pll_src * pll.mul;
let r = vco_freq / pll.div; let r = vco_freq / pll.div;
let clk48 = (vco_freq == Hertz(96_000_000)).then_some(Hertz(48_000_000));
assert!(r <= Hertz(32_000_000)); assert!(r <= Hertz(32_000_000));
@ -541,7 +514,10 @@ mod pll {
// Enable PLL // Enable PLL
pll_enable(instance, true); pll_enable(instance, true);
PllOutput { r: Some(r), clk48 } PllOutput {
r: Some(r),
vco: Some(vco_freq),
}
} }
} }

View file

@ -31,9 +31,7 @@ mod _version;
pub use _version::*; pub use _version::*;
#[cfg(clock_mux)] pub use crate::_generated::{mux, Clocks};
pub use crate::_generated::mux;
pub use crate::_generated::Clocks;
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
/// Must be written within a critical section /// Must be written within a critical section

View file

@ -85,6 +85,9 @@ pub struct Config {
/// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits. /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits.
pub voltage_range: VoltageScale, pub voltage_range: VoltageScale,
pub ls: super::LsConfig, pub ls: super::LsConfig,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -104,6 +107,7 @@ impl Default for Config {
apb3_pre: APBPrescaler::DIV1, apb3_pre: APBPrescaler::DIV1,
voltage_range: VoltageScale::RANGE1, voltage_range: VoltageScale::RANGE1,
ls: Default::default(), ls: Default::default(),
mux: Default::default(),
} }
} }
} }
@ -259,6 +263,8 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init(); let rtc = config.ls.init();
config.mux.init();
set_clocks!( set_clocks!(
sys: Some(sys_clk), sys: Some(sys_clk),
hclk1: Some(hclk), hclk1: Some(hclk),
@ -289,7 +295,6 @@ pub(crate) unsafe fn init(config: Config) {
lse: None, lse: None,
lsi: None, lsi: None,
msik: None, msik: None,
iclk: None,
shsi: None, shsi: None,
shsi_div_2: None, shsi_div_2: None,
); );

View file

@ -1,8 +1,6 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::regs::Cfgr1; use crate::pac::rcc::regs::Cfgr1;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk};
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk,
};
use crate::pac::{FLASH, RCC}; use crate::pac::{FLASH, RCC};
use crate::time::Hertz; use crate::time::Hertz;
@ -32,9 +30,10 @@ pub struct Config {
// low speed LSI/LSE/RTC // low speed LSI/LSE/RTC
pub ls: super::LsConfig, pub ls: super::LsConfig,
pub adc_clock_source: AdcClockSource,
pub voltage_scale: VoltageScale, pub voltage_scale: VoltageScale,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
} }
impl Default for Config { impl Default for Config {
@ -49,8 +48,8 @@ impl Default for Config {
apb2_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1,
apb7_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1,
ls: Default::default(), ls: Default::default(),
adc_clock_source: AdcClockSource::HCLK4,
voltage_scale: VoltageScale::RANGE2, voltage_scale: VoltageScale::RANGE2,
mux: Default::default(),
} }
} }
} }
@ -152,7 +151,7 @@ pub(crate) unsafe fn init(config: Config) {
w.set_ppre2(config.apb2_pre); w.set_ppre2(config.apb2_pre);
}); });
RCC.ccipr3().modify(|w| w.set_adcsel(config.adc_clock_source)); config.mux.init();
set_clocks!( set_clocks!(
sys: Some(sys_clk), sys: Some(sys_clk),

View file

@ -606,13 +606,6 @@ impl<'d, T: Instance> Bus<'d, T> {
// Wait for USB power to stabilize // Wait for USB power to stabilize
while !crate::pac::PWR.cr3().read().usb33rdy() {} while !crate::pac::PWR.cr3().read().usb33rdy() {}
// Use internal 48MHz HSI clock. Should be enabled in RCC by default.
critical_section::with(|_| {
crate::pac::RCC
.d2ccip2r()
.modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48))
});
// Enable ULPI clock if external PHY is used // Enable ULPI clock if external PHY is used
let ulpien = !self.phy_type.internal(); let ulpien = !self.phy_type.internal();
critical_section::with(|_| { critical_section::with(|_| {
@ -645,13 +638,6 @@ impl<'d, T: Instance> Bus<'d, T> {
// Wait for USB power to stabilize // Wait for USB power to stabilize
while !crate::pac::PWR.svmsr().read().vddusbrdy() {} while !crate::pac::PWR.svmsr().read().vddusbrdy() {}
// Select HSI48 as USB clock source.
critical_section::with(|_| {
crate::pac::RCC.ccipr1().modify(|w| {
w.set_iclksel(crate::pac::rcc::vals::Iclksel::HSI48);
})
});
} }
<T as RccPeripheral>::enable_and_reset(); <T as RccPeripheral>::enable_and_reset();

View file

@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) {
config.rcc.apb1_pre = APBPrescaler::DIV2; config.rcc.apb1_pre = APBPrescaler::DIV2;
config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1;
config.rcc.mux.hrtim1sw = Some(embassy_stm32::rcc::mux::Timsw::PLL1_P); config.rcc.mux.hrtim1sw = embassy_stm32::rcc::mux::Timsw::PLL1_P;
} }
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);

View file

@ -4,37 +4,35 @@
use defmt::info; use defmt::info;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::gpio::OutputType; use embassy_stm32::gpio::OutputType;
use embassy_stm32::pac::rcc::vals::Tim1sel;
use embassy_stm32::rcc::{Config as RccConfig, PllConfig, PllSource, Pllm, Plln, Pllq, Pllr, Sysclk};
use embassy_stm32::time::khz; use embassy_stm32::time::khz;
use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
use embassy_stm32::timer::simple_pwm::PwmPin; use embassy_stm32::timer::simple_pwm::PwmPin;
use embassy_stm32::timer::Channel; use embassy_stm32::timer::Channel;
use embassy_stm32::{pac, Config as PeripheralConfig}; use embassy_stm32::Config as PeripheralConfig;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut rcc_config = RccConfig::default(); let mut config = PeripheralConfig::default();
rcc_config.sys = Sysclk::PLL(PllConfig { {
source: PllSource::HSI, use embassy_stm32::rcc::*;
m: Pllm::DIV1,
n: Plln::MUL16,
r: Pllr::DIV4, // CPU clock comes from PLLR (HSI (16MHz) / 1 * 16 / 4 = 64MHz)
q: Some(Pllq::DIV2), // TIM1 or TIM15 can be sourced from PLLQ (HSI (16MHz) / 1 * 16 / 2 = 128MHz)
p: None,
});
let mut peripheral_config = PeripheralConfig::default(); config.rcc.sys = Sysclk::PLL(PllConfig {
peripheral_config.rcc = rcc_config; source: PllSource::HSI,
m: Pllm::DIV1,
n: Plln::MUL16,
r: Pllr::DIV4, // CPU clock comes from PLLR (HSI (16MHz) / 1 * 16 / 4 = 64MHz)
q: Some(Pllq::DIV2), // TIM1 or TIM15 can be sourced from PLLQ (HSI (16MHz) / 1 * 16 / 2 = 128MHz)
p: None,
});
let p = embassy_stm32::init(peripheral_config); // configure TIM1 mux to select PLLQ as clock source
// https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
// configure TIM1 mux to select PLLQ as clock source // RM0444 page 210
// https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf // RCC - Peripherals Independent Clock Control Register - bit 22 -> 1
// RM0444 page 210 config.rcc.mux.tim1sel = embassy_stm32::rcc::mux::Tim1sel::PLL1_Q;
// RCC - Peripherals Independent Clock Control Register - bit 22 -> 1 }
pac::RCC.ccipr().modify(|w| w.set_tim1sel(Tim1sel::PLL1_Q)); let p = embassy_stm32::init(config);
let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull); let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);

View file

@ -4,7 +4,6 @@
use defmt::{panic, *}; use defmt::{panic, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_futures::join::join; use embassy_futures::join::join;
use embassy_stm32::rcc::{Hsi48Config, UsbSrc};
use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::usb::{Driver, Instance};
use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
@ -19,10 +18,11 @@ bind_interrupts!(struct Irqs {
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.usb_src = Some(UsbSrc::Hsi48(Hsi48Config { {
sync_from_usb: true, use embassy_stm32::rcc::*;
..Default::default() config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true });
})); config.rcc.mux.usbsel = mux::Usbsel::HSI48;
}
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View file

@ -4,7 +4,6 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::adc::{Adc, SampleTime};
use embassy_stm32::rcc::{AdcClockSource, Pll, PllMul, PllPreDiv, PllRDiv, Pllsrc, Sysclk};
use embassy_stm32::Config; use embassy_stm32::Config;
use embassy_time::{Delay, Timer}; use embassy_time::{Delay, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -12,20 +11,20 @@ use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{
config.rcc.pll = Some(Pll { use embassy_stm32::rcc::*;
source: Pllsrc::HSI, config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV4, source: Pllsrc::HSI,
mul: PllMul::MUL85, prediv: PllPreDiv::DIV4,
divp: None, mul: PllMul::MUL85,
divq: None, divp: None,
// Main system clock at 170 MHz divq: None,
divr: Some(PllRDiv::DIV2), // Main system clock at 170 MHz
}); divr: Some(PllRDiv::DIV2),
});
config.rcc.adc12_clock_source = AdcClockSource::SYS; config.rcc.mux.adc12sel = mux::Adcsel::SYS;
config.rcc.sys = Sysclk::PLL1_R; config.rcc.sys = Sysclk::PLL1_R;
}
let mut p = embassy_stm32::init(config); let mut p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View file

@ -3,6 +3,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::peripherals::*; use embassy_stm32::peripherals::*;
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, can, Config}; use embassy_stm32::{bind_interrupts, can, Config};
use embassy_time::Timer; use embassy_time::Timer;
use static_cell::StaticCell; use static_cell::StaticCell;
@ -15,8 +16,24 @@ bind_interrupts!(struct Irqs {
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let config = Config::default(); let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(24_000_000),
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: Pllsrc::HSE,
prediv: PllPreDiv::DIV6,
mul: PllMul::MUL85,
divp: None,
divq: Some(PllQDiv::DIV8), // 42.5 Mhz for fdcan.
divr: Some(PllRDiv::DIV2), // Main system clock at 170 MHz
});
config.rcc.mux.fdcansel = mux::Fdcansel::PLL1_Q;
config.rcc.sys = Sysclk::PLL1_R;
}
let peripherals = embassy_stm32::init(config); let peripherals = embassy_stm32::init(config);
let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs); let mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);

View file

@ -12,6 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: Pllsrc::HSI, source: Pllsrc::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,

View file

@ -3,9 +3,6 @@
use defmt::{panic, *}; use defmt::{panic, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{
Clk48Src, Hse, HseMode, Hsi48Config, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, Pllsrc, Sysclk,
};
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::usb::{self, Driver, Instance}; use embassy_stm32::usb::{self, Driver, Instance};
use embassy_stm32::{bind_interrupts, peripherals, Config}; use embassy_stm32::{bind_interrupts, peripherals, Config};
@ -22,38 +19,27 @@ bind_interrupts!(struct Irqs {
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. use embassy_stm32::rcc::*;
const USE_HSI48: bool = true;
let plldivq = if USE_HSI48 { None } else { Some(PllQDiv::DIV6) };
config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000),
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: Pllsrc::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL72,
divp: None,
divq: plldivq,
// Main system clock at 144 MHz
divr: Some(PllRDiv::DIV2),
});
config.rcc.sys = Sysclk::PLL1_R;
config.rcc.boost = true; // BOOST!
if USE_HSI48 {
// Sets up the Clock Recovery System (CRS) to use the USB SOF to trim the HSI48 oscillator. // Sets up the Clock Recovery System (CRS) to use the USB SOF to trim the HSI48 oscillator.
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true });
config.rcc.clk48_src = Clk48Src::HSI48; config.rcc.hse = Some(Hse {
} else { freq: Hertz(8_000_000),
config.rcc.clk48_src = Clk48Src::PLL1_Q; mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: Pllsrc::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL72,
divp: None,
divq: Some(PllQDiv::DIV6), // 48mhz
divr: Some(PllRDiv::DIV2), // Main system clock at 144 MHz
});
config.rcc.sys = Sysclk::PLL1_R;
config.rcc.boost = true; // BOOST!
config.rcc.mux.clk48sel = mux::Clk48sel::HSI48;
//config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; // uncomment to use PLL1_Q instead.
} }
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View file

@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
freq: embassy_stm32::time::Hertz(25_000_000), freq: embassy_stm32::time::Hertz(25_000_000),
mode: rcc::HseMode::Oscillator, mode: rcc::HseMode::Oscillator,
}); });
config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; config.rcc.mux.fdcan12sel = rcc::mux::Fdcansel::HSE;
let peripherals = embassy_stm32::init(config); let peripherals = embassy_stm32::init(config);

View file

@ -5,7 +5,7 @@ use defmt::{panic, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::usb::{Driver, Instance};
use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError; use embassy_usb::driver::EndpointError;
use embassy_usb::Builder; use embassy_usb::Builder;
@ -41,15 +41,12 @@ async fn main(_spawner: Spawner) {
config.rcc.apb3_pre = APBPrescaler::DIV4; config.rcc.apb3_pre = APBPrescaler::DIV4;
config.rcc.sys = Sysclk::PLL1_P; config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
config.rcc.mux.usbsel = mux::Usbsel::HSI48;
} }
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");
pac::RCC.ccipr4().write(|w| {
w.set_usbsel(pac::rcc::vals::Usbsel::HSI48);
});
// Create the driver, from the HAL. // Create the driver, from the HAL.
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);

View file

@ -38,7 +38,7 @@ async fn main(_spawner: Spawner) {
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale1; config.rcc.voltage_scale = VoltageScale::Scale1;
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.mux.adcsel = mux::Adcsel::PLL2_P;
} }
let mut p = embassy_stm32::init(config); let mut p = embassy_stm32::init(config);

View file

@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
freq: embassy_stm32::time::Hertz(25_000_000), freq: embassy_stm32::time::Hertz(25_000_000),
mode: rcc::HseMode::Oscillator, mode: rcc::HseMode::Oscillator,
}); });
config.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; config.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
let peripherals = embassy_stm32::init(config); let peripherals = embassy_stm32::init(config);

View file

@ -40,7 +40,7 @@ fn main() -> ! {
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale1; config.rcc.voltage_scale = VoltageScale::Scale1;
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.mux.adcsel = mux::Adcsel::PLL2_P;
} }
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);

View file

@ -42,7 +42,7 @@ async fn main(spawner: Spawner) {
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale1; config.rcc.voltage_scale = VoltageScale::Scale1;
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.mux.adcsel = mux::Adcsel::PLL2_P;
} }
// Initialize the board and obtain a Peripherals instance // Initialize the board and obtain a Peripherals instance

View file

@ -3,7 +3,7 @@
use defmt::*; use defmt::*;
use embassy_stm32::adc::{Adc, Resolution}; use embassy_stm32::adc::{Adc, Resolution};
use embassy_stm32::pac; use embassy_stm32::Config;
use embassy_time::Delay; use embassy_time::Delay;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -11,12 +11,12 @@ use {defmt_rtt as _, panic_probe as _};
fn main() -> ! { fn main() -> ! {
info!("Hello World!"); info!("Hello World!");
pac::RCC.ccipr().modify(|w| { let mut config = Config::default();
w.set_adcsel(pac::rcc::vals::Adcsel::SYS); {
}); use embassy_stm32::rcc::*;
pac::RCC.ahb2enr().modify(|w| w.set_adcen(true)); config.rcc.mux.adcsel = mux::Adcsel::SYS;
}
let p = embassy_stm32::init(Default::default()); let p = embassy_stm32::init(config);
let mut adc = Adc::new(p.ADC1, &mut Delay); let mut adc = Adc::new(p.ADC1, &mut Delay);
//adc.enable_vref(); //adc.enable_vref();

View file

@ -33,7 +33,7 @@ fn options() -> TestOptions {
freq: embassy_stm32::time::Hertz(25_000_000), freq: embassy_stm32::time::Hertz(25_000_000),
mode: rcc::HseMode::Oscillator, mode: rcc::HseMode::Oscillator,
}); });
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
TestOptions { TestOptions {
config: c, config: c,
max_latency: Duration::from_micros(1200), max_latency: Duration::from_micros(1200),
@ -50,7 +50,7 @@ fn options() -> TestOptions {
freq: embassy_stm32::time::Hertz(25_000_000), freq: embassy_stm32::time::Hertz(25_000_000),
mode: rcc::HseMode::Oscillator, mode: rcc::HseMode::Oscillator,
}); });
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE; c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
TestOptions { TestOptions {
config: c, config: c,
max_latency: Duration::from_micros(1200), max_latency: Duration::from_micros(1200),

View file

@ -2,6 +2,8 @@
pub use defmt::*; pub use defmt::*;
#[allow(unused)] #[allow(unused)]
use embassy_stm32::rcc::*;
#[allow(unused)]
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::Config; use embassy_stm32::Config;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -265,7 +267,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32f091rc")] #[cfg(feature = "stm32f091rc")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
@ -281,7 +282,6 @@ pub fn config() -> Config {
} }
#[cfg(feature = "stm32f103c8")] #[cfg(feature = "stm32f103c8")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Oscillator, mode: HseMode::Oscillator,
@ -298,7 +298,6 @@ pub fn config() -> Config {
} }
#[cfg(feature = "stm32f207zg")] #[cfg(feature = "stm32f207zg")]
{ {
use embassy_stm32::rcc::*;
// By default, HSE on the board comes from a 8 MHz clock signal (not a crystal) // By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
@ -327,7 +326,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32f303ze")] #[cfg(feature = "stm32f303ze")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
@ -345,7 +343,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32f429zi")] #[cfg(feature = "stm32f429zi")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
@ -366,7 +363,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32f446re")] #[cfg(feature = "stm32f446re")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Oscillator, mode: HseMode::Oscillator,
@ -387,7 +383,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32f767zi")] #[cfg(feature = "stm32f767zi")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(8_000_000), freq: Hertz(8_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
@ -408,7 +403,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32h563zi")] #[cfg(feature = "stm32h563zi")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = None; config.rcc.hsi = None;
config.rcc.hsi48 = Some(Default::default()); // needed for RNG config.rcc.hsi48 = Some(Default::default()); // needed for RNG
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
@ -433,7 +427,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32h503rb")] #[cfg(feature = "stm32h503rb")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = None; config.rcc.hsi = None;
config.rcc.hsi48 = Some(Default::default()); // needed for RNG config.rcc.hsi48 = Some(Default::default()); // needed for RNG
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
@ -456,9 +449,26 @@ pub fn config() -> Config {
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
} }
#[cfg(feature = "stm32g491re")]
{
config.rcc.hse = Some(Hse {
freq: Hertz(24_000_000),
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: Pllsrc::HSE,
prediv: PllPreDiv::DIV6,
mul: PllMul::MUL85,
divp: None,
divq: Some(PllQDiv::DIV8), // 42.5 Mhz for fdcan.
divr: Some(PllRDiv::DIV2), // Main system clock at 170 MHz
});
config.rcc.mux.fdcansel = mux::Fdcansel::PLL1_Q;
config.rcc.sys = Sysclk::PLL1_R;
}
#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = Some(Default::default()); // needed for RNG config.rcc.hsi48 = Some(Default::default()); // needed for RNG
@ -485,7 +495,7 @@ pub fn config() -> Config {
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.voltage_scale = VoltageScale::Scale1; config.rcc.voltage_scale = VoltageScale::Scale1;
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.mux.adcsel = mux::Adcsel::PLL2_P;
#[cfg(any(feature = "stm32h755zi"))] #[cfg(any(feature = "stm32h755zi"))]
{ {
config.rcc.supply_config = SupplyConfig::DirectSMPS; config.rcc.supply_config = SupplyConfig::DirectSMPS;
@ -494,7 +504,6 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32h7a3zi"))] #[cfg(any(feature = "stm32h7a3zi"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = Some(Default::default()); // needed for RNG config.rcc.hsi48 = Some(Default::default()); // needed for RNG
@ -521,12 +530,11 @@ pub fn config() -> Config {
config.rcc.apb3_pre = APBPrescaler::DIV2; // 140 Mhz config.rcc.apb3_pre = APBPrescaler::DIV2; // 140 Mhz
config.rcc.apb4_pre = APBPrescaler::DIV2; // 140 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 140 Mhz
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.mux.adcsel = mux::Adcsel::PLL2_P;
} }
#[cfg(any(feature = "stm32l496zg", feature = "stm32l4a6zg", feature = "stm32l4r5zi"))] #[cfg(any(feature = "stm32l496zg", feature = "stm32l4a6zg", feature = "stm32l4r5zi"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.sys = Sysclk::PLL1_R; config.rcc.sys = Sysclk::PLL1_R;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
@ -541,7 +549,6 @@ pub fn config() -> Config {
#[cfg(feature = "stm32wl55jc")] #[cfg(feature = "stm32wl55jc")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000), freq: Hertz(32_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
@ -560,7 +567,6 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32l552ze"))] #[cfg(any(feature = "stm32l552ze"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.sys = Sysclk::PLL1_R; config.rcc.sys = Sysclk::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
@ -576,7 +582,6 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32u585ai", feature = "stm32u5a5zj"))] #[cfg(any(feature = "stm32u585ai", feature = "stm32u5a5zj"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI, // 16 MHz source: PllSource::HSI, // 16 MHz
@ -593,17 +598,12 @@ pub fn config() -> Config {
#[cfg(feature = "stm32wba52cg")] #[cfg(feature = "stm32wba52cg")]
{ {
use embassy_stm32::rcc::*;
config.rcc.sys = Sysclk::HSI; config.rcc.sys = Sysclk::HSI;
config.rcc.mux.rngsel = mux::Rngsel::HSI;
embassy_stm32::pac::RCC.ccipr2().write(|w| {
w.set_rngsel(embassy_stm32::pac::rcc::vals::Rngsel::HSI);
});
} }
#[cfg(feature = "stm32l073rz")] #[cfg(feature = "stm32l073rz")]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PllSource::HSI, source: PllSource::HSI,
@ -615,7 +615,6 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32l152re"))] #[cfg(any(feature = "stm32l152re"))]
{ {
use embassy_stm32::rcc::*;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PllSource::HSI, source: PllSource::HSI,