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

stm32/rcc: merge wb into l4/l5.
This commit is contained in:
Dario Nieuwenhuis 2023-10-23 16:21:17 +00:00 committed by GitHub
commit d673f8a865
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 327 additions and 529 deletions

4
ci.sh
View file

@ -221,8 +221,8 @@ rm out/tests/stm32wb55rg/wpan_ble
# unstable, I think it's running out of RAM? # unstable, I think it's running out of RAM?
rm out/tests/stm32f207zg/eth rm out/tests/stm32f207zg/eth
# doesn't work. Wire in D0-D1 might be bad, or the special IOVDD2 PGx pins. # doesn't work, gives "noise error", no idea why. usart_dma does pass.
rm out/tests/stm32u5a5zj/{gpio,usart*} rm out/tests/stm32u5a5zj/usart
if [[ -z "${TELEPROBE_TOKEN-}" ]]; then if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
echo No teleprobe token found, skipping running HIL tests echo No teleprobe token found, skipping running HIL tests

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-4ddcb77c9d213d11eebb048f40e112bc54163cdc" } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9" }
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-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]} stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9", default-features = false, features = ["metadata"]}
[features] [features]

View file

@ -763,6 +763,13 @@ pub(crate) unsafe fn init(_cs: CriticalSection) {
<crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs);
crate::_generated::init_gpio(); crate::_generated::init_gpio();
// Setting this bit is mandatory to use PG[15:2].
#[cfg(stm32u5)]
crate::pac::PWR.svmcr().modify(|w| {
w.set_io2sv(true);
w.set_io2vmen(true);
});
} }
mod eh02 { mod eh02 {

View file

@ -166,8 +166,8 @@ pub(crate) unsafe fn init(config: Config) {
}; };
let hclk = sys / config.ahb_pre; let hclk = sys / config.ahb_pre;
let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre); let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
assert!(max::SYSCLK.contains(&sys)); assert!(max::SYSCLK.contains(&sys));
assert!(max::HCLK.contains(&hclk)); assert!(max::HCLK.contains(&hclk));
@ -326,15 +326,6 @@ fn flash_setup(clk: Hertz) {
while FLASH.acr().read().latency() != latency {} while FLASH.acr().read().latency() != latency {}
} }
fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
where
Hertz: core::ops::Div<D, Output = Hertz>,
{
let pclk = hclk / ppre;
let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
(pclk, pclk_tim)
}
#[cfg(stm32f7)] #[cfg(stm32f7)]
mod max { mod max {
use core::ops::RangeInclusive; use core::ops::RangeInclusive;

View file

@ -6,8 +6,11 @@ use crate::pac::pwr::vals::Vos;
pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
#[cfg(stm32h7)] #[cfg(stm32h7)]
pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; pub use crate::pac::rcc::vals::{
pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; Ckpersel as PerClockSource, 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::{FLASH, PWR, RCC}; use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks}; use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz; use crate::time::Hertz;
@ -58,41 +61,9 @@ pub struct Hse {
pub mode: HseMode, pub mode: HseMode,
} }
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Hsi {
/// 64Mhz
Mhz64,
/// 32Mhz (divided by 2)
Mhz32,
/// 16Mhz (divided by 4)
Mhz16,
/// 8Mhz (divided by 8)
Mhz8,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Sysclk {
/// HSI selected as sysclk
HSI,
/// HSE selected as sysclk
HSE,
/// CSI selected as sysclk
CSI,
/// PLL1_P selected as sysclk
Pll1P,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum PllSource {
Hsi,
Csi,
Hse,
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Pll { pub struct Pll {
/// Source clock selection. /// Source clock selection.
#[cfg(stm32h5)]
pub source: PllSource, pub source: PllSource,
/// PLL pre-divider (DIVM). /// PLL pre-divider (DIVM).
@ -152,15 +123,12 @@ impl From<TimerPrescaler> for Timpre {
/// Configuration of the core clocks /// Configuration of the core clocks
#[non_exhaustive] #[non_exhaustive]
pub struct Config { pub struct Config {
pub hsi: Option<Hsi>, pub hsi: Option<HSIPrescaler>,
pub hse: Option<Hse>, pub hse: Option<Hse>,
pub csi: bool, pub csi: bool,
pub hsi48: bool, pub hsi48: bool,
pub sys: Sysclk, pub sys: Sysclk,
#[cfg(stm32h7)]
pub pll_src: PllSource,
pub pll1: Option<Pll>, pub pll1: Option<Pll>,
pub pll2: Option<Pll>, pub pll2: Option<Pll>,
#[cfg(any(rcc_h5, stm32h7))] #[cfg(any(rcc_h5, stm32h7))]
@ -184,13 +152,11 @@ pub struct Config {
impl Default for Config { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
hsi: Some(Hsi::Mhz64), hsi: Some(HSIPrescaler::DIV1),
hse: None, hse: None,
csi: false, csi: false,
hsi48: false, hsi48: false,
sys: Sysclk::HSI, sys: Sysclk::HSI,
#[cfg(stm32h7)]
pll_src: PllSource::Hsi,
pll1: None, pll1: None,
pll2: None, pll2: None,
#[cfg(any(rcc_h5, stm32h7))] #[cfg(any(rcc_h5, stm32h7))]
@ -303,19 +269,13 @@ pub(crate) unsafe fn init(config: Config) {
RCC.cr().modify(|w| w.set_hsion(false)); RCC.cr().modify(|w| w.set_hsion(false));
None None
} }
Some(hsi) => { Some(hsidiv) => {
let (freq, hsidiv) = match hsi {
Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
};
RCC.cr().modify(|w| { RCC.cr().modify(|w| {
w.set_hsidiv(hsidiv); w.set_hsidiv(hsidiv);
w.set_hsion(true); w.set_hsion(true);
}); });
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
Some(freq) Some(HSI_FREQ / hsidiv)
} }
}; };
@ -360,25 +320,29 @@ pub(crate) unsafe fn init(config: Config) {
} }
}; };
// Configure PLLs. // H7 has shared PLLSRC, check it's equal in all PLLs.
let pll_input = PllInput {
csi,
hse,
hsi,
#[cfg(stm32h7)] #[cfg(stm32h7)]
source: config.pll_src, {
let plls = [&config.pll1, &config.pll2, &config.pll3];
if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
panic!("Source must be equal across all enabled PLLs.")
}; };
}
// Configure PLLs.
let pll_input = PllInput { csi, hse, hsi };
let pll1 = init_pll(0, config.pll1, &pll_input); let pll1 = init_pll(0, config.pll1, &pll_input);
let pll2 = init_pll(1, config.pll2, &pll_input); let pll2 = init_pll(1, config.pll2, &pll_input);
#[cfg(any(rcc_h5, stm32h7))] #[cfg(any(rcc_h5, stm32h7))]
let pll3 = init_pll(2, config.pll3, &pll_input); let pll3 = init_pll(2, config.pll3, &pll_input);
// Configure sysclk // Configure sysclk
let (sys, sw) = match config.sys { let sys = match config.sys {
Sysclk::HSI => (unwrap!(hsi), Sw::HSI), Sysclk::HSI => unwrap!(hsi),
Sysclk::HSE => (unwrap!(hse), Sw::HSE), Sysclk::HSE => unwrap!(hse),
Sysclk::CSI => (unwrap!(csi), Sw::CSI), Sysclk::CSI => unwrap!(csi),
Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P), Sysclk::PLL1_P => unwrap!(pll1.p),
_ => unreachable!(),
}; };
// Check limits. // Check limits.
@ -502,8 +466,8 @@ pub(crate) unsafe fn init(config: Config) {
RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into())); RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
RCC.cfgr().modify(|w| w.set_sw(sw)); RCC.cfgr().modify(|w| w.set_sw(config.sys));
while RCC.cfgr().read().sws() != sw {} while RCC.cfgr().read().sws() != config.sys {}
// IO compensation cell - Requires CSI clock and SYSCFG // IO compensation cell - Requires CSI clock and SYSCFG
#[cfg(stm32h7)] // TODO h5 #[cfg(stm32h7)] // TODO h5
@ -588,8 +552,6 @@ struct PllInput {
hsi: Option<Hertz>, hsi: Option<Hertz>,
hse: Option<Hertz>, hse: Option<Hertz>,
csi: Option<Hertz>, csi: Option<Hertz>,
#[cfg(stm32h7)]
source: PllSource,
} }
struct PllOutput { struct PllOutput {
@ -619,15 +581,11 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
}; };
}; };
#[cfg(stm32h5)] let in_clk = match config.source {
let source = config.source; PllSource::DISABLE => panic!("must not set PllSource::Disable"),
#[cfg(stm32h7)] PllSource::HSI => unwrap!(input.hsi),
let source = input.source; PllSource::HSE => unwrap!(input.hse),
PllSource::CSI => unwrap!(input.csi),
let (in_clk, src) = match source {
PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
}; };
let ref_clk = in_clk / config.prediv as u32; let ref_clk = in_clk / config.prediv as u32;
@ -667,7 +625,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
#[cfg(stm32h5)] #[cfg(stm32h5)]
RCC.pllcfgr(num).write(|w| { RCC.pllcfgr(num).write(|w| {
w.set_pllsrc(src); w.set_pllsrc(config.source);
w.set_divm(config.prediv); w.set_divm(config.prediv);
w.set_pllvcosel(vco_range); w.set_pllvcosel(vco_range);
w.set_pllrge(ref_range); w.set_pllrge(ref_range);
@ -681,7 +639,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
{ {
RCC.pllckselr().modify(|w| { RCC.pllckselr().modify(|w| {
w.set_divm(num, config.prediv); w.set_divm(num, config.prediv);
w.set_pllsrc(src); w.set_pllsrc(config.source);
}); });
RCC.pllcfgr().modify(|w| { RCC.pllcfgr().modify(|w| {
w.set_pllvcosel(num, vco_range); w.set_pllvcosel(num, vco_range);

View file

@ -156,23 +156,9 @@ pub(crate) unsafe fn init(config: Config) {
w.set_ppre2(config.apb2_pre); w.set_ppre2(config.apb2_pre);
}); });
let ahb_freq = 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 (apb1_freq, apb1_tim_freq) = match config.apb1_pre { let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_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)
}
};
#[cfg(crs)] #[cfg(crs)]
if config.enable_hsi48 { if config.enable_hsi48 {
@ -209,11 +195,11 @@ pub(crate) unsafe fn init(config: Config) {
set_freqs(Clocks { set_freqs(Clocks {
sys: sys_clk, sys: sys_clk,
hclk1: ahb_freq, hclk1,
pclk1: apb1_freq, pclk1,
pclk2: apb2_freq, pclk2,
pclk1_tim: apb1_tim_freq, pclk1_tim,
pclk2_tim: apb2_tim_freq, pclk2_tim,
rtc, rtc,
}); });
} }

View file

@ -1,7 +1,8 @@
use crate::pac::rcc::regs::Cfgr; use crate::pac::rcc::regs::Cfgr;
#[cfg(not(stm32wl))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src; pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
use crate::pac::rcc::vals::Msirgsel; #[cfg(any(stm32wb, stm32wl))]
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, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, 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, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
@ -27,6 +28,9 @@ pub struct Hse {
pub freq: Hertz, pub freq: Hertz,
/// HSE mode. /// HSE mode.
pub mode: HseMode, pub mode: HseMode,
/// HSE prescaler
#[cfg(any(stm32wb, stm32wl))]
pub prescaler: HsePrescaler,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -54,12 +58,12 @@ pub struct Config {
pub msi: Option<MSIRange>, pub msi: Option<MSIRange>,
pub hsi: bool, pub hsi: bool,
pub hse: Option<Hse>, pub hse: Option<Hse>,
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
pub hsi48: bool, pub hsi48: bool,
// pll // pll
pub pll: Option<Pll>, pub pll: Option<Pll>,
#[cfg(any(stm32l4, stm32l5))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
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>,
@ -69,11 +73,13 @@ 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)] #[cfg(any(stm32wl5x, stm32wb))]
pub core2_ahb_pre: AHBPrescaler,
#[cfg(any(stm32wl, stm32wb))]
pub shared_ahb_pre: AHBPrescaler, pub shared_ahb_pre: AHBPrescaler,
// muxes // muxes
#[cfg(not(stm32wl))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
pub clk48_src: Clk48Src, pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC // low speed LSI/LSE/RTC
@ -91,28 +97,63 @@ 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)] #[cfg(any(stm32wl5x, stm32wb))]
core2_ahb_pre: AHBPrescaler::DIV1,
#[cfg(any(stm32wl, stm32wb))]
shared_ahb_pre: AHBPrescaler::DIV1, shared_ahb_pre: AHBPrescaler::DIV1,
pll: None, pll: None,
#[cfg(any(stm32l4, stm32l5))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
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(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
hsi48: true, hsi48: true,
#[cfg(not(stm32wl))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48, clk48_src: Clk48Src::HSI48,
ls: Default::default(), ls: Default::default(),
} }
} }
} }
#[cfg(stm32wb)]
pub const WPAN_DEFAULT: Config = Config {
hse: Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Oscillator,
prescaler: HsePrescaler::DIV1,
}),
mux: ClockSrc::PLL1_R,
hsi48: true,
msi: None,
hsi: false,
clk48_src: Clk48Src::PLL1_Q,
ls: super::LsConfig::default_lse(),
pll: Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL12,
divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
divq: Some(PllQDiv::DIV4), // 32 / 2 * 12 / 4 = 48Mhz
divr: Some(PllRDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
}),
pllsai1: None,
ahb_pre: AHBPrescaler::DIV1,
core2_ahb_pre: AHBPrescaler::DIV2,
shared_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
};
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| { RCC.cr().modify(|w| {
w.set_msirgsel(Msirgsel::CR); #[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(MSIRange::RANGE4M); w.set_msirange(MSIRange::RANGE4M);
w.set_msipllen(false); w.set_msipllen(false);
w.set_msion(true) w.set_msion(true)
@ -138,8 +179,9 @@ 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().modify(|w| { RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(range); w.set_msirange(range);
w.set_msirgsel(Msirgsel::CR);
w.set_msion(true); w.set_msion(true);
// If LSE is enabled, enable calibration of MSI // If LSE is enabled, enable calibration of MSI
@ -173,7 +215,7 @@ pub(crate) unsafe fn init(config: Config) {
hse.freq hse.freq
}); });
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
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() {}
@ -185,7 +227,7 @@ pub(crate) unsafe fn init(config: Config) {
let _plls = [ let _plls = [
&config.pll, &config.pll,
#[cfg(any(stm32l4, stm32l5))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
&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,
@ -193,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) {
// L4 has shared PLLSRC, PLLM, check it's equal in all PLLs. // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs.
#[cfg(all(stm32l4, not(rcc_l4plus)))] #[cfg(all(stm32l4, not(rcc_l4plus)))]
match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) { match super::util::get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
Err(()) => panic!("Source must be equal across all enabled PLLs."), Err(()) => panic!("Source must be equal across all enabled PLLs."),
Ok(None) => {} Ok(None) => {}
Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| { Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| {
@ -204,7 +246,7 @@ pub(crate) unsafe fn init(config: Config) {
// L4+, WL 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, stm32wl))] #[cfg(any(rcc_l4plus, stm32wl))]
match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { match super::util::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) => {}
Ok(Some(source)) => RCC.pllcfgr().write(|w| { Ok(Some(source)) => RCC.pllcfgr().write(|w| {
@ -214,7 +256,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))] #[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);
#[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);
@ -223,19 +265,19 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::HSE => hse.unwrap(), ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI => hsi.unwrap(), ClockSrc::HSI => hsi.unwrap(),
ClockSrc::MSI => msi.unwrap(), ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL1_R => pll._r.unwrap(), ClockSrc::PLL1_R => pll.r.unwrap(),
}; };
#[cfg(stm32l4)] #[cfg(stm32l4)]
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))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
let _clk48 = match config.clk48_src { let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => hsi48, Clk48Src::HSI48 => hsi48,
Clk48Src::MSI => msi, Clk48Src::MSI => msi,
Clk48Src::PLLSAI1_Q => pllsai1._q, Clk48Src::PLLSAI1_Q => pllsai1.q,
Clk48Src::PLL1_Q => pll._q, Clk48Src::PLL1_Q => pll.q,
}; };
#[cfg(rcc_l4plus)] #[cfg(rcc_l4plus)]
@ -243,30 +285,21 @@ 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);
let ahb_freq = 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 (apb1_freq, apb1_tim_freq) = match config.apb1_pre { let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
APBPrescaler::DIV1 => (ahb_freq, ahb_freq), #[cfg(not(any(stm32wl5x, stm32wb)))]
pre => { let hclk2 = hclk1;
let freq = ahb_freq / pre; #[cfg(any(stm32wl5x, stm32wb))]
(freq, freq * 2u32) let hclk2 = sys_clk / config.core2_ahb_pre;
} #[cfg(not(any(stm32wl, stm32wb)))]
}; let hclk3 = hclk1;
#[cfg(any(stm32wl, stm32wb))]
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { let hclk3 = sys_clk / config.shared_ahb_pre;
APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
pre => {
let freq = ahb_freq / pre;
(freq, freq * 2u32)
}
};
#[cfg(stm32wl)]
let ahb3_freq = sys_clk / config.shared_ahb_pre;
// Set flash wait states // Set flash wait states
#[cfg(stm32l4)] #[cfg(stm32l4)]
let latency = match sys_clk.0 { let latency = match hclk1.0 {
0..=16_000_000 => 0, 0..=16_000_000 => 0,
0..=32_000_000 => 1, 0..=32_000_000 => 1,
0..=48_000_000 => 2, 0..=48_000_000 => 2,
@ -274,7 +307,7 @@ pub(crate) unsafe fn init(config: Config) {
_ => 4, _ => 4,
}; };
#[cfg(stm32l5)] #[cfg(stm32l5)]
let latency = match sys_clk.0 { let latency = match hclk1.0 {
// VCORE Range 0 (performance), others TODO // VCORE Range 0 (performance), others TODO
0..=20_000_000 => 0, 0..=20_000_000 => 0,
0..=40_000_000 => 1, 0..=40_000_000 => 1,
@ -284,12 +317,21 @@ pub(crate) unsafe fn init(config: Config) {
_ => 5, _ => 5,
}; };
#[cfg(stm32wl)] #[cfg(stm32wl)]
let latency = match ahb3_freq.0 { let latency = match hclk3.0 {
// VOS RANGE1, others TODO. // VOS RANGE1, others TODO.
..=18_000_000 => 0, ..=18_000_000 => 0,
..=36_000_000 => 1, ..=36_000_000 => 1,
_ => 2, _ => 2,
}; };
#[cfg(stm32wb)]
let latency = match hclk3.0 {
// VOS RANGE1, others TODO.
..=18_000_000 => 0,
..=36_000_000 => 1,
..=54_000_000 => 2,
..=64_000_000 => 3,
_ => 4,
};
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 {}
@ -302,28 +344,29 @@ pub(crate) unsafe fn init(config: Config) {
}); });
while RCC.cfgr().read().sws() != config.mux {} while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32wl)] #[cfg(any(stm32wl, stm32wb))]
{ {
RCC.extcfgr().modify(|w| { RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shared_ahb_pre); w.set_shdhpre(config.shared_ahb_pre);
#[cfg(any(stm32wl5x, stm32wb))]
w.set_c2hpre(config.core2_ahb_pre);
}); });
while !RCC.extcfgr().read().shdhpref() {} while !RCC.extcfgr().read().shdhpref() {}
#[cfg(any(stm32wl5x, stm32wb))]
while !RCC.extcfgr().read().c2hpref() {}
} }
set_freqs(Clocks { set_freqs(Clocks {
sys: sys_clk, sys: sys_clk,
hclk1: ahb_freq, hclk1,
hclk2: ahb_freq, hclk2,
#[cfg(not(stm32wl))] hclk3,
hclk3: ahb_freq, pclk1,
pclk1: apb1_freq, pclk2,
pclk2: apb2_freq, pclk1_tim,
pclk1_tim: apb1_tim_freq, pclk2_tim,
pclk2_tim: apb2_tim_freq,
#[cfg(stm32wl)] #[cfg(stm32wl)]
hclk3: ahb3_freq, pclk3: hclk3,
#[cfg(stm32wl)]
pclk3: ahb3_freq,
#[cfg(rcc_l4)] #[cfg(rcc_l4)]
hsi: None, hsi: None,
#[cfg(rcc_l4)] #[cfg(rcc_l4)]
@ -362,60 +405,56 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
} }
} }
#[allow(unused)]
fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
let Some(x) = iter.next() else { return Ok(None) };
if !iter.all(|y| y == x) {
return Err(());
}
return Ok(Some(x));
}
struct PllInput { struct PllInput {
hsi: Option<Hertz>, hsi: Option<Hertz>,
hse: Option<Hertz>, hse: Option<Hertz>,
msi: Option<Hertz>, msi: Option<Hertz>,
} }
#[allow(unused)]
#[derive(Default)] #[derive(Default)]
struct PllOutput { struct PllOutput {
_p: Option<Hertz>, p: Option<Hertz>,
_q: Option<Hertz>, q: Option<Hertz>,
_r: Option<Hertz>, r: Option<Hertz>,
} }
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance { enum PllInstance {
Pll, Pll,
#[cfg(any(stm32l4, stm32l5))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
Pllsai1, Pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
Pllsai2, Pllsai2,
} }
fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { fn pll_enable(instance: PllInstance, enabled: bool) {
// Disable PLL
match instance { match instance {
PllInstance::Pll => { PllInstance::Pll => {
RCC.cr().modify(|w| w.set_pllon(false)); RCC.cr().modify(|w| w.set_pllon(enabled));
while RCC.cr().read().pllrdy() {} while RCC.cr().read().pllrdy() != enabled {}
} }
#[cfg(any(stm32l4, stm32l5))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
PllInstance::Pllsai1 => { PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(false)); RCC.cr().modify(|w| w.set_pllsai1on(enabled));
while RCC.cr().read().pllsai1rdy() {} while RCC.cr().read().pllsai1rdy() != enabled {}
} }
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => { PllInstance::Pllsai2 => {
RCC.cr().modify(|w| w.set_pllsai2on(false)); RCC.cr().modify(|w| w.set_pllsai2on(enabled));
while RCC.cr().read().pllsai2rdy() {} while RCC.cr().read().pllsai2rdy() != enabled {}
} }
} }
}
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 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 NONE"), PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"),
PLLSource::HSE => input.hse, PLLSource::HSE => input.hse,
PLLSource::HSI => input.hsi, PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi, PLLSource::MSI => input.msi,
@ -459,7 +498,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))] #[cfg(any(stm32l4, stm32l5, stm32wb))]
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);
@ -478,22 +517,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
} }
// Enable PLL // Enable PLL
match instance { pll_enable(instance, true);
PllInstance::Pll => {
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
}
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(true));
while !RCC.cr().read().pllsai1rdy() {}
}
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => {
RCC.cr().modify(|w| w.set_pllsai2on(true));
while !RCC.cr().read().pllsai2rdy() {}
}
}
PllOutput { _p: p, _q: q, _r: r } PllOutput { p, q, r }
} }

