stm32/rcc: merge wl into l4/l5.

This commit is contained in:
Dario Nieuwenhuis 2023-10-23 00:28:54 +02:00
parent 46ff2c82aa
commit b9e13cb5d1
11 changed files with 198 additions and 276 deletions

View File

@ -58,7 +58,7 @@ rand_core = "0.6.3"
sdio-host = "0.5.0" sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1" critical-section = "1.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ee64389697d9234af374a89788aa52bb93d59284" } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc" }
vcell = "0.1.3" vcell = "0.1.3"
bxcan = "0.7.0" bxcan = "0.7.0"
nb = "1.0.0" nb = "1.0.0"
@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
[build-dependencies] [build-dependencies]
proc-macro2 = "1.0.36" proc-macro2 = "1.0.36"
quote = "1.0.15" quote = "1.0.15"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ee64389697d9234af374a89788aa52bb93d59284", default-features = false, features = ["metadata"]} stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]}
[features] [features]

View File

@ -5,6 +5,7 @@ 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;
@ -273,7 +274,7 @@ fn _configure_pwr() {
// set LPTIM1 & LPTIM2 clock source // set LPTIM1 & LPTIM2 clock source
rcc.ccipr().modify(|w| { rcc.ccipr().modify(|w| {
w.set_lptim1sel(0b00); // PCLK w.set_lptim1sel(Lptim1sel::PCLK1);
w.set_lptim2sel(0b00); // PCLK w.set_lptim2sel(Lptim2sel::PCLK1);
}); });
} }

View File

