Merge pull request #2177 from embassy-rs/rcc-no-spaghetti

stm32/rcc: unify l0l1 and l4l5.
This commit is contained in:
Dario Nieuwenhuis 2023-11-13 00:46:43 +00:00 committed by GitHub
commit f00e97a5f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 360 additions and 434 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-1374ed622714ef4702826699ca21cc1f741f4133" } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f" }
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-1374ed622714ef4702826699ca21cc1f741f4133", default-features = false, features = ["metadata"]} stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c551c07bf12513dd8346a9fe0bc70cf79f2ea02f", default-features = false, features = ["metadata"]}
[features] [features]

View File

@ -1,7 +1,7 @@
use crate::pac::flash::vals::Latency; use crate::pac::flash::vals::Latency;
use crate::pac::rcc::vals::Sw; use crate::pac::rcc::vals::Sw;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc, Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllsrc as PllSource,
Ppre as APBPrescaler, Ppre as APBPrescaler,
}; };
use crate::pac::{FLASH, RCC}; use crate::pac::{FLASH, RCC};
@ -35,30 +35,30 @@ pub enum HSESrc {
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct PLLConfig { pub struct Pll {
pub pre_div: PLLPreDiv, pub pre_div: PllPreDiv,
pub mul: PLLMul, pub mul: PllMul,
pub p_div: PLLPDiv, pub divp: PllPDiv,
pub q_div: PLLQDiv, pub divq: PllQDiv,
} }
impl Default for PLLConfig { impl Default for Pll {
fn default() -> Self { fn default() -> Self {
PLLConfig { Pll {
pre_div: PLLPreDiv::DIV16, pre_div: PllPreDiv::DIV16,
mul: PLLMul::MUL192, mul: PllMul::MUL192,
p_div: PLLPDiv::DIV2, divp: PllPDiv::DIV2,
q_div: PLLQDiv::DIV4, divq: PllQDiv::DIV4,
} }
} }
} }
impl PLLConfig { impl Pll {
pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { pub fn clocks(&self, src_freq: Hertz) -> PLLClocks {
let in_freq = src_freq / self.pre_div; let in_freq = src_freq / self.pre_div;
let vco_freq = src_freq / self.pre_div * self.mul; let vco_freq = src_freq / self.pre_div * self.mul;
let main_freq = vco_freq / self.p_div; let main_freq = vco_freq / self.divp;
let pll48_freq = vco_freq / self.q_div; let pll48_freq = vco_freq / self.divq;
PLLClocks { PLLClocks {
in_freq, in_freq,
vco_freq, vco_freq,
@ -172,8 +172,8 @@ impl VoltageScale {
pub struct Config { pub struct Config {
pub hse: Option<HSEConfig>, pub hse: Option<HSEConfig>,
pub hsi: bool, pub hsi: bool,
pub pll_mux: PLLSrc, pub pll_mux: PllSource,
pub pll: PLLConfig, pub pll: Pll,
pub mux: ClockSrc, pub mux: ClockSrc,
pub voltage: VoltageScale, pub voltage: VoltageScale,
pub ahb_pre: AHBPrescaler, pub ahb_pre: AHBPrescaler,
@ -188,8 +188,8 @@ impl Default for Config {
Config { Config {
hse: None, hse: None,
hsi: true, hsi: true,
pll_mux: PLLSrc::HSI, pll_mux: PllSource::HSI,
pll: PLLConfig::default(), pll: Pll::default(),
voltage: VoltageScale::Range3, voltage: VoltageScale::Range3,
mux: ClockSrc::HSI, mux: ClockSrc::HSI,
ahb_pre: AHBPrescaler::DIV1, ahb_pre: AHBPrescaler::DIV1,
@ -217,13 +217,13 @@ pub(crate) unsafe fn init(config: Config) {
} }
let pll_src_freq = match config.pll_mux { let pll_src_freq = match config.pll_mux {
PLLSrc::HSE => { PllSource::HSE => {
let hse_config = config let hse_config = config
.hse .hse
.unwrap_or_else(|| panic!("HSE must be configured to be used as PLL input")); .unwrap_or_else(|| panic!("HSE must be configured to be used as PLL input"));
hse_config.frequency hse_config.frequency
} }
PLLSrc::HSI => HSI_FREQ, PllSource::HSI => HSI_FREQ,
}; };
// Reference: STM32F215xx/217xx datasheet Table 33. Main PLL characteristics // Reference: STM32F215xx/217xx datasheet Table 33. Main PLL characteristics
@ -238,8 +238,8 @@ pub(crate) unsafe fn init(config: Config) {
w.set_pllsrc(config.pll_mux); w.set_pllsrc(config.pll_mux);
w.set_pllm(config.pll.pre_div); w.set_pllm(config.pll.pre_div);
w.set_plln(config.pll.mul); w.set_plln(config.pll.mul);
w.set_pllp(config.pll.p_div); w.set_pllp(config.pll.divp);
w.set_pllq(config.pll.q_div); w.set_pllq(config.pll.divq);
}); });
let (sys_clk, sw) = match config.mux { let (sys_clk, sw) = match config.mux {

View File

@ -28,7 +28,7 @@ pub enum ClockSrc {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct PllConfig { pub struct PllConfig {
/// The source from which the PLL receives a clock signal /// The source from which the PLL receives a clock signal
pub source: PllSrc, pub source: PllSource,
/// The initial divisor of that clock signal /// The initial divisor of that clock signal
pub m: Pllm, pub m: Pllm,
/// The PLL VCO multiplier, which must be in the range `8..=86`. /// The PLL VCO multiplier, which must be in the range `8..=86`.
@ -48,7 +48,7 @@ impl Default for PllConfig {
fn default() -> PllConfig { fn default() -> PllConfig {
// HSI / 1 * 8 / 2 = 64 MHz // HSI / 1 * 8 / 2 = 64 MHz
PllConfig { PllConfig {
source: PllSrc::HSI, source: PllSource::HSI,
m: Pllm::DIV1, m: Pllm::DIV1,
n: Plln::MUL8, n: Plln::MUL8,
r: Pllr::DIV2, r: Pllr::DIV2,
@ -59,7 +59,7 @@ impl Default for PllConfig {
} }
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub enum PllSrc { pub enum PllSource {
HSI, HSI,
HSE(Hertz), HSE(Hertz),
} }
@ -89,8 +89,8 @@ impl Default for Config {
impl PllConfig { impl PllConfig {
pub(crate) fn init(self) -> Hertz { pub(crate) fn init(self) -> Hertz {
let (src, input_freq) = match self.source { let (src, input_freq) = match self.source {
PllSrc::HSI => (vals::Pllsrc::HSI, HSI_FREQ), PllSource::HSI => (vals::Pllsrc::HSI, HSI_FREQ),
PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq), PllSource::HSE(freq) => (vals::Pllsrc::HSE, freq),
}; };
let m_freq = input_freq / self.m; let m_freq = input_freq / self.m;
@ -121,11 +121,11 @@ impl PllConfig {
// > 3. Change the desired parameter. // > 3. Change the desired parameter.
// Enable whichever clock source we're using, and wait for it to become ready // Enable whichever clock source we're using, and wait for it to become ready
match self.source { match self.source {
PllSrc::HSI => { PllSource::HSI => {
RCC.cr().write(|w| w.set_hsion(true)); RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
} }
PllSrc::HSE(_) => { PllSource::HSE(_) => {
RCC.cr().write(|w| w.set_hseon(true)); RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {} while !RCC.cr().read().hserdy() {}
} }

View File

@ -23,16 +23,16 @@ pub enum ClockSrc {
/// PLL clock input source /// PLL clock input source
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum PllSrc { pub enum PllSource {
HSI, HSI,
HSE(Hertz), HSE(Hertz),
} }
impl Into<Pllsrc> for PllSrc { impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc { fn into(self) -> Pllsrc {
match self { match self {
PllSrc::HSE(..) => Pllsrc::HSE, PllSource::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI, PllSource::HSI => Pllsrc::HSI,
} }
} }
} }
@ -44,7 +44,7 @@ impl Into<Pllsrc> for PllSrc {
/// frequency ranges for each of these settings. /// frequency ranges for each of these settings.
pub struct Pll { pub struct Pll {
/// PLL Source clock selection. /// PLL Source clock selection.
pub source: PllSrc, pub source: PllSource,
/// PLL pre-divider /// PLL pre-divider
pub prediv_m: PllM, pub prediv_m: PllM,
@ -118,13 +118,13 @@ pub struct PllFreq {
pub(crate) unsafe fn init(config: Config) { pub(crate) unsafe fn init(config: 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 {
PllSrc::HSI => { PllSource::HSI => {
RCC.cr().write(|w| w.set_hsion(true)); RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
HSI_FREQ HSI_FREQ
} }
PllSrc::HSE(freq) => { PllSource::HSE(freq) => {
RCC.cr().write(|w| w.set_hseon(true)); RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {} while !RCC.cr().read().hserdy() {}
freq freq

View File

@ -1,12 +1,13 @@
#[cfg(any(stm32l0, stm32l1))]
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))] #[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; 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::{ pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange as MSIRange, Ppre as APBPrescaler, Sw as ClockSrc};
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul,
Pllp as PllPDiv, Pllq as PllQDiv, 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};
use crate::time::Hertz; use crate::time::Hertz;
@ -33,25 +34,6 @@ pub struct Hse {
pub prescaler: HsePrescaler, pub prescaler: HsePrescaler,
} }
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PLLSource,
/// PLL pre-divider (DIVM).
pub prediv: PllPreDiv,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL P division factor. If None, PLL P output is disabled.
pub divp: Option<PllPDiv>,
/// PLL Q division factor. If None, PLL Q output is disabled.
pub divq: Option<PllQDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<PllRDiv>,
}
/// Clocks configuration /// Clocks configuration
pub struct Config { pub struct Config {
// base clock sources // base clock sources
@ -79,13 +61,17 @@ pub struct Config {
pub shared_ahb_pre: AHBPrescaler, pub shared_ahb_pre: AHBPrescaler,
// muxes // muxes
#[cfg(any(stm32l4, stm32l5, stm32wb))] #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
pub clk48_src: Clk48Src, 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, pub adc_clock_source: AdcClockSource,
#[cfg(any(stm32l0, stm32l1))]
pub voltage_scale: VoltageScale,
} }
impl Default for Config { impl Default for Config {
@ -110,10 +96,13 @@ impl Default for Config {
pllsai2: None, pllsai2: None,
#[cfg(crs)] #[cfg(crs)]
hsi48: Some(Default::default()), hsi48: Some(Default::default()),
#[cfg(any(stm32l4, stm32l5, stm32wb))] #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48, clk48_src: Clk48Src::HSI48,
ls: Default::default(), ls: Default::default(),
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
adc_clock_source: AdcClockSource::SYS, adc_clock_source: AdcClockSource::SYS,
#[cfg(any(stm32l0, stm32l1))]
voltage_scale: VoltageScale::RANGE1,
} }
} }
} }
@ -135,7 +124,7 @@ pub const WPAN_DEFAULT: Config = Config {
ls: super::LsConfig::default_lse(), ls: super::LsConfig::default_lse(),
pll: Some(Pll { pll: Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL12, mul: PllMul::MUL12,
divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
@ -152,20 +141,26 @@ pub const WPAN_DEFAULT: Config = Config {
adc_clock_source: AdcClockSource::SYS, adc_clock_source: AdcClockSource::SYS,
}; };
fn msi_enable(range: MSIRange) {
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(range);
w.set_msipllen(false);
});
#[cfg(any(stm32l0, stm32l1))]
RCC.icscr().modify(|w| w.set_msirange(range));
RCC.cr().modify(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {}
}
pub(crate) unsafe fn init(config: Config) { pub(crate) unsafe fn init(config: Config) {
// Switch to MSI to prevent problems with PLL configuration. // Switch to MSI to prevent problems with PLL configuration.
if !RCC.cr().read().msion() { if !RCC.cr().read().msion() {
// Turn on MSI and configure it to 4MHz. // Turn on MSI and configure it to 4MHz.
RCC.cr().modify(|w| { msi_enable(MSIRange::RANGE4M)
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(MSIRange::RANGE4M);
w.set_msipllen(false);
w.set_msion(true)
});
// Wait until MSI is running
while !RCC.cr().read().msirdy() {}
} }
if RCC.cfgr().read().sws() != ClockSrc::MSI { if RCC.cfgr().read().sws() != ClockSrc::MSI {
// Set MSI as a clock source, reset prescalers. // Set MSI as a clock source, reset prescalers.
@ -174,6 +169,14 @@ pub(crate) unsafe fn init(config: Config) {
while RCC.cfgr().read().sws() != ClockSrc::MSI {} while RCC.cfgr().read().sws() != ClockSrc::MSI {}
} }
// Set voltage scale
#[cfg(any(stm32l0, stm32l1))]
{
while crate::pac::PWR.csr().read().vosf() {}
crate::pac::PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while crate::pac::PWR.csr().read().vosf() {}
}
#[cfg(stm32l5)] #[cfg(stm32l5)]
crate::pac::PWR.cr1().modify(|w| { crate::pac::PWR.cr1().modify(|w| {
w.set_vos(crate::pac::pwr::vals::Vos::RANGE0); w.set_vos(crate::pac::pwr::vals::Vos::RANGE0);
@ -182,21 +185,16 @@ pub(crate) unsafe fn init(config: Config) {
let rtc = config.ls.init(); let rtc = config.ls.init();
let msi = config.msi.map(|range| { let msi = config.msi.map(|range| {
// Enable MSI msi_enable(range);
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
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() {}
msirange_to_hertz(range) msirange_to_hertz(range)
}); });
// If LSE is enabled and the right freq, enable calibration of MSI
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
if config.ls.lse.map(|x| x.frequency) == Some(Hertz(32_768)) {
RCC.cr().modify(|w| w.set_msipllen(true));
}
let hsi = config.hsi.then(|| { let hsi = config.hsi.then(|| {
RCC.cr().modify(|w| w.set_hsion(true)); RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
@ -218,7 +216,10 @@ pub(crate) unsafe fn init(config: Config) {
}); });
#[cfg(crs)] #[cfg(crs)]
let _hsi48 = config.hsi48.map(super::init_hsi48); let _hsi48 = config.hsi48.map(|config| {
//
super::init_hsi48(config)
});
#[cfg(not(crs))] #[cfg(not(crs))]
let _hsi48: Option<Hertz> = None; let _hsi48: Option<Hertz> = None;
@ -251,7 +252,12 @@ pub(crate) unsafe fn init(config: Config) {
}), }),
}; };
let pll_input = PllInput { hse, hsi, msi }; let pll_input = PllInput {
hse,
hsi,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
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, stm32wb))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
@ -265,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::PLL1_R => pll.r.unwrap(), ClockSrc::PLL1_R => pll.r.unwrap(),
}; };
#[cfg(stm32l4)] #[cfg(any(rcc_l0_v2, stm32l4, stm32l5, stm32wb))]
RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(stm32l5)] #[cfg(any(rcc_l0_v2))]
RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48,
Clk48Src::PLL1_VCO_DIV_2 => pll.clk48,
};
#[cfg(any(stm32l4, stm32l5, stm32wb))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
let _clk48 = match config.clk48_src { let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => _hsi48, Clk48Src::HSI48 => _hsi48,
@ -285,16 +294,23 @@ pub(crate) unsafe fn init(config: Config) {
let hclk1 = sys_clk / config.ahb_pre; let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre); let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(not(any(stm32wl5x, stm32wb)))] #[cfg(any(stm32l4, stm32l5, stm32wlex))]
let hclk2 = hclk1; let hclk2 = hclk1;
#[cfg(any(stm32wl5x, stm32wb))] #[cfg(any(stm32wl5x, stm32wb))]
let hclk2 = sys_clk / config.core2_ahb_pre; let hclk2 = sys_clk / config.core2_ahb_pre;
#[cfg(not(any(stm32wl, stm32wb)))] #[cfg(any(stm32l4, stm32l5, stm32wlex))]
let hclk3 = hclk1; let hclk3 = hclk1;
#[cfg(any(stm32wl, stm32wb))] #[cfg(any(stm32wl5x, stm32wb))]
let hclk3 = sys_clk / config.shared_ahb_pre; let hclk3 = sys_clk / config.shared_ahb_pre;
// Set flash wait states // Set flash wait states
#[cfg(any(stm32l0, stm32l1))]
let latency = match (config.voltage_scale, sys_clk.0) {
(VoltageScale::RANGE1, ..=16_000_000) => false,
(VoltageScale::RANGE2, ..=8_000_000) => false,
(VoltageScale::RANGE3, ..=4_200_000) => false,
_ => true,
};
#[cfg(stm32l4)] #[cfg(stm32l4)]
let latency = match hclk1.0 { let latency = match hclk1.0 {
0..=16_000_000 => 0, 0..=16_000_000 => 0,
@ -330,6 +346,10 @@ pub(crate) unsafe fn init(config: Config) {
_ => 4, _ => 4,
}; };
#[cfg(stm32l1)]
FLASH.acr().write(|w| w.set_acc64(true));
#[cfg(not(stm32l5))]
FLASH.acr().modify(|w| w.set_prften(true));
FLASH.acr().modify(|w| w.set_latency(latency)); FLASH.acr().modify(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {} while FLASH.acr().read().latency() != latency {}
@ -341,9 +361,7 @@ pub(crate) unsafe fn init(config: Config) {
}); });
while RCC.cfgr().read().sws() != config.mux {} while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32l5)] #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
RCC.ccipr1().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(not(stm32l5))]
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source)); RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
#[cfg(any(stm32wl, stm32wb))] #[cfg(any(stm32wl, stm32wb))]
@ -361,7 +379,9 @@ pub(crate) unsafe fn init(config: Config) {
set_freqs(Clocks { set_freqs(Clocks {
sys: sys_clk, sys: sys_clk,
hclk1, hclk1,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk2, hclk2,
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
hclk3, hclk3,
pclk1, pclk1,
pclk2, pclk2,
@ -389,6 +409,12 @@ pub(crate) unsafe fn init(config: Config) {
}); });
} }
#[cfg(any(stm32l0, stm32l1))]
fn msirange_to_hertz(range: MSIRange) -> Hertz {
Hertz(32_768 * (1 << (range as u8 + 1)))
}
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
fn msirange_to_hertz(range: MSIRange) -> Hertz { fn msirange_to_hertz(range: MSIRange) -> Hertz {
match range { match range {
MSIRange::RANGE100K => Hertz(100_000), MSIRange::RANGE100K => Hertz(100_000),
@ -407,20 +433,6 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
} }
} }
struct PllInput {
hsi: Option<Hertz>,
hse: Option<Hertz>,
msi: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
struct PllOutput {
p: Option<Hertz>,
q: Option<Hertz>,
r: Option<Hertz>,
}
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance { enum PllInstance {
Pll, Pll,
@ -449,20 +461,124 @@ fn pll_enable(instance: PllInstance, enabled: bool) {
} }
} }
fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { pub use pll::*;
#[cfg(any(stm32l0, stm32l1))]
mod pll {
use super::{pll_enable, PllInstance};
pub use crate::pac::rcc::vals::{Plldiv as PllDiv, Pllmul as PllMul, Pllsrc as PllSource};
use crate::pac::RCC;
use crate::time::Hertz;
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PllSource,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL main output division factor.
pub div: PllDiv,
}
pub(super) struct PllInput {
pub hsi: Option<Hertz>,
pub hse: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
pub(super) struct PllOutput {
pub r: Option<Hertz>,
pub clk48: Option<Hertz>,
}
pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL // Disable PLL
pll_enable(instance, false); pll_enable(instance, false);
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::DISABLE => panic!("must not select PLL source as DISABLE"), PllSource::HSE => unwrap!(input.hse),
PLLSource::HSE => input.hse, PllSource::HSI => unwrap!(input.hsi),
PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi,
}; };
let pll_src = pll_src.unwrap(); 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));
RCC.cfgr().write(move |w| {
w.set_pllmul(pll.mul);
w.set_plldiv(pll.div);
w.set_pllsrc(pll.source);
});
// Enable PLL
pll_enable(instance, true);
PllOutput { r: Some(r), clk48 }
}
}
#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
mod pll {
use super::{pll_enable, PllInstance};
pub use crate::pac::rcc::vals::{
Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PllSource,
};
use crate::pac::RCC;
use crate::time::Hertz;
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
pub source: PllSource,
/// PLL pre-divider (DIVM).
pub prediv: PllPreDiv,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL P division factor. If None, PLL P output is disabled.
pub divp: Option<PllPDiv>,
/// PLL Q division factor. If None, PLL Q output is disabled.
pub divq: Option<PllQDiv>,
/// PLL R division factor. If None, PLL R output is disabled.
pub divr: Option<PllRDiv>,
}
pub(super) struct PllInput {
pub hsi: Option<Hertz>,
pub hse: Option<Hertz>,
pub msi: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
pub(super) struct PllOutput {
pub p: Option<Hertz>,
pub q: Option<Hertz>,
pub r: Option<Hertz>,
}
pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
pll_enable(instance, false);
let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source {
PllSource::DISABLE => panic!("must not select PLL source as DISABLE"),
PllSource::HSE => unwrap!(input.hse),
PllSource::HSI => unwrap!(input.hsi),
PllSource::MSI => unwrap!(input.msi),
};
let vco_freq = pll_src / pll.prediv * pll.mul; let vco_freq = pll_src / pll.prediv * pll.mul;
@ -523,3 +639,4 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
PllOutput { p, q, r } PllOutput { p, q, r }
} }
}

View File

@ -1,190 +0,0 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale;
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul,
Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
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)]
pub struct Pll {
/// PLL source
pub source: PLLSource,
/// PLL multiplication factor.
pub mul: PllMul,
/// PLL main output division factor.
pub div: PllDiv,
}
/// Clocks configutation
pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
pub hsi: bool,
pub hse: Option<Hse>,
#[cfg(crs)]
pub hsi48: Option<super::Hsi48Config>,
pub pll: Option<Pll>,
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
pub voltage_scale: VoltageScale,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
msi: Some(MSIRange::RANGE5),
hse: None,
hsi: false,
#[cfg(crs)]
hsi48: Some(Default::default()),
pll: None,
mux: ClockSrc::MSI,
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
voltage_scale: VoltageScale::RANGE1,
ls: Default::default(),
}
}
}
pub(crate) unsafe fn init(config: Config) {
// Set voltage scale
while PWR.csr().read().vosf() {}
PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while PWR.csr().read().vosf() {}
let rtc = config.ls.init();
let msi = config.msi.map(|range| {
RCC.icscr().modify(|w| w.set_msirange(range));
RCC.cr().modify(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {}
Hertz(32_768 * (1 << (range as u8 + 1)))
});
let hsi = config.hsi.then(|| {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
});
let hse = config.hse.map(|hse| {
RCC.cr().modify(|w| {
w.set_hsebyp(hse.mode == HseMode::Bypass);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
hse.freq
});
let pll = config.pll.map(|pll| {
let freq = match pll.source {
PLLSource::HSE => hse.unwrap(),
PLLSource::HSI => hsi.unwrap(),
};
// Disable PLL
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
let freq = freq * pll.mul / pll.div;
assert!(freq <= Hertz(32_000_000));
RCC.cfgr().write(move |w| {
w.set_pllmul(pll.mul);
w.set_plldiv(pll.div);
w.set_pllsrc(pll.source);
});
// Enable PLL
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
freq
});
let sys_clk = match config.mux {
ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI => hsi.unwrap(),
ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL1_P => pll.unwrap(),
};
let wait_states = match (config.voltage_scale, sys_clk.0) {
(VoltageScale::RANGE1, ..=16_000_000) => 0,
(VoltageScale::RANGE2, ..=8_000_000) => 0,
(VoltageScale::RANGE3, ..=4_200_000) => 0,
_ => 1,
};
#[cfg(stm32l1)]
FLASH.acr().write(|w| w.set_acc64(true));
FLASH.acr().modify(|w| w.set_prften(true));
FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
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);
});
let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(crs)]
let _hsi48 = config.hsi48.map(|config| {
// Select HSI48 as USB clock
RCC.ccipr().modify(|w| w.set_hsi48msel(true));
super::init_hsi48(config)
});
set_freqs(Clocks {
sys: sys_clk,
hclk1,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
rtc,
});
}

View File

@ -23,8 +23,7 @@ pub use hsi48::*;
#[cfg_attr(rcc_g0, path = "g0.rs")] #[cfg_attr(rcc_g0, path = "g0.rs")]
#[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(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")]
mod _version; mod _version;

View File

@ -35,7 +35,7 @@ impl Default for ClockSrc {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct PllConfig { pub struct PllConfig {
/// The clock source for the PLL. /// The clock source for the PLL.
pub source: PllSrc, pub source: PllSource,
/// The PLL prescaler. /// The PLL prescaler.
/// ///
/// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
@ -57,7 +57,7 @@ impl PllConfig {
/// A configuration for HSI / 1 * 10 / 1 = 160 MHz /// A configuration for HSI / 1 * 10 / 1 = 160 MHz
pub const fn hsi_160mhz() -> Self { pub const fn hsi_160mhz() -> Self {
PllConfig { PllConfig {
source: PllSrc::HSI, source: PllSource::HSI,
m: Pllm::DIV1, m: Pllm::DIV1,
n: Plln::MUL10, n: Plln::MUL10,
r: Plldiv::DIV1, r: Plldiv::DIV1,
@ -67,7 +67,7 @@ impl PllConfig {
/// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
pub const fn msis_160mhz() -> Self { pub const fn msis_160mhz() -> Self {
PllConfig { PllConfig {
source: PllSrc::MSIS(Msirange::RANGE_48MHZ), source: PllSource::MSIS(Msirange::RANGE_48MHZ),
m: Pllm::DIV3, m: Pllm::DIV3,
n: Plln::MUL10, n: Plln::MUL10,
r: Plldiv::DIV1, r: Plldiv::DIV1,
@ -76,7 +76,7 @@ impl PllConfig {
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum PllSrc { pub enum PllSource {
/// Use an internal medium speed oscillator as the PLL source. /// Use an internal medium speed oscillator as the PLL source.
MSIS(Msirange), MSIS(Msirange),
/// Use the external high speed clock as the system PLL source. /// Use the external high speed clock as the system PLL source.
@ -88,12 +88,12 @@ pub enum PllSrc {
HSI, HSI,
} }
impl Into<Pllsrc> for PllSrc { impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc { fn into(self) -> Pllsrc {
match self { match self {
PllSrc::MSIS(..) => Pllsrc::MSIS, PllSource::MSIS(..) => Pllsrc::MSIS,
PllSrc::HSE(..) => Pllsrc::HSE, PllSource::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI, PllSource::HSI => Pllsrc::HSI,
} }
} }
} }
@ -216,9 +216,9 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::PLL1_R(pll) => { ClockSrc::PLL1_R(pll) => {
// Configure the PLL source // Configure the PLL source
let source_clk = match pll.source { let source_clk = match pll.source {
PllSrc::MSIS(range) => config.init_msis(range), PllSource::MSIS(range) => config.init_msis(range),
PllSrc::HSE(hertz) => config.init_hse(hertz), PllSource::HSE(hertz) => config.init_hse(hertz),
PllSrc::HSI => config.init_hsi(), PllSource::HSI => config.init_hsi(),
}; };
// Calculate the reference clock, which is the source divided by m // Calculate the reference clock, which is the source divided by m

View File

@ -17,16 +17,16 @@ pub enum ClockSrc {
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum PllSrc { pub enum PllSource {
HSE(Hertz), HSE(Hertz),
HSI, HSI,
} }
impl Into<Pllsrc> for PllSrc { impl Into<Pllsrc> for PllSource {
fn into(self) -> Pllsrc { fn into(self) -> Pllsrc {
match self { match self {
PllSrc::HSE(..) => Pllsrc::HSE, PllSource::HSE(..) => Pllsrc::HSE,
PllSrc::HSI => Pllsrc::HSI, PllSource::HSI => Pllsrc::HSI,
} }
} }
} }

View File

@ -7,7 +7,7 @@ use core::convert::TryFrom;
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ use embassy_stm32::rcc::{
APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc, APBPrescaler, ClockSrc, HSEConfig, HSESrc, Pll, PllMul, PllPDiv, PllPreDiv, PllQDiv, PllSource,
}; };
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::Config; use embassy_stm32::Config;
@ -25,16 +25,16 @@ async fn main(_spawner: Spawner) {
source: HSESrc::Bypass, source: HSESrc::Bypass,
}); });
// PLL uses HSE as the clock source // PLL uses HSE as the clock source
config.rcc.pll_mux = PLLSrc::HSE; config.rcc.pll_mux = PllSource::HSE;
config.rcc.pll = PLLConfig { config.rcc.pll = Pll {
// 8 MHz clock source / 8 = 1 MHz PLL input // 8 MHz clock source / 8 = 1 MHz PLL input
pre_div: unwrap!(PLLPreDiv::try_from(8)), pre_div: unwrap!(PllPreDiv::try_from(8)),
// 1 MHz PLL input * 240 = 240 MHz PLL VCO // 1 MHz PLL input * 240 = 240 MHz PLL VCO
mul: unwrap!(PLLMul::try_from(240)), mul: unwrap!(PllMul::try_from(240)),
// 240 MHz PLL VCO / 2 = 120 MHz main PLL output // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
p_div: PLLPDiv::DIV2, divp: PllPDiv::DIV2,
// 240 MHz PLL VCO / 5 = 48 MHz PLL48 output // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
q_div: PLLQDiv::DIV5, divq: PllQDiv::DIV5,
}; };
// System clock comes from PLL (= the 120 MHz main PLL output) // System clock comes from PLL (= the 120 MHz main PLL output)
config.rcc.mux = ClockSrc::PLL; config.rcc.mux = ClockSrc::PLL;

View File

@ -5,7 +5,7 @@
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, ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSource};
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 _};
@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PllSrc::HSI, source: PllSource::HSI,
prediv_m: PllM::DIV4, prediv_m: PllM::DIV4,
mul_n: PllN::MUL85, mul_n: PllN::MUL85,
div_p: None, div_p: None,

View File

@ -4,7 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSrc}; use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSource};
use embassy_stm32::Config; use embassy_stm32::Config;
use embassy_time::Timer; use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PllSrc::HSI, source: PllSource::HSI,
prediv_m: PllM::DIV4, prediv_m: PllM::DIV4,
mul_n: PllN::MUL85, mul_n: PllN::MUL85,
div_p: None, div_p: None,

View File

@ -4,7 +4,7 @@
use defmt::{panic, *}; use defmt::{panic, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{Clock48MhzSrc, ClockSrc, Hsi48Config, Pll, PllM, PllN, PllQ, PllR, PllSrc}; use embassy_stm32::rcc::{Clock48MhzSrc, ClockSrc, Hsi48Config, Pll, PllM, PllN, PllQ, PllR, PllSource};
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};
@ -25,14 +25,14 @@ async fn main(_spawner: Spawner) {
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
const USE_HSI48: bool = true; const USE_HSI48: bool = true;
let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) }; let plldivq = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PllSrc::HSE(Hertz(8_000_000)), source: PllSource::HSE(Hertz(8_000_000)),
prediv_m: PllM::DIV2, prediv_m: PllM::DIV2,
mul_n: PllN::MUL72, mul_n: PllN::MUL72,
div_p: None, div_p: None,
div_q: pllq_div, div_q: plldivq,
// Main system clock at 144 MHz // Main system clock at 144 MHz
div_r: Some(PllR::DIV2), div_r: Some(PllR::DIV2),
}); });

View File

@ -4,7 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv}; use embassy_stm32::rcc::{ClockSrc, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, PllSource};
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -19,7 +19,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL18, mul: PllMul::MUL18,
divp: None, divp: None,

View File

@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) {
mode: HseMode::Oscillator, mode: HseMode::Oscillator,
}); });
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20, mul: PllMul::MUL20,
divp: None, divp: None,

View File

@ -75,7 +75,7 @@ async fn main(spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) // 80Mhz clock (Source: 8 / SrcDiv: 1 * PllMul 20 / ClkDiv 2)
// 80MHz highest frequency for flash 0 wait. // 80MHz highest frequency for flash 0 wait.
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
@ -83,7 +83,7 @@ async fn main(spawner: Spawner) {
mode: HseMode::Oscillator, mode: HseMode::Oscillator,
}); });
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20, mul: PllMul::MUL20,
divp: None, divp: None,

View File

@ -27,7 +27,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10, mul: PllMul::MUL10,
divp: None, divp: None,

View File

@ -4,7 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv}; use embassy_stm32::rcc::{ClockSrc, Pll, PllMul, PllPreDiv, PllRDiv, PllSource};
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -20,7 +20,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
// 64Mhz clock (16 / 1 * 8 / 2) // 64Mhz clock (16 / 1 * 8 / 2)
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL8, mul: PllMul::MUL8,
divp: None, divp: None,

View File

@ -49,7 +49,7 @@ async fn main(spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2) // 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10, mul: PllMul::MUL10,
divp: None, divp: None,

View File

@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2) // 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10, mul: PllMul::MUL10,
divp: None, divp: None,

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
// 80Mhz clock (16 / 1 * 10 / 2) // 80Mhz clock (16 / 1 * 10 / 2)
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10, mul: PllMul::MUL10,
divp: None, divp: None,

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.mux = ClockSrc::PLL1_R(PllConfig { config.rcc.mux = ClockSrc::PLL1_R(PllConfig {
source: PllSrc::HSI, source: PllSource::HSI,
m: Pllm::DIV2, m: Pllm::DIV2,
n: Plln::MUL10, n: Plln::MUL10,
r: Plldiv::DIV1, r: Plldiv::DIV1,

View File

@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,

View File

@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,

View File

@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,

View File

@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,

View File

@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,

View File

@ -241,16 +241,16 @@ pub fn config() -> Config {
source: HSESrc::Bypass, source: HSESrc::Bypass,
}); });
// PLL uses HSE as the clock source // PLL uses HSE as the clock source
config.rcc.pll_mux = PLLSrc::HSE; config.rcc.pll_mux = PllSource::HSE;
config.rcc.pll = PLLConfig { config.rcc.pll = Pll {
// 8 MHz clock source / 8 = 1 MHz PLL input // 8 MHz clock source / 8 = 1 MHz PLL input
pre_div: unwrap!(PLLPreDiv::try_from(8)), pre_div: unwrap!(PllPreDiv::try_from(8)),
// 1 MHz PLL input * 240 = 240 MHz PLL VCO // 1 MHz PLL input * 240 = 240 MHz PLL VCO
mul: unwrap!(PLLMul::try_from(240)), mul: unwrap!(PllMul::try_from(240)),
// 240 MHz PLL VCO / 2 = 120 MHz main PLL output // 240 MHz PLL VCO / 2 = 120 MHz main PLL output
p_div: PLLPDiv::DIV2, divp: PllPDiv::DIV2,
// 240 MHz PLL VCO / 5 = 48 MHz PLL48 output // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output
q_div: PLLQDiv::DIV5, divq: PllQDiv::DIV5,
}; };
// System clock comes from PLL (= the 120 MHz main PLL output) // System clock comes from PLL (= the 120 MHz main PLL output)
config.rcc.mux = ClockSrc::PLL; config.rcc.mux = ClockSrc::PLL;
@ -397,7 +397,7 @@ pub fn config() -> Config {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hsi = true; config.rcc.hsi = true;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
mul: PllMul::MUL18, mul: PllMul::MUL18,
divp: None, divp: None,
@ -416,7 +416,7 @@ pub fn config() -> Config {
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
source: PLLSource::HSE, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6, mul: PllMul::MUL6,
divp: None, divp: None,
@ -432,7 +432,7 @@ pub fn config() -> Config {
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {
// 110Mhz clock (16 / 4 * 55 / 2) // 110Mhz clock (16 / 4 * 55 / 2)
source: PLLSource::HSI, source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL55, mul: PllMul::MUL55,
divp: None, divp: None,
@ -462,11 +462,11 @@ pub fn config() -> Config {
use embassy_stm32::rcc::*; 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,
mul: PLLMul::MUL4, mul: PllMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2) div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
}); });
config.rcc.mux = ClockSrc::PLL1_P; config.rcc.mux = ClockSrc::PLL1_R;
} }
#[cfg(any(feature = "stm32l152re"))] #[cfg(any(feature = "stm32l152re"))]
@ -474,11 +474,11 @@ pub fn config() -> Config {
use embassy_stm32::rcc::*; 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,
mul: PLLMul::MUL4, mul: PllMul::MUL4,
div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2) div: PllDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
}); });
config.rcc.mux = ClockSrc::PLL1_P; config.rcc.mux = ClockSrc::PLL1_R;
} }
config config