View file

@ -19,9 +19,8 @@ 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, rcc_wl5, rcc_wle), path = "l4l5.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_wb, path = "wb.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")]
mod _version; mod _version;
#[cfg(feature = "low-power")] #[cfg(feature = "low-power")]
@ -247,3 +246,33 @@ pub(crate) mod sealed {
} }
pub trait RccPeripheral: sealed::RccPeripheral + 'static {} pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
#[allow(unused)]
mod util {
use crate::time::Hertz;
pub fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
where
Hertz: core::ops::Div<D, Output = Hertz>,
{
let pclk = hclk / ppre;
let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
(pclk, pclk_tim)
}
pub fn all_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> bool {
let Some(x) = iter.next() else { return true };
if !iter.all(|y| y == x) {
return false;
}
true
}
pub fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
let Some(x) = iter.next() else { return Ok(None) };
if !iter.all(|y| y == x) {
return Err(());
}
Ok(Some(x))
}
}

View file

@ -1,258 +0,0 @@
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource,
Ppre as APBPrescaler, Sw as Sysclk,
};
use crate::rcc::{set_freqs, Clocks};
use crate::time::{mhz, Hertz};
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
pub struct Hse {
pub prediv: HsePrescaler,
pub frequency: Hertz,
}
pub struct PllMux {
/// Source clock selection.
pub source: PllSource,
/// PLL pre-divider (DIVM). Must be between 1 and 63.
pub prediv: Pllm,
}
pub struct Pll {
/// PLL multiplication factor. Must be between 4 and 512.
pub mul: Plln,
/// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
/// On PLL1, it must be even (in particular, it cannot be 1.)
pub divp: Option<Pllp>,
/// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
pub divq: Option<Pllq>,
/// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
pub divr: Option<Pllr>,
}
/// Clocks configutation
pub struct Config {
pub hse: Option<Hse>,
pub sys: Sysclk,
pub mux: Option<PllMux>,
pub hsi48: bool,
pub pll: Option<Pll>,
pub pllsai: Option<Pll>,
pub ahb1_pre: AHBPrescaler,
pub ahb2_pre: AHBPrescaler,
pub ahb3_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
}
pub const WPAN_DEFAULT: Config = Config {
hse: Some(Hse {
frequency: mhz(32),
prediv: HsePrescaler::DIV1,
}),
sys: Sysclk::PLL1_R,
mux: Some(PllMux {
source: PllSource::HSE,
prediv: Pllm::DIV2,
}),
hsi48: true,
ls: super::LsConfig::default_lse(),
pll: Some(Pll {
mul: Plln::MUL12,
divp: Some(Pllp::DIV3),
divq: Some(Pllq::DIV4),
divr: Some(Pllr::DIV3),
}),
pllsai: None,
ahb1_pre: AHBPrescaler::DIV1,
ahb2_pre: AHBPrescaler::DIV2,
ahb3_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
};
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
sys: Sysclk::HSI,
hse: None,
mux: None,
pll: None,
pllsai: None,
hsi48: true,
ls: Default::default(),
ahb1_pre: AHBPrescaler::DIV1,
ahb2_pre: AHBPrescaler::DIV1,
ahb3_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
}
}
}
#[cfg(stm32wb)]
/// RCC initialization function
pub(crate) unsafe fn init(config: Config) {
let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv);
let mux_clk = config.mux.as_ref().map(|pll_mux| {
(match pll_mux.source {
PllSource::HSE => hse_clk.unwrap(),
PllSource::HSI => HSI_FREQ,
_ => unreachable!(),
} / pll_mux.prediv)
});
let (pll_r, _pll_q, _pll_p) = match &config.pll {
Some(pll) => {
let pll_vco = mux_clk.unwrap() * pll.mul as u32;
(
pll.divr.map(|divr| pll_vco / divr),
pll.divq.map(|divq| pll_vco / divq),
pll.divp.map(|divp| pll_vco / divp),
)
}
None => (None, None, None),
};
let sys_clk = match config.sys {
Sysclk::HSE => hse_clk.unwrap(),
Sysclk::HSI => HSI_FREQ,
Sysclk::PLL1_R => pll_r.unwrap(),
_ => unreachable!(),
};
let ahb1_clk = sys_clk / config.ahb1_pre;
let ahb2_clk = sys_clk / config.ahb2_pre;
let ahb3_clk = sys_clk / config.ahb3_pre;
let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
pre => {
let freq = ahb1_clk / pre;
(freq, freq * 2u32)
}
};
let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
pre => {
let freq = ahb1_clk / pre;
(freq, freq * 2u32)
}
};
let rcc = crate::pac::RCC;
let needs_hsi = if let Some(pll_mux) = &config.mux {
pll_mux.source == PllSource::HSI
} else {
false
};
if needs_hsi || config.sys == Sysclk::HSI {
rcc.cr().modify(|w| {
w.set_hsion(true);
});
while !rcc.cr().read().hsirdy() {}
}
rcc.cfgr().modify(|w| w.set_stopwuck(true));
let rtc = config.ls.init();
match &config.hse {
Some(hse) => {
rcc.cr().modify(|w| {
w.set_hsepre(hse.prediv);
w.set_hseon(true);
});
while !rcc.cr().read().hserdy() {}
}
_ => {}
}
match &config.mux {
Some(pll_mux) => {
rcc.pllcfgr().modify(|w| {
w.set_pllm(pll_mux.prediv);
w.set_pllsrc(pll_mux.source.into());
});
}
_ => {}
};
match &config.pll {
Some(pll) => {
rcc.pllcfgr().modify(|w| {
w.set_plln(pll.mul);
pll.divp.map(|divp| {
w.set_pllpen(true);
w.set_pllp(divp)
});
pll.divq.map(|divq| {
w.set_pllqen(true);
w.set_pllq(divq)
});
pll.divr.map(|divr| {
w.set_pllren(true);
w.set_pllr(divr);
});
});
rcc.cr().modify(|w| w.set_pllon(true));
while !rcc.cr().read().pllrdy() {}
}
_ => {}
}
let _hsi48 = config.hsi48.then(|| {
rcc.crrcr().modify(|w| w.set_hsi48on(true));
while !rcc.crrcr().read().hsi48rdy() {}
Hertz(48_000_000)
});
rcc.cfgr().modify(|w| {
w.set_sw(config.sys.into());
w.set_hpre(config.ahb1_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
rcc.extcfgr().modify(|w| {
w.set_c2hpre(config.ahb2_pre);
w.set_shdhpre(config.ahb3_pre);
});
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb1_clk,
hclk2: ahb2_clk,
hclk3: ahb3_clk,
pclk1: apb1_clk,
pclk2: apb2_clk,
pclk1_tim: apb1_tim_clk,
pclk2_tim: apb2_tim_clk,
rtc,
})
}