@ -1,8 +1,10 @@
use crate::pac::rcc::regs::Cfgr; use crate::pac::rcc::regs::Cfgr;
#[cfg(not(stm32wl))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
use crate::pac::rcc::vals::Msirgsel; use crate::pac::rcc::vals::Msirgsel;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Clk48sel as Clk48Src, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
}; };
use crate::pac::{FLASH, RCC}; use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks}; use crate::rcc::{set_freqs, Clocks};
@ -11,6 +13,22 @@ use crate::time::Hertz;
/// HSI speed /// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000); pub const HSI_FREQ: Hertz = Hertz(16_000_000);
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1)
Bypass,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Hse {
/// HSE frequency.
pub freq: Hertz,
/// HSE mode.
pub mode: HseMode,
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Pll { pub struct Pll {
/// PLL source /// PLL source
@ -35,12 +53,13 @@ pub struct Config {
// base clock sources // base clock sources
pub msi: Option<MSIRange>, pub msi: Option<MSIRange>,
pub hsi: bool, pub hsi: bool,
pub hse: Option<Hertz>, pub hse: Option<Hse>,
#[cfg(not(any(stm32l47x, stm32l48x)))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
pub hsi48: bool, pub hsi48: bool,
// pll // pll
pub pll: Option<Pll>, pub pll: Option<Pll>,
#[cfg(any(stm32l4, stm32l5))]
pub pllsai1: Option<Pll>, pub pllsai1: Option<Pll>,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pub pllsai2: Option<Pll>, pub pllsai2: Option<Pll>,
@ -50,8 +69,11 @@ pub struct Config {
pub ahb_pre: AHBPrescaler, pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler, pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler, pub apb2_pre: APBPrescaler,
#[cfg(stm32wl)]
pub shared_ahb_pre: AHBPrescaler,
// muxes // muxes
#[cfg(not(stm32wl))]
pub clk48_src: Clk48Src, pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC // low speed LSI/LSE/RTC
@ -69,12 +91,16 @@ impl Default for Config {
ahb_pre: AHBPrescaler::DIV1, ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1,
#[cfg(stm32wl)]
shared_ahb_pre: AHBPrescaler::DIV1,
pll: None, pll: None,
#[cfg(any(stm32l4, stm32l5))]
pllsai1: None, pllsai1: None,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2: None, pllsai2: None,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
hsi48: true, hsi48: true,
#[cfg(not(stm32wl))]
clk48_src: Clk48Src::HSI48, clk48_src: Clk48Src::HSI48,
ls: Default::default(), ls: Default::default(),
} }
@ -111,7 +137,7 @@ pub(crate) unsafe fn init(config: Config) {
let msi = config.msi.map(|range| { let msi = config.msi.map(|range| {
// Enable MSI // Enable MSI
RCC.cr().write(|w| { RCC.cr().modify(|w| {
w.set_msirange(range); w.set_msirange(range);
w.set_msirgsel(Msirgsel::CR); w.set_msirgsel(Msirgsel::CR);
w.set_msion(true); w.set_msion(true);
@ -128,20 +154,26 @@ pub(crate) unsafe fn init(config: Config) {
}); });
let hsi = config.hsi.then(|| { let hsi = config.hsi.then(|| {
RCC.cr().write(|w| w.set_hsion(true)); RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
HSI_FREQ HSI_FREQ
}); });
let hse = config.hse.map(|freq| { let hse = config.hse.map(|hse| {
RCC.cr().write(|w| w.set_hseon(true)); RCC.cr().modify(|w| {
#[cfg(stm32wl)]
w.set_hsebyppwr(hse.mode == HseMode::Bypass);
#[cfg(not(stm32wl))]
w.set_hsebyp(hse.mode == HseMode::Bypass);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {} while !RCC.cr().read().hserdy() {}
freq hse.freq
}); });
#[cfg(not(any(stm32l47x, stm32l48x)))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
let hsi48 = config.hsi48.then(|| { let hsi48 = config.hsi48.then(|| {
RCC.crrcr().modify(|w| w.set_hsi48on(true)); RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {} while !RCC.crrcr().read().hsi48rdy() {}
@ -153,6 +185,7 @@ pub(crate) unsafe fn init(config: Config) {
let _plls = [ let _plls = [
&config.pll, &config.pll,
#[cfg(any(stm32l4, stm32l5))]
&config.pllsai1, &config.pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
&config.pllsai2, &config.pllsai2,
@ -169,8 +202,8 @@ pub(crate) unsafe fn init(config: Config) {
}), }),
}; };
// L4+ has shared PLLSRC, check it's equal in all PLLs. // L4+, WL has shared PLLSRC, check it's equal in all PLLs.
#[cfg(any(rcc_l4plus))] #[cfg(any(rcc_l4plus, stm32wl))]
match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { match get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
Err(()) => panic!("Source must be equal across all enabled PLLs."), Err(()) => panic!("Source must be equal across all enabled PLLs."),
Ok(None) => {} Ok(None) => {}
@ -181,6 +214,7 @@ pub(crate) unsafe fn init(config: Config) {
let pll_input = PllInput { hse, hsi, msi }; let pll_input = PllInput { hse, hsi, msi };
let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
#[cfg(any(stm32l4, stm32l5))]
let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input); let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
@ -196,6 +230,7 @@ pub(crate) unsafe fn init(config: Config) {
RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(stm32l5)] #[cfg(stm32l5)]
RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(not(stm32wl))]
let _clk48 = match config.clk48_src { let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => hsi48, Clk48Src::HSI48 => hsi48,
Clk48Src::MSI => msi, Clk48Src::MSI => msi,
@ -208,38 +243,6 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(all(stm32l4, not(rcc_l4plus)))] #[cfg(all(stm32l4, not(rcc_l4plus)))]
assert!(sys_clk.0 <= 80_000_000); assert!(sys_clk.0 <= 80_000_000);
// Set flash wait states
#[cfg(stm32l4)]
FLASH.acr().modify(|w| {
w.set_latency(match sys_clk.0 {
0..=16_000_000 => 0,
0..=32_000_000 => 1,
0..=48_000_000 => 2,
0..=64_000_000 => 3,
_ => 4,
})
});
// VCORE Range 0 (performance), others TODO
#[cfg(stm32l5)]
FLASH.acr().modify(|w| {
w.set_latency(match sys_clk.0 {
0..=20_000_000 => 0,
0..=40_000_000 => 1,
0..=60_000_000 => 2,
0..=80_000_000 => 3,
0..=100_000_000 => 4,
_ => 5,
})
});
RCC.cfgr().modify(|w| {
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
while RCC.cfgr().read().sws() != config.mux {}
let ahb_freq = sys_clk / config.ahb_pre; let ahb_freq = sys_clk / config.ahb_pre;
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
@ -258,15 +261,69 @@ pub(crate) unsafe fn init(config: Config) {
} }
}; };
#[cfg(stm32wl)]
let ahb3_freq = sys_clk / config.shared_ahb_pre;
// Set flash wait states
#[cfg(stm32l4)]
let latency = match sys_clk.0 {
0..=16_000_000 => 0,
0..=32_000_000 => 1,
0..=48_000_000 => 2,
0..=64_000_000 => 3,
_ => 4,
};
#[cfg(stm32l5)]
let latency = match sys_clk.0 {
// VCORE Range 0 (performance), others TODO
0..=20_000_000 => 0,
0..=40_000_000 => 1,
0..=60_000_000 => 2,
0..=80_000_000 => 3,
0..=100_000_000 => 4,
_ => 5,
};
#[cfg(stm32wl)]
let latency = match ahb3_freq.0 {
// VOS RANGE1, others TODO.
..=18_000_000 => 0,
..=36_000_000 => 1,
_ => 2,
};
FLASH.acr().modify(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {}
RCC.cfgr().modify(|w| {
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32wl)]
{
RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shared_ahb_pre);
});
while !RCC.extcfgr().read().shdhpref() {}
}
set_freqs(Clocks { set_freqs(Clocks {
sys: sys_clk, sys: sys_clk,
hclk1: ahb_freq, hclk1: ahb_freq,
hclk2: ahb_freq, hclk2: ahb_freq,
#[cfg(not(stm32wl))]
hclk3: ahb_freq, hclk3: ahb_freq,
pclk1: apb1_freq, pclk1: apb1_freq,
pclk2: apb2_freq, pclk2: apb2_freq,
pclk1_tim: apb1_tim_freq, pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq, pclk2_tim: apb2_tim_freq,
#[cfg(stm32wl)]
hclk3: ahb3_freq,
#[cfg(stm32wl)]
pclk3: ahb3_freq,
#[cfg(rcc_l4)] #[cfg(rcc_l4)]
hsi: None, hsi: None,
#[cfg(rcc_l4)] #[cfg(rcc_l4)]
@ -330,6 +387,7 @@ struct PllOutput {
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance { enum PllInstance {
Pll, Pll,
#[cfg(any(stm32l4, stm32l5))]
Pllsai1, Pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
Pllsai2, Pllsai2,
@ -342,6 +400,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
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() {}
} }
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => { PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(false)); RCC.cr().modify(|w| w.set_pllsai1on(false));
while RCC.cr().read().pllsai1rdy() {} while RCC.cr().read().pllsai1rdy() {}
@ -356,7 +415,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
let Some(pll) = config else { return PllOutput::default() }; let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source { let pll_src = match pll.source {
PLLSource::NONE => panic!("must not select PLL source as NONE"), PLLSource::DISABLE => panic!("must not select PLL source as NONE"),
PLLSource::HSE => input.hse, PLLSource::HSE => input.hse,
PLLSource::HSI => input.hsi, PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi, PLLSource::MSI => input.msi,
@ -400,6 +459,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
w.set_pllsrc(pll.source); w.set_pllsrc(pll.source);
write_fields!(w); write_fields!(w);
}), }),
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))] #[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv); w.set_pllm(pll.prediv);
@ -423,6 +483,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
RCC.cr().modify(|w| w.set_pllon(true)); RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {} while !RCC.cr().read().pllrdy() {}
} }
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => { PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(true)); RCC.cr().modify(|w| w.set_pllsai1on(true));
while !RCC.cr().read().pllsai1rdy() {} while !RCC.cr().read().pllsai1rdy() {}

View File

@ -19,11 +19,10 @@ pub use mco::*;
#[cfg_attr(rcc_g4, path = "g4.rs")] #[cfg_attr(rcc_g4, path = "g4.rs")]
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] #[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5), path = "l4l5.rs")] #[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle), path = "l4l5.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wb, path = "wb.rs")] #[cfg_attr(rcc_wb, path = "wb.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")]
#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
mod _version; mod _version;
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};

View File

@ -170,7 +170,7 @@ impl Config {
RCC.icscr1().modify(|w| { RCC.icscr1().modify(|w| {
w.set_msisrange(range); w.set_msisrange(range);
w.set_msirgsel(Msirgsel::RCC_ICSCR1); w.set_msirgsel(Msirgsel::ICSCR1);
}); });
RCC.cr().write(|w| { RCC.cr().write(|w| {
w.set_msipllen(false); w.set_msipllen(false);

View File

@ -1,184 +0,0 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::vals::Sw;
pub use crate::pac::rcc::vals::{
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
Pllsrc as PllSource, Ppre as APBPrescaler,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// HSE speed
pub const HSE_FREQ: Hertz = Hertz(32_000_000);
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
MSI(MSIRange),
HSE,
HSI,
}
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub shd_ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub adc_clock_source: AdcClockSource,
pub ls: super::LsConfig,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
mux: ClockSrc::MSI(MSIRange::RANGE4M),
ahb_pre: AHBPrescaler::DIV1,
shd_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
adc_clock_source: AdcClockSource::HSI,
ls: Default::default(),
}
}
}
pub(crate) unsafe fn init(config: Config) {
let (sys_clk, sw, vos) = match config.mux {
ClockSrc::HSI => (HSI_FREQ, Sw::HSI, VoltageScale::RANGE2),
ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1),
ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
};
let ahb_freq = sys_clk / config.ahb_pre;
let shd_ahb_freq = sys_clk / config.shd_ahb_pre;
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
pre => {
let freq = ahb_freq / pre;
(freq, freq * 2u32)
}
};
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
pre => {
let freq = ahb_freq / pre;
(freq, freq * 2u32)
}
};
// Adjust flash latency
let flash_clk_src_freq = shd_ahb_freq;
let ws = match vos {
VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
0..=18_000_000 => 0b000,
18_000_001..=36_000_000 => 0b001,
_ => 0b010,
},
VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
0..=6_000_000 => 0b000,
6_000_001..=12_000_000 => 0b001,
_ => 0b010,
},
_ => unreachable!(),
};
FLASH.acr().modify(|w| {
w.set_latency(ws);
});
while FLASH.acr().read().latency() != ws {}
match config.mux {
ClockSrc::HSI => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
ClockSrc::HSE => {
// Enable HSE
RCC.cr().write(|w| {
w.set_hsebyppwr(true);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
}
ClockSrc::MSI(range) => {
let cr = RCC.cr().read();
assert!(!cr.msion() || cr.msirdy());
RCC.cr().write(|w| {
w.set_msirgsel(true);
w.set_msirange(range);
w.set_msion(true);
// If LSE is enabled, enable calibration of MSI
w.set_msipllen(config.ls.lse.is_some());
});
while !RCC.cr().read().msirdy() {}
}
}
RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shd_ahb_pre);
});
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
// ADC clock MUX
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
// TODO: switch voltage range
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
hclk3: shd_ahb_freq,
pclk1: apb1_freq,
pclk2: apb2_freq,
pclk3: shd_ahb_freq,
pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq,
rtc,
});
}
fn msirange_to_hertz(range: MSIRange) -> Hertz {
match range {
MSIRange::RANGE100K => Hertz(100_000),
MSIRange::RANGE200K => Hertz(200_000),
MSIRange::RANGE400K => Hertz(400_000),
MSIRange::RANGE800K => Hertz(800_000),
MSIRange::RANGE1M => Hertz(1_000_000),
MSIRange::RANGE2M => Hertz(2_000_000),
MSIRange::RANGE4M => Hertz(4_000_000),
MSIRange::RANGE8M => Hertz(8_000_000),
MSIRange::RANGE16M => Hertz(16_000_000),
MSIRange::RANGE24M => Hertz(24_000_000),
MSIRange::RANGE32M => Hertz(32_000_000),
MSIRange::RANGE48M => Hertz(48_000_000),
_ => unreachable!(),
}
}
fn msirange_to_vos(range: MSIRange) -> VoltageScale {
if range.to_bits() > MSIRange::RANGE16M.to_bits() {
VoltageScale::RANGE1
} else {
VoltageScale::RANGE2
}
}

View File

@ -5,7 +5,6 @@
use chrono::{NaiveDate, NaiveDateTime}; use chrono::{NaiveDate, NaiveDateTime};
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig};
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::Config; use embassy_stm32::Config;
@ -15,17 +14,23 @@ 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.mux = ClockSrc::PLL1_R; {
config.rcc.hse = Some(Hertz::mhz(8)); use embassy_stm32::rcc::*;
config.rcc.pll = Some(Pll { config.rcc.mux = ClockSrc::PLL1_R;
source: PLLSource::HSE, config.rcc.hse = Some(Hse {
prediv: PllPreDiv::DIV1, freq: Hertz::mhz(8),
mul: PllMul::MUL20, mode: HseMode::Oscillator,
divp: None, });
divq: None, config.rcc.pll = Some(Pll {
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2) source: PLLSource::HSE,
}); prediv: PllPreDiv::DIV1,
config.rcc.ls = LsConfig::default_lse(); mul: PllMul::MUL20,
divp: None,
divq: None,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
});
config.rcc.ls = LsConfig::default_lse();
}
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View File

