mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
stm32: autogenerate mux config for all chips.
This commit is contained in:
parent
d5c9c611fa
commit
95234cddba
@ -70,7 +70,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-d7462d805ef05892531a83cd9ad60c9cba568d54" }
|
||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e853cf944b150898312984d092d63926970c340d" }
|
||||
vcell = "0.1.3"
|
||||
bxcan = "0.7.0"
|
||||
nb = "1.0.0"
|
||||
@ -94,7 +94,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-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]
|
||||
|
@ -5,7 +5,9 @@ use std::{env, fs};
|
||||
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
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() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
@ -374,12 +376,130 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let force_refcount = HashSet::from(["usart"]);
|
||||
let mut refcount_statics = BTreeSet::new();
|
||||
struct ClockGen<'a> {
|
||||
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 {
|
||||
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 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 refcount_static =
|
||||
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! {
|
||||
@ -442,63 +562,12 @@ fn main() {
|
||||
};
|
||||
|
||||
let clock_frequency = match &rcc.kernel_clock {
|
||||
PeripheralRccKernelClock::Mux(mux) => {
|
||||
let ir = &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);
|
||||
|
||||
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() }
|
||||
}
|
||||
}
|
||||
PeripheralRccKernelClock::Mux(mux) => clock_gen.gen_mux(mux),
|
||||
PeripheralRccKernelClock::Clock(clock) => clock_gen.gen_clock(clock),
|
||||
};
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
// 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 {
|
||||
StopMode::Standby => None,
|
||||
StopMode::Stop2 => Some(quote! { REFCOUNT_STOP2 }),
|
||||
@ -543,74 +612,79 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
if !rcc_cfgr_regs.is_empty() {
|
||||
println!("cargo:rustc-cfg=clock_mux");
|
||||
let struct_fields: Vec<_> = clock_gen
|
||||
.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()
|
||||
.map(|(_fieldset, fieldname, enum_name)| {
|
||||
quote! {
|
||||
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)| {
|
||||
.filter(|(f, _, _)| f == fieldset)
|
||||
.map(|(_, fieldname, _)| {
|
||||
let setter = format_ident!("set_{}", fieldname);
|
||||
quote! {
|
||||
match self.#fieldname {
|
||||
None => {}
|
||||
Some(val) => {
|
||||
crate::pac::RCC.#fieldset()
|
||||
.modify(|w| w.#setter(val));
|
||||
}
|
||||
};
|
||||
w.#setter(self.#fieldname);
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let enum_names: BTreeSet<_> = rcc_cfgr_regs
|
||||
.iter()
|
||||
.map(|(_fieldset, _fieldname, 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 Default for ClockMux {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#( #field_names: None, )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClockMux {
|
||||
pub fn init(self) {
|
||||
#( #inits )*
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
inits.extend(quote! {
|
||||
crate::pac::RCC.#fieldset().modify(|w| {
|
||||
#(#setters)*
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
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();
|
||||
clock_gen.clock_names.insert("sys".to_string());
|
||||
clock_gen.clock_names.insert("rtc".to_string());
|
||||
let clock_idents: Vec<_> = clock_gen.clock_names.iter().map(|n| format_ident!("{}", n)).collect();
|
||||
g.extend(quote! {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[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()
|
||||
.map(|refcount_static| {
|
||||
quote! {
|
||||
|
@ -7,7 +7,6 @@ use core::task::Poll;
|
||||
use self::sealed::Instance;
|
||||
use crate::interrupt;
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::pac::rcc::vals::{Lptim1sel, Lptim2sel};
|
||||
use crate::peripherals::IPCC;
|
||||
use crate::rcc::sealed::RccPeripheral;
|
||||
|
||||
@ -105,7 +104,8 @@ impl Ipcc {
|
||||
IPCC::enable_and_reset();
|
||||
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();
|
||||
|
||||
@ -271,18 +271,3 @@ pub(crate) mod sealed {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ pub struct Config {
|
||||
pub ahb_pre: AHBPrescaler,
|
||||
pub apb_pre: APBPrescaler,
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -31,6 +34,7 @@ impl Default for Config {
|
||||
ahb_pre: AHBPrescaler::DIV1,
|
||||
apb_pre: APBPrescaler::DIV1,
|
||||
ls: Default::default(),
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,28 +101,25 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
|
||||
if !set_flash_latency_after {
|
||||
// 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
|
||||
let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
|
||||
RCC.cfgr().modify(|w| {
|
||||
w.set_sw(sw);
|
||||
w.set_hpre(hpre);
|
||||
w.set_ppre(ppre);
|
||||
w.set_hpre(config.ahb_pre);
|
||||
w.set_ppre(config.apb_pre);
|
||||
});
|
||||
|
||||
if set_flash_latency_after {
|
||||
// We can make the flash require fewer wait states
|
||||
// Spin until the SYSCLK changes have taken effect
|
||||
loop {
|
||||
let cfgr = RCC.cfgr().read();
|
||||
if cfgr.sw() == sw && cfgr.hpre() == hpre && cfgr.ppre() == ppre {
|
||||
break;
|
||||
}
|
||||
// Spin until the SYSCLK changes have taken effect
|
||||
loop {
|
||||
let cfgr = RCC.cfgr().read();
|
||||
if cfgr.sw() == sw && cfgr.hpre() == config.ahb_pre && cfgr.ppre() == config.apb_pre {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -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!(
|
||||
hsi: None,
|
||||
lse: None,
|
||||
|
@ -98,8 +98,8 @@ pub struct Config {
|
||||
#[cfg(all(stm32f3, not(rcc_f37), adc3_common))]
|
||||
pub adc34: AdcClockSource,
|
||||
|
||||
#[cfg(clock_mux)]
|
||||
pub mux: crate::rcc::mux::ClockMux,
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
|
||||
pub ls: super::LsConfig,
|
||||
}
|
||||
@ -128,7 +128,6 @@ impl Default for Config {
|
||||
#[cfg(all(stm32f3, not(rcc_f37), adc3_common))]
|
||||
adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
|
||||
|
||||
#[cfg(clock_mux)]
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
@ -370,7 +369,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
};
|
||||
*/
|
||||
|
||||
#[cfg(clock_mux)]
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
|
@ -95,6 +95,9 @@ pub struct Config {
|
||||
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
|
||||
#[cfg(stm32f2)]
|
||||
pub voltage: VoltageScale,
|
||||
}
|
||||
@ -120,6 +123,7 @@ impl Default for Config {
|
||||
|
||||
#[cfg(stm32f2)]
|
||||
voltage: VoltageScale::Range3,
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -256,6 +260,8 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
});
|
||||
while RCC.cfgr().read().sws() != config.sys {}
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
hsi: hsi,
|
||||
hse: hse,
|
||||
@ -286,7 +292,9 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
#[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
|
||||
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_hse: None,
|
||||
|
@ -71,22 +71,6 @@ pub enum PllSource {
|
||||
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
|
||||
pub struct Config {
|
||||
pub sys: Sysclk,
|
||||
@ -94,8 +78,10 @@ pub struct Config {
|
||||
pub apb_pre: APBPrescaler,
|
||||
pub low_power_run: bool,
|
||||
pub ls: super::LsConfig,
|
||||
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))]
|
||||
pub usb_src: Option<UsbSrc>,
|
||||
#[cfg(crs)]
|
||||
pub hsi48: Option<super::Hsi48Config>,
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -107,8 +93,9 @@ impl Default for Config {
|
||||
apb_pre: APBPrescaler::DIV1,
|
||||
low_power_run: false,
|
||||
ls: Default::default(),
|
||||
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))]
|
||||
usb_src: None,
|
||||
#[cfg(crs)]
|
||||
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 hse_freq = (sw == Sw::HSE).then_some(sys_clk);
|
||||
|
||||
#[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))]
|
||||
let hsi48_freq = config.usb_src.and_then(|config| {
|
||||
match config {
|
||||
UsbSrc::PllQ => {
|
||||
// Make sure the PLLQ is enabled and running at 48Mhz
|
||||
assert!(pll1_q_freq.is_some() && pll1_q_freq.unwrap().0 == 48_000_000);
|
||||
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;
|
||||
#[cfg(crs)]
|
||||
let hsi48 = config.hsi48.map(super::init_hsi48);
|
||||
#[cfg(not(crs))]
|
||||
let hsi48: Option<Hertz> = None;
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys_clk),
|
||||
@ -357,7 +322,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
pclk1: Some(apb_freq),
|
||||
pclk1_tim: Some(apb_tim_freq),
|
||||
hsi: hsi_freq,
|
||||
hsi48: hsi48_freq,
|
||||
hsi48: hsi48,
|
||||
hsi_div_8: hsi_div_8_freq,
|
||||
hse: hse_freq,
|
||||
lse: lse_freq,
|
||||
|
@ -1,11 +1,10 @@
|
||||
use stm32_metapac::flash::vals::Latency;
|
||||
use stm32_metapac::rcc::vals::{Adcsel, Sw};
|
||||
use stm32_metapac::rcc::vals::Sw;
|
||||
use stm32_metapac::FLASH;
|
||||
|
||||
pub use crate::pac::rcc::vals::{
|
||||
Adcsel as AdcClockSource, Clk48sel as Clk48Src, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler,
|
||||
Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc, Ppre as APBPrescaler,
|
||||
Sw as Sysclk,
|
||||
Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc,
|
||||
Ppre as APBPrescaler, Sw as Sysclk,
|
||||
};
|
||||
use crate::pac::{PWR, RCC};
|
||||
use crate::time::Hertz;
|
||||
@ -82,24 +81,15 @@ pub struct Config {
|
||||
|
||||
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
|
||||
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
|
||||
/// Recommended when the SYSCLK frequency is greater than 150MHz.
|
||||
pub boost: bool,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -115,12 +105,9 @@ impl Default for Config {
|
||||
apb1_pre: APBPrescaler::DIV1,
|
||||
apb2_pre: APBPrescaler::DIV1,
|
||||
low_power_run: false,
|
||||
clk48_src: Clk48Src::HSI48,
|
||||
ls: Default::default(),
|
||||
adc12_clock_source: Adcsel::DISABLE,
|
||||
adc345_clock_source: Adcsel::DISABLE,
|
||||
fdcan_clock_source: FdCanClockSource::PCLK1,
|
||||
boost: false,
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,9 +152,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
};
|
||||
|
||||
// Configure HSI48 if required
|
||||
if let Some(hsi48_config) = config.hsi48 {
|
||||
super::init_hsi48(hsi48_config);
|
||||
}
|
||||
let hsi48 = config.hsi48.map(super::init_hsi48);
|
||||
|
||||
let pll_freq = config.pll.map(|pll_config| {
|
||||
let src_freq = match pll_config.source {
|
||||
@ -176,13 +161,13 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(max::PLL_IN.contains(&src_freq));
|
||||
|
||||
// Disable PLL before configuration
|
||||
RCC.cr().modify(|w| w.set_pllon(false));
|
||||
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));
|
||||
|
||||
@ -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 (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 they‘re 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 {
|
||||
assert!(sys_clk <= Hertz(2_000_000));
|
||||
PWR.cr1().modify(|w| w.set_lpr(true));
|
||||
@ -344,6 +293,8 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
|
||||
let rtc = config.ls.init();
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys_clk),
|
||||
hclk1: Some(hclk),
|
||||
@ -353,12 +304,11 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
pclk1_tim: Some(apb1_tim_freq),
|
||||
pclk2: Some(apb2_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_q: pll_freq.as_ref().and_then(|pll| pll.pll_q),
|
||||
pll1_r: pll_freq.as_ref().and_then(|pll| pll.pll_r),
|
||||
hse: hse,
|
||||
hsi48: hsi48,
|
||||
rtc: rtc,
|
||||
);
|
||||
}
|
||||
|
@ -2,15 +2,10 @@ use core::ops::RangeInclusive;
|
||||
|
||||
use crate::pac;
|
||||
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::{
|
||||
Ckpersel as PerClockSource, Fdcansel as FdCanClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv,
|
||||
Pllm as PllPreDiv, Plln as PllMul, Pllsrc as PllSource, Sw as Sysclk,
|
||||
Hsidiv as HSIPrescaler, Plldiv as PllDiv, 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::time::Hertz;
|
||||
|
||||
@ -194,16 +189,15 @@ pub struct Config {
|
||||
#[cfg(stm32h7)]
|
||||
pub apb4_pre: APBPrescaler,
|
||||
|
||||
pub per_clock_source: PerClockSource,
|
||||
pub adc_clock_source: AdcClockSource,
|
||||
pub fdcan_clock_source: FdCanClockSource,
|
||||
|
||||
pub timer_prescaler: TimerPrescaler,
|
||||
pub voltage_scale: VoltageScale,
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
pub supply_config: SupplyConfig,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -227,21 +221,14 @@ impl Default for Config {
|
||||
#[cfg(stm32h7)]
|
||||
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,
|
||||
voltage_scale: VoltageScale::Scale0,
|
||||
ls: Default::default(),
|
||||
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
|
||||
supply_config: SupplyConfig::Default,
|
||||
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,31 +491,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
#[cfg(stm32h7)]
|
||||
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);
|
||||
|
||||
let rtc = config.ls.init();
|
||||
@ -550,16 +512,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
RCC.d3cfgr().modify(|w| {
|
||||
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)]
|
||||
{
|
||||
@ -573,12 +525,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
w.set_ppre2(config.apb2_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()));
|
||||
@ -601,6 +547,8 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
while !pac::SYSCFG.cccsr().read().ready() {}
|
||||
}
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys),
|
||||
hclk1: Some(hclk),
|
||||
@ -614,7 +562,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
pclk4: Some(apb4),
|
||||
pclk1_tim: Some(apb1_tim),
|
||||
pclk2_tim: Some(apb2_tim),
|
||||
adc: adc,
|
||||
rtc: rtc,
|
||||
|
||||
hsi: hsi,
|
||||
@ -646,7 +593,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
|
||||
#[cfg(stm32h5)]
|
||||
audioclk: None,
|
||||
per: None,
|
||||
i2s_ckin: None,
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
#[cfg(any(stm32l0, stm32l1))]
|
||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
||||
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))]
|
||||
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};
|
||||
@ -59,18 +55,14 @@ pub struct Config {
|
||||
#[cfg(any(stm32wl, stm32wb))]
|
||||
pub shared_ahb_pre: AHBPrescaler,
|
||||
|
||||
// muxes
|
||||
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
|
||||
pub clk48_src: Clk48Src,
|
||||
|
||||
// low speed LSI/LSE/RTC
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
|
||||
pub adc_clock_source: AdcClockSource,
|
||||
|
||||
#[cfg(any(stm32l0, stm32l1))]
|
||||
pub voltage_scale: VoltageScale,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -95,13 +87,10 @@ impl Default for Config {
|
||||
pllsai2: None,
|
||||
#[cfg(crs)]
|
||||
hsi48: Some(Default::default()),
|
||||
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
|
||||
clk48_src: Clk48Src::HSI48,
|
||||
ls: Default::default(),
|
||||
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
|
||||
adc_clock_source: AdcClockSource::SYS,
|
||||
#[cfg(any(stm32l0, stm32l1))]
|
||||
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 }),
|
||||
msi: None,
|
||||
hsi: false,
|
||||
clk48_src: Clk48Src::PLL1_Q,
|
||||
|
||||
ls: super::LsConfig::default_lse(),
|
||||
|
||||
@ -137,7 +125,8 @@ pub const WPAN_DEFAULT: Config = Config {
|
||||
shared_ahb_pre: AHBPrescaler::DIV1,
|
||||
apb1_pre: APBPrescaler::DIV1,
|
||||
apb2_pre: APBPrescaler::DIV1,
|
||||
adc_clock_source: AdcClockSource::SYS,
|
||||
|
||||
mux: super::mux::ClockMux::default(),
|
||||
};
|
||||
|
||||
fn msi_enable(range: MSIRange) {
|
||||
@ -267,21 +256,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
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)]
|
||||
assert!(sys_clk.0 <= 120_000_000);
|
||||
#[cfg(all(stm32l4, not(rcc_l4plus)))]
|
||||
@ -357,9 +331,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
});
|
||||
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))]
|
||||
{
|
||||
RCC.extcfgr().modify(|w| {
|
||||
@ -372,6 +343,8 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
while !RCC.extcfgr().read().c2hpref() {}
|
||||
}
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys_clk),
|
||||
hclk1: Some(hclk1),
|
||||
@ -388,10 +361,11 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
hsi: hsi,
|
||||
hse: hse,
|
||||
msi: msi,
|
||||
#[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
|
||||
clk48: clk48,
|
||||
hsi48: hsi48,
|
||||
|
||||
#[cfg(any(stm32l0, stm32l1))]
|
||||
pll1_vco_div_2: pll.vco.map(|c| c/2u32),
|
||||
|
||||
#[cfg(not(any(stm32l0, stm32l1)))]
|
||||
pll1_p: pll.p,
|
||||
#[cfg(not(any(stm32l0, stm32l1)))]
|
||||
@ -511,7 +485,7 @@ mod pll {
|
||||
#[derive(Default)]
|
||||
pub(super) struct PllOutput {
|
||||
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 {
|
||||
@ -528,7 +502,6 @@ mod pll {
|
||||
let vco_freq = pll_src * pll.mul;
|
||||
|
||||
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));
|
||||
|
||||
@ -541,7 +514,10 @@ mod pll {
|
||||
// Enable PLL
|
||||
pll_enable(instance, true);
|
||||
|
||||
PllOutput { r: Some(r), clk48 }
|
||||
PllOutput {
|
||||
r: Some(r),
|
||||
vco: Some(vco_freq),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,7 @@ mod _version;
|
||||
|
||||
pub use _version::*;
|
||||
|
||||
#[cfg(clock_mux)]
|
||||
pub use crate::_generated::mux;
|
||||
pub use crate::_generated::Clocks;
|
||||
pub use crate::_generated::{mux, Clocks};
|
||||
|
||||
#[cfg(feature = "low-power")]
|
||||
/// Must be written within a critical section
|
||||
|
@ -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.
|
||||
pub voltage_range: VoltageScale,
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -104,6 +107,7 @@ impl Default for Config {
|
||||
apb3_pre: APBPrescaler::DIV1,
|
||||
voltage_range: VoltageScale::RANGE1,
|
||||
ls: Default::default(),
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,6 +263,8 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
|
||||
let rtc = config.ls.init();
|
||||
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys_clk),
|
||||
hclk1: Some(hclk),
|
||||
@ -289,7 +295,6 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
lse: None,
|
||||
lsi: None,
|
||||
msik: None,
|
||||
iclk: None,
|
||||
shsi: None,
|
||||
shsi_div_2: None,
|
||||
);
|
||||
|
@ -1,8 +1,6 @@
|
||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
||||
use crate::pac::rcc::regs::Cfgr1;
|
||||
pub use crate::pac::rcc::vals::{
|
||||
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk,
|
||||
};
|
||||
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk};
|
||||
use crate::pac::{FLASH, RCC};
|
||||
use crate::time::Hertz;
|
||||
|
||||
@ -32,9 +30,10 @@ pub struct Config {
|
||||
// low speed LSI/LSE/RTC
|
||||
pub ls: super::LsConfig,
|
||||
|
||||
pub adc_clock_source: AdcClockSource,
|
||||
|
||||
pub voltage_scale: VoltageScale,
|
||||
|
||||
/// Per-peripheral kernel clock selection muxes
|
||||
pub mux: super::mux::ClockMux,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -49,8 +48,8 @@ impl Default for Config {
|
||||
apb2_pre: APBPrescaler::DIV1,
|
||||
apb7_pre: APBPrescaler::DIV1,
|
||||
ls: Default::default(),
|
||||
adc_clock_source: AdcClockSource::HCLK4,
|
||||
voltage_scale: VoltageScale::RANGE2,
|
||||
mux: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +151,7 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
w.set_ppre2(config.apb2_pre);
|
||||
});
|
||||
|
||||
RCC.ccipr3().modify(|w| w.set_adcsel(config.adc_clock_source));
|
||||
config.mux.init();
|
||||
|
||||
set_clocks!(
|
||||
sys: Some(sys_clk),
|
||||
|
@ -606,13 +606,6 @@ impl<'d, T: Instance> Bus<'d, T> {
|
||||
// Wait for USB power to stabilize
|
||||
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
|
||||
let ulpien = !self.phy_type.internal();
|
||||
critical_section::with(|_| {
|
||||
@ -645,13 +638,6 @@ impl<'d, T: Instance> Bus<'d, T> {
|
||||
|
||||
// Wait for USB power to stabilize
|
||||
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();
|
||||
|
@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) {
|
||||
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||
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);
|
||||
|
||||
|
@ -4,37 +4,35 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
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::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin};
|
||||
use embassy_stm32::timer::simple_pwm::PwmPin;
|
||||
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 _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut rcc_config = RccConfig::default();
|
||||
rcc_config.sys = Sysclk::PLL(PllConfig {
|
||||
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 mut config = PeripheralConfig::default();
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
|
||||
let mut peripheral_config = PeripheralConfig::default();
|
||||
peripheral_config.rcc = rcc_config;
|
||||
config.rcc.sys = Sysclk::PLL(PllConfig {
|
||||
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
|
||||
// RM0444 page 210
|
||||
// RCC - Peripherals Independent Clock Control Register - bit 22 -> 1
|
||||
pac::RCC.ccipr().modify(|w| w.set_tim1sel(Tim1sel::PLL1_Q));
|
||||
// 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
|
||||
// RM0444 page 210
|
||||
// RCC - Peripherals Independent Clock Control Register - bit 22 -> 1
|
||||
config.rcc.mux.tim1sel = embassy_stm32::rcc::mux::Tim1sel::PLL1_Q;
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
let ch1 = PwmPin::new_ch1(p.PA8, OutputType::PushPull);
|
||||
let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull);
|
||||
|
@ -4,7 +4,6 @@
|
||||
use defmt::{panic, *};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_stm32::rcc::{Hsi48Config, UsbSrc};
|
||||
use embassy_stm32::usb::{Driver, Instance};
|
||||
use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
@ -19,10 +18,11 @@ bind_interrupts!(struct Irqs {
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
config.rcc.usb_src = Some(UsbSrc::Hsi48(Hsi48Config {
|
||||
sync_from_usb: true,
|
||||
..Default::default()
|
||||
}));
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true });
|
||||
config.rcc.mux.usbsel = mux::Usbsel::HSI48;
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
info!("Hello World!");
|
||||
|
@ -4,7 +4,6 @@
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::adc::{Adc, SampleTime};
|
||||
use embassy_stm32::rcc::{AdcClockSource, Pll, PllMul, PllPreDiv, PllRDiv, Pllsrc, Sysclk};
|
||||
use embassy_stm32::Config;
|
||||
use embassy_time::{Delay, Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -12,20 +11,20 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
|
||||
config.rcc.pll = Some(Pll {
|
||||
source: Pllsrc::HSI,
|
||||
prediv: PllPreDiv::DIV4,
|
||||
mul: PllMul::MUL85,
|
||||
divp: None,
|
||||
divq: None,
|
||||
// Main system clock at 170 MHz
|
||||
divr: Some(PllRDiv::DIV2),
|
||||
});
|
||||
|
||||
config.rcc.adc12_clock_source = AdcClockSource::SYS;
|
||||
config.rcc.sys = Sysclk::PLL1_R;
|
||||
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.pll = Some(Pll {
|
||||
source: Pllsrc::HSI,
|
||||
prediv: PllPreDiv::DIV4,
|
||||
mul: PllMul::MUL85,
|
||||
divp: None,
|
||||
divq: None,
|
||||
// Main system clock at 170 MHz
|
||||
divr: Some(PllRDiv::DIV2),
|
||||
});
|
||||
config.rcc.mux.adc12sel = mux::Adcsel::SYS;
|
||||
config.rcc.sys = Sysclk::PLL1_R;
|
||||
}
|
||||
let mut p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::peripherals::*;
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::{bind_interrupts, can, Config};
|
||||
use embassy_time::Timer;
|
||||
use static_cell::StaticCell;
|
||||
@ -15,8 +16,24 @@ bind_interrupts!(struct Irqs {
|
||||
|
||||
#[embassy_executor::main]
|
||||
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 mut can = can::FdcanConfigurator::new(peripherals.FDCAN1, peripherals.PA11, peripherals.PA12, Irqs);
|
||||
|
@ -12,6 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.pll = Some(Pll {
|
||||
source: Pllsrc::HSI,
|
||||
prediv: PllPreDiv::DIV4,
|
||||
|
@ -3,9 +3,6 @@
|
||||
|
||||
use defmt::{panic, *};
|
||||
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::usb::{self, Driver, Instance};
|
||||
use embassy_stm32::{bind_interrupts, peripherals, Config};
|
||||
@ -22,38 +19,27 @@ bind_interrupts!(struct Irqs {
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut config = Config::default();
|
||||
|
||||
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
|
||||
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 {
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
// 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.clk48_src = Clk48Src::HSI48;
|
||||
} else {
|
||||
config.rcc.clk48_src = Clk48Src::PLL1_Q;
|
||||
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: 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);
|
||||
|
||||
info!("Hello World!");
|
||||
|
@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
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);
|
||||
|
||||
|
@ -5,7 +5,7 @@ use defmt::{panic, *};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::time::Hertz;
|
||||
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::driver::EndpointError;
|
||||
use embassy_usb::Builder;
|
||||
@ -41,15 +41,12 @@ async fn main(_spawner: Spawner) {
|
||||
config.rcc.apb3_pre = APBPrescaler::DIV4;
|
||||
config.rcc.sys = Sysclk::PLL1_P;
|
||||
config.rcc.voltage_scale = VoltageScale::Scale0;
|
||||
config.rcc.mux.usbsel = mux::Usbsel::HSI48;
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
info!("Hello World!");
|
||||
|
||||
pac::RCC.ccipr4().write(|w| {
|
||||
w.set_usbsel(pac::rcc::vals::Usbsel::HSI48);
|
||||
});
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11);
|
||||
|
||||
|
@ -38,7 +38,7 @@ async fn main(_spawner: Spawner) {
|
||||
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
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);
|
||||
|
||||
|
@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
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);
|
||||
|
||||
|
@ -40,7 +40,7 @@ fn main() -> ! {
|
||||
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
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);
|
||||
|
||||
|
@ -42,7 +42,7 @@ async fn main(spawner: Spawner) {
|
||||
config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
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
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
use defmt::*;
|
||||
use embassy_stm32::adc::{Adc, Resolution};
|
||||
use embassy_stm32::pac;
|
||||
use embassy_stm32::Config;
|
||||
use embassy_time::Delay;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
@ -11,12 +11,12 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
fn main() -> ! {
|
||||
info!("Hello World!");
|
||||
|
||||
pac::RCC.ccipr().modify(|w| {
|
||||
w.set_adcsel(pac::rcc::vals::Adcsel::SYS);
|
||||
});
|
||||
pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
|
||||
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
let mut config = Config::default();
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.mux.adcsel = mux::Adcsel::SYS;
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
let mut adc = Adc::new(p.ADC1, &mut Delay);
|
||||
//adc.enable_vref();
|
||||
|
@ -33,7 +33,7 @@ fn options() -> TestOptions {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
mode: rcc::HseMode::Oscillator,
|
||||
});
|
||||
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
|
||||
c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
|
||||
TestOptions {
|
||||
config: c,
|
||||
max_latency: Duration::from_micros(1200),
|
||||
@ -50,7 +50,7 @@ fn options() -> TestOptions {
|
||||
freq: embassy_stm32::time::Hertz(25_000_000),
|
||||
mode: rcc::HseMode::Oscillator,
|
||||
});
|
||||
c.rcc.fdcan_clock_source = rcc::FdCanClockSource::HSE;
|
||||
c.rcc.mux.fdcansel = rcc::mux::Fdcansel::HSE;
|
||||
TestOptions {
|
||||
config: c,
|
||||
max_latency: Duration::from_micros(1200),
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
pub use defmt::*;
|
||||
#[allow(unused)]
|
||||
use embassy_stm32::rcc::*;
|
||||
#[allow(unused)]
|
||||
use embassy_stm32::time::Hertz;
|
||||
use embassy_stm32::Config;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -265,7 +267,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32f091rc")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Bypass,
|
||||
@ -281,7 +282,6 @@ pub fn config() -> Config {
|
||||
}
|
||||
#[cfg(feature = "stm32f103c8")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Oscillator,
|
||||
@ -298,7 +298,6 @@ pub fn config() -> Config {
|
||||
}
|
||||
#[cfg(feature = "stm32f207zg")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
// By default, HSE on the board comes from a 8 MHz clock signal (not a crystal)
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
@ -327,7 +326,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32f303ze")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Bypass,
|
||||
@ -345,7 +343,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32f429zi")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Bypass,
|
||||
@ -366,7 +363,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32f446re")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Oscillator,
|
||||
@ -387,7 +383,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32f767zi")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(8_000_000),
|
||||
mode: HseMode::Bypass,
|
||||
@ -408,7 +403,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32h563zi")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = None;
|
||||
config.rcc.hsi48 = Some(Default::default()); // needed for RNG
|
||||
config.rcc.hse = Some(Hse {
|
||||
@ -433,7 +427,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32h503rb")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = None;
|
||||
config.rcc.hsi48 = Some(Default::default()); // needed for RNG
|
||||
config.rcc.hse = Some(Hse {
|
||||
@ -456,9 +449,26 @@ pub fn config() -> Config {
|
||||
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"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = Some(HSIPrescaler::DIV1);
|
||||
config.rcc.csi = true;
|
||||
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.apb4_pre = APBPrescaler::DIV2; // 100 Mhz
|
||||
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"))]
|
||||
{
|
||||
config.rcc.supply_config = SupplyConfig::DirectSMPS;
|
||||
@ -494,7 +504,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(any(feature = "stm32h7a3zi"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = Some(HSIPrescaler::DIV1);
|
||||
config.rcc.csi = true;
|
||||
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.apb4_pre = APBPrescaler::DIV2; // 140 Mhz
|
||||
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"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.sys = Sysclk::PLL1_R;
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.pll = Some(Pll {
|
||||
@ -541,7 +549,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32wl55jc")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hse = Some(Hse {
|
||||
freq: Hertz(32_000_000),
|
||||
mode: HseMode::Bypass,
|
||||
@ -560,7 +567,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(any(feature = "stm32l552ze"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.sys = Sysclk::PLL1_R;
|
||||
config.rcc.pll = Some(Pll {
|
||||
@ -576,7 +582,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(any(feature = "stm32u585ai", feature = "stm32u5a5zj"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.pll1 = Some(Pll {
|
||||
source: PllSource::HSI, // 16 MHz
|
||||
@ -593,17 +598,12 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(feature = "stm32wba52cg")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.sys = Sysclk::HSI;
|
||||
|
||||
embassy_stm32::pac::RCC.ccipr2().write(|w| {
|
||||
w.set_rngsel(embassy_stm32::pac::rcc::vals::Rngsel::HSI);
|
||||
});
|
||||
config.rcc.mux.rngsel = mux::Rngsel::HSI;
|
||||
}
|
||||
|
||||
#[cfg(feature = "stm32l073rz")]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.pll = Some(Pll {
|
||||
source: PllSource::HSI,
|
||||
@ -615,7 +615,6 @@ pub fn config() -> Config {
|
||||
|
||||
#[cfg(any(feature = "stm32l152re"))]
|
||||
{
|
||||
use embassy_stm32::rcc::*;
|
||||
config.rcc.hsi = true;
|
||||
config.rcc.pll = Some(Pll {
|
||||
source: PllSource::HSI,
|
||||
|
Loading…
Reference in New Issue
Block a user