View file

@ -43,7 +43,7 @@ async fn main(spawner: Spawner) -> ! {
mode: HseMode::BypassDigital, mode: HseMode::BypassDigital,
}); });
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::Hse, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125, mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -54,7 +54,7 @@ async fn main(spawner: Spawner) -> ! {
config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV1;
config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1;
config.rcc.apb3_pre = APBPrescaler::DIV1; config.rcc.apb3_pre = APBPrescaler::DIV1;
config.rcc.sys = Sysclk::Pll1P; config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View file

@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) {
mode: HseMode::BypassDigital, mode: HseMode::BypassDigital,
}); });
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::Hse, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125, mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2), // 250mhz divp: Some(PllDiv::DIV2), // 250mhz
@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) {
config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb1_pre = APBPrescaler::DIV4;
config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.apb2_pre = APBPrescaler::DIV2;
config.rcc.apb3_pre = APBPrescaler::DIV4; config.rcc.apb3_pre = APBPrescaler::DIV4;
config.rcc.sys = Sysclk::Pll1P; config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);

View file

@ -14,10 +14,10 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -25,13 +25,14 @@ async fn main(_spawner: Spawner) {
divr: None, divr: None,
}); });
config.rcc.pll2 = Some(Pll { config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz divp: Some(PllDiv::DIV8), // 100mhz
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -28,17 +28,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz divq: Some(PllDiv::DIV8), // 100mhz
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -16,10 +16,10 @@ fn main() -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -27,13 +27,14 @@ fn main() -> ! {
divr: None, divr: None,
}); });
config.rcc.pll2 = Some(Pll { config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz divp: Some(PllDiv::DIV8), // 100mhz
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -24,10 +24,10 @@ 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::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -35,13 +35,14 @@ async fn main(spawner: Spawner) {
divr: None, divr: None,
}); });
config.rcc.pll2 = Some(Pll { config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz divp: Some(PllDiv::DIV8), // 100mhz
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -34,18 +34,18 @@ async fn main(spawner: Spawner) -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -35,18 +35,18 @@ async fn main(spawner: Spawner) -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz divq: Some(PllDiv::DIV8), // 100mhz
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -17,18 +17,18 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz divq: Some(PllDiv::DIV8), // 100mhz
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -18,17 +18,17 @@ async fn main(_spawner: Spawner) -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -40,17 +40,17 @@ fn main() -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -36,17 +36,17 @@ fn main() -> ! {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -23,18 +23,18 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for USB config.rcc.hsi48 = true; // needed for USB
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View file

@ -39,6 +39,7 @@ async fn main(_spawner: Spawner) {
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000), freq: Hertz(32_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {

View file

@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
use embassy_stm32::bind_interrupts; use embassy_stm32::bind_interrupts;
use embassy_stm32::gpio::{Level, Output, Pin, Speed}; use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::spi::Spi; use embassy_stm32::spi::Spi;
use embassy_stm32::time::Hertz;
use embassy_time::{Delay, Timer}; use embassy_time::{Delay, Timer};
use lora_phy::mod_params::*; use lora_phy::mod_params::*;
use lora_phy::sx1261_2::SX1261_2; use lora_phy::sx1261_2::SX1261_2;
@ -26,7 +27,23 @@ 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,
prescaler: HsePrescaler::DIV1,
});
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);
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);

View file

@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
use embassy_stm32::bind_interrupts; use embassy_stm32::bind_interrupts;
use embassy_stm32::gpio::{Level, Output, Pin, Speed}; use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::spi::Spi; use embassy_stm32::spi::Spi;
use embassy_stm32::time::Hertz;
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;
@ -26,7 +27,23 @@ 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,
prescaler: HsePrescaler::DIV1,
});
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);
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);

View file

@ -21,6 +21,7 @@ async fn main(_spawner: Spawner) {
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000), freq: Hertz(32_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {

View file

@ -5,20 +5,34 @@
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};
use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig};
use embassy_stm32::time::Hertz;
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 _};
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.mux = ClockSrc::HSE; {
use embassy_stm32::rcc::*;
config.rcc.ls = LsConfig::default_lse(); config.rcc.ls = LsConfig::default_lse();
embassy_stm32::init(config) config.rcc.hse = Some(Hse {
}; freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
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);
info!("Hello World!"); info!("Hello World!");
let now = NaiveDate::from_ymd_opt(2020, 5, 15) let now = NaiveDate::from_ymd_opt(2020, 5, 15)

View file

@ -227,6 +227,11 @@ pub fn config() -> Config {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut config = Config::default(); let mut config = Config::default();
#[cfg(feature = "stm32wb55rg")]
{
config.rcc = embassy_stm32::rcc::WPAN_DEFAULT;
}
#[cfg(feature = "stm32f207zg")] #[cfg(feature = "stm32f207zg")]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
@ -307,7 +312,7 @@ pub fn config() -> Config {
mode: HseMode::BypassDigital, mode: HseMode::BypassDigital,
}); });
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::Hse, source: PllSource::HSE,
prediv: PllPreDiv::DIV2, prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125, mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -318,18 +323,18 @@ pub fn config() -> Config {
config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb1_pre = APBPrescaler::DIV1;
config.rcc.apb2_pre = APBPrescaler::DIV1; config.rcc.apb2_pre = APBPrescaler::DIV1;
config.rcc.apb3_pre = APBPrescaler::DIV1; config.rcc.apb3_pre = APBPrescaler::DIV1;
config.rcc.sys = Sysclk::Pll1P; config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0; config.rcc.voltage_scale = VoltageScale::Scale0;
} }
#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2), divp: Some(PllDiv::DIV2),
@ -337,13 +342,14 @@ pub fn config() -> Config {
divr: None, divr: None,
}); });
config.rcc.pll2 = Some(Pll { config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50, mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz divp: Some(PllDiv::DIV8), // 100mhz
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
@ -356,11 +362,11 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32h7a3zi"))] #[cfg(any(feature = "stm32h7a3zi"))]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64); config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true; config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL35, mul: PllMul::MUL35,
divp: Some(PllDiv::DIV2), // 280 Mhz divp: Some(PllDiv::DIV2), // 280 Mhz
@ -368,13 +374,14 @@ pub fn config() -> Config {
divr: None, divr: None,
}); });
config.rcc.pll2 = Some(Pll { config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4, prediv: PllPreDiv::DIV4,
mul: PllMul::MUL35, mul: PllMul::MUL35,
divp: Some(PllDiv::DIV8), // 70 Mhz divp: Some(PllDiv::DIV8), // 70 Mhz
divq: None, divq: None,
divr: None, divr: None,
}); });
config.rcc.sys = Sysclk::Pll1P; // 280 Mhz config.rcc.sys = Sysclk::PLL1_P; // 280 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV1; // 280 Mhz config.rcc.ahb_pre = AHBPrescaler::DIV1; // 280 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 140 Mhz config.rcc.apb1_pre = APBPrescaler::DIV2; // 140 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 140 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 140 Mhz
@ -405,6 +412,7 @@ pub fn config() -> Config {
config.rcc.hse = Some(Hse { config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000), freq: Hertz(32_000_000),
mode: HseMode::Bypass, mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
}); });
config.rcc.mux = ClockSrc::PLL1_R; config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll { config.rcc.pll = Some(Pll {