@ -48,7 +48,6 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
use embedded_hal_bus::spi::ExclusiveDevice; use embedded_hal_bus::spi::ExclusiveDevice;
use hal::gpio::Pull; use hal::gpio::Pull;
use hal::i2c::Config as I2C_Config; use hal::i2c::Config as I2C_Config;
use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use hal::spi::{Config as SPI_Config, Spi}; use hal::spi::{Config as SPI_Config, Spi};
use hal::time::Hertz; use hal::time::Hertz;
@ -74,20 +73,25 @@ async fn main(spawner: Spawner) {
defmt::println!("Start main()"); defmt::println!("Start main()");
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
{
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) use embassy_stm32::rcc::*;
// 80MHz highest frequency for flash 0 wait. // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
config.rcc.mux = ClockSrc::PLL1_R; // 80MHz highest frequency for flash 0 wait.
config.rcc.hse = Some(Hertz::mhz(8)); config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.hse = Some(Hse {
source: PLLSource::HSE, freq: Hertz::mhz(8),
prediv: PllPreDiv::DIV1, mode: HseMode::Oscillator,
mul: PllMul::MUL20, });
divp: None, config.rcc.pll = Some(Pll {
divq: None, source: PLLSource::HSE,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2) prediv: PllPreDiv::DIV1,
}); mul: PllMul::MUL20,
config.rcc.hsi48 = true; // needed for rng divp: None,
divq: None,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
});
config.rcc.hsi48 = true; // needed for rng
}
let dp = embassy_stm32::init(config); let dp = embassy_stm32::init(config);

View File

@ -12,7 +12,8 @@ use embassy_lora::LoraTimer;
use embassy_stm32::gpio::{Level, Output, Pin, Speed}; use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::rng::{self, Rng}; use embassy_stm32::rng::{self, Rng};
use embassy_stm32::spi::Spi; use embassy_stm32::spi::Spi;
use embassy_stm32::{bind_interrupts, pac, peripherals}; use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, peripherals};
use embassy_time::Delay; use embassy_time::Delay;
use lora_phy::mod_params::*; use lora_phy::mod_params::*;
use lora_phy::sx1261_2::SX1261_2; use lora_phy::sx1261_2::SX1261_2;
@ -33,11 +34,24 @@ bind_interrupts!(struct Irqs{
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
});
}
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
// Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx

View File

@ -4,9 +4,9 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, MSIRange};
use embassy_stm32::rng::{self, Rng}; use embassy_stm32::rng::{self, Rng};
use embassy_stm32::{bind_interrupts, pac, peripherals}; use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, peripherals};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs{ bind_interrupts!(struct Irqs{
@ -16,11 +16,24 @@ bind_interrupts!(struct Irqs{
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M); {
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
});
}
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
pac::RCC.ccipr().modify(|w| w.set_rngsel(0b11)); // msi
info!("Hello World!"); info!("Hello World!");
let mut rng = Rng::new(p.RNG, Irqs); let mut rng = Rng::new(p.RNG, Irqs);

View File

@ -402,9 +402,18 @@ pub fn config() -> Config {
#[cfg(feature = "stm32wl55jc")] #[cfg(feature = "stm32wl55jc")]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M); config.rcc.hse = Some(Hse {
embassy_stm32::pac::RCC.ccipr().modify(|w| { freq: Hertz(32_000_000),
w.set_rngsel(0b11); // msi mode: HseMode::Bypass,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
}); });
} }