diff --git a/ci.sh b/ci.sh index ffd36a45..eac4d371 100755 --- a/ci.sh +++ b/ci.sh @@ -221,8 +221,8 @@ rm out/tests/stm32wb55rg/wpan_ble # unstable, I think it's running out of RAM? rm out/tests/stm32f207zg/eth -# doesn't work. Wire in D0-D1 might be bad, or the special IOVDD2 PGx pins. -rm out/tests/stm32u5a5zj/{gpio,usart*} +# doesn't work, gives "noise error", no idea why. usart_dma does pass. +rm out/tests/stm32u5a5zj/usart if [[ -z "${TELEPROBE_TOKEN-}" ]]; then echo No teleprobe token found, skipping running HIL tests diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 568a7eeb..99288340 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 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" bxcan = "0.7.0" nb = "1.0.0" @@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" 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] diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index e1702b00..011f4c07 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -763,6 +763,13 @@ pub(crate) unsafe fn init(_cs: CriticalSection) { ::enable_and_reset_with_cs(_cs); 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 { diff --git a/embassy-stm32/src/rcc/f4f7.rs b/embassy-stm32/src/rcc/f4f7.rs index 3f9a2be6..2e4f9572 100644 --- a/embassy-stm32/src/rcc/f4f7.rs +++ b/embassy-stm32/src/rcc/f4f7.rs @@ -166,8 +166,8 @@ pub(crate) unsafe fn init(config: Config) { }; let hclk = sys / config.ahb_pre; - let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre); - let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre); + let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); + let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); assert!(max::SYSCLK.contains(&sys)); assert!(max::HCLK.contains(&hclk)); @@ -326,15 +326,6 @@ fn flash_setup(clk: Hertz) { while FLASH.acr().read().latency() != latency {} } -fn calc_pclk(hclk: Hertz, ppre: D) -> (Hertz, Hertz) -where - Hertz: core::ops::Div, -{ - let pclk = hclk / ppre; - let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 }; - (pclk, pclk_tim) -} - #[cfg(stm32f7)] mod max { use core::ops::RangeInclusive; diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 8883763e..7e924f0a 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -6,8 +6,11 @@ use crate::pac::pwr::vals::Vos; pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; #[cfg(stm32h7)] 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::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; +pub use crate::pac::rcc::vals::{ + 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::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -58,41 +61,9 @@ pub struct Hse { 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)] pub struct Pll { /// Source clock selection. - #[cfg(stm32h5)] pub source: PllSource, /// PLL pre-divider (DIVM). @@ -152,15 +123,12 @@ impl From for Timpre { /// Configuration of the core clocks #[non_exhaustive] pub struct Config { - pub hsi: Option, + pub hsi: Option, pub hse: Option, pub csi: bool, pub hsi48: bool, pub sys: Sysclk, - #[cfg(stm32h7)] - pub pll_src: PllSource, - pub pll1: Option, pub pll2: Option, #[cfg(any(rcc_h5, stm32h7))] @@ -184,13 +152,11 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { - hsi: Some(Hsi::Mhz64), + hsi: Some(HSIPrescaler::DIV1), hse: None, csi: false, hsi48: false, sys: Sysclk::HSI, - #[cfg(stm32h7)] - pll_src: PllSource::Hsi, pll1: None, pll2: None, #[cfg(any(rcc_h5, stm32h7))] @@ -303,19 +269,13 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_hsion(false)); None } - Some(hsi) => { - 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), - }; + Some(hsidiv) => { RCC.cr().modify(|w| { w.set_hsidiv(hsidiv); w.set_hsion(true); }); while !RCC.cr().read().hsirdy() {} - Some(freq) + Some(HSI_FREQ / hsidiv) } }; @@ -360,25 +320,29 @@ pub(crate) unsafe fn init(config: Config) { } }; + // H7 has shared PLLSRC, check it's equal in all PLLs. + #[cfg(stm32h7)] + { + 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, - #[cfg(stm32h7)] - source: config.pll_src, - }; + let pll_input = PllInput { csi, hse, hsi }; let pll1 = init_pll(0, config.pll1, &pll_input); let pll2 = init_pll(1, config.pll2, &pll_input); #[cfg(any(rcc_h5, stm32h7))] let pll3 = init_pll(2, config.pll3, &pll_input); // Configure sysclk - let (sys, sw) = match config.sys { - Sysclk::HSI => (unwrap!(hsi), Sw::HSI), - Sysclk::HSE => (unwrap!(hse), Sw::HSE), - Sysclk::CSI => (unwrap!(csi), Sw::CSI), - Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P), + let sys = match config.sys { + Sysclk::HSI => unwrap!(hsi), + Sysclk::HSE => unwrap!(hse), + Sysclk::CSI => unwrap!(csi), + Sysclk::PLL1_P => unwrap!(pll1.p), + _ => unreachable!(), }; // 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_sw(sw)); - while RCC.cfgr().read().sws() != sw {} + RCC.cfgr().modify(|w| w.set_sw(config.sys)); + while RCC.cfgr().read().sws() != config.sys {} // IO compensation cell - Requires CSI clock and SYSCFG #[cfg(stm32h7)] // TODO h5 @@ -588,8 +552,6 @@ struct PllInput { hsi: Option, hse: Option, csi: Option, - #[cfg(stm32h7)] - source: PllSource, } struct PllOutput { @@ -619,15 +581,11 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { }; }; - #[cfg(stm32h5)] - let source = config.source; - #[cfg(stm32h7)] - let source = input.source; - - 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 in_clk = match config.source { + PllSource::DISABLE => panic!("must not set PllSource::Disable"), + PllSource::HSI => unwrap!(input.hsi), + PllSource::HSE => unwrap!(input.hse), + PllSource::CSI => unwrap!(input.csi), }; let ref_clk = in_clk / config.prediv as u32; @@ -667,7 +625,7 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { #[cfg(stm32h5)] RCC.pllcfgr(num).write(|w| { - w.set_pllsrc(src); + w.set_pllsrc(config.source); w.set_divm(config.prediv); w.set_pllvcosel(vco_range); w.set_pllrge(ref_range); @@ -681,7 +639,7 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { { RCC.pllckselr().modify(|w| { w.set_divm(num, config.prediv); - w.set_pllsrc(src); + w.set_pllsrc(config.source); }); RCC.pllcfgr().modify(|w| { w.set_pllvcosel(num, vco_range); diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs index 52e9ccb3..9fb2062d 100644 --- a/embassy-stm32/src/rcc/l0l1.rs +++ b/embassy-stm32/src/rcc/l0l1.rs @@ -156,23 +156,9 @@ pub(crate) unsafe fn init(config: Config) { w.set_ppre2(config.apb2_pre); }); - let ahb_freq = sys_clk / config.ahb_pre; - - let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let freq = ahb_freq / pre; - (freq, freq * 2u32) - } - }; - - let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let freq = ahb_freq / pre; - (freq, freq * 2u32) - } - }; + 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)] if config.enable_hsi48 { @@ -209,11 +195,11 @@ pub(crate) unsafe fn init(config: Config) { set_freqs(Clocks { sys: sys_clk, - hclk1: ahb_freq, - pclk1: apb1_freq, - pclk2: apb2_freq, - pclk1_tim: apb1_tim_freq, - pclk2_tim: apb2_tim_freq, + hclk1, + pclk1, + pclk2, + pclk1_tim, + pclk2_tim, rtc, }); } diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs index b5696227..2f89f682 100644 --- a/embassy-stm32/src/rcc/l4l5.rs +++ b/embassy-stm32/src/rcc/l4l5.rs @@ -1,7 +1,8 @@ use crate::pac::rcc::regs::Cfgr; -#[cfg(not(stm32wl))] +#[cfg(any(stm32l4, stm32l5, stm32wb))] 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::{ 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, @@ -27,6 +28,9 @@ pub struct Hse { pub freq: Hertz, /// HSE mode. pub mode: HseMode, + /// HSE prescaler + #[cfg(any(stm32wb, stm32wl))] + pub prescaler: HsePrescaler, } #[derive(Clone, Copy)] @@ -54,12 +58,12 @@ pub struct Config { pub msi: Option, pub hsi: bool, pub hse: Option, - #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] + #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))] pub hsi48: bool, // pll pub pll: Option, - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] pub pllsai1: Option, #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] pub pllsai2: Option, @@ -69,11 +73,13 @@ pub struct Config { pub ahb_pre: AHBPrescaler, pub apb1_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, // muxes - #[cfg(not(stm32wl))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] pub clk48_src: Clk48Src, // low speed LSI/LSE/RTC @@ -91,28 +97,63 @@ impl Default for Config { ahb_pre: AHBPrescaler::DIV1, apb1_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, pll: None, - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] pllsai1: None, #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] pllsai2: None, - #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] + #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))] hsi48: true, - #[cfg(not(stm32wl))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] clk48_src: Clk48Src::HSI48, 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) { // Switch to MSI to prevent problems with PLL configuration. if !RCC.cr().read().msion() { // Turn on MSI and configure it to 4MHz. 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_msipllen(false); w.set_msion(true) @@ -138,8 +179,9 @@ pub(crate) unsafe fn init(config: Config) { let msi = config.msi.map(|range| { // Enable MSI RCC.cr().modify(|w| { + #[cfg(not(stm32wb))] + w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR); w.set_msirange(range); - w.set_msirgsel(Msirgsel::CR); w.set_msion(true); // If LSE is enabled, enable calibration of MSI @@ -173,7 +215,7 @@ pub(crate) unsafe fn init(config: Config) { 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(|| { RCC.crrcr().modify(|w| w.set_hsi48on(true)); while !RCC.crrcr().read().hsi48rdy() {} @@ -185,7 +227,7 @@ pub(crate) unsafe fn init(config: Config) { let _plls = [ &config.pll, - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] &config.pllsai1, #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] &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. #[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."), Ok(None) => {} 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. #[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."), Ok(None) => {} 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 = 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); #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 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::HSI => hsi.unwrap(), ClockSrc::MSI => msi.unwrap(), - ClockSrc::PLL1_R => pll._r.unwrap(), + ClockSrc::PLL1_R => pll.r.unwrap(), }; #[cfg(stm32l4)] RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); #[cfg(stm32l5)] RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); - #[cfg(not(stm32wl))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] let _clk48 = match config.clk48_src { Clk48Src::HSI48 => hsi48, Clk48Src::MSI => msi, - Clk48Src::PLLSAI1_Q => pllsai1._q, - Clk48Src::PLL1_Q => pll._q, + Clk48Src::PLLSAI1_Q => pllsai1.q, + Clk48Src::PLL1_Q => pll.q, }; #[cfg(rcc_l4plus)] @@ -243,30 +285,21 @@ pub(crate) unsafe fn init(config: Config) { #[cfg(all(stm32l4, not(rcc_l4plus)))] assert!(sys_clk.0 <= 80_000_000); - let ahb_freq = sys_clk / config.ahb_pre; - - let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let freq = ahb_freq / pre; - (freq, freq * 2u32) - } - }; - - let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let freq = ahb_freq / pre; - (freq, freq * 2u32) - } - }; - - #[cfg(stm32wl)] - let ahb3_freq = sys_clk / config.shared_ahb_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(not(any(stm32wl5x, stm32wb)))] + let hclk2 = hclk1; + #[cfg(any(stm32wl5x, stm32wb))] + let hclk2 = sys_clk / config.core2_ahb_pre; + #[cfg(not(any(stm32wl, stm32wb)))] + let hclk3 = hclk1; + #[cfg(any(stm32wl, stm32wb))] + let hclk3 = sys_clk / config.shared_ahb_pre; // Set flash wait states #[cfg(stm32l4)] - let latency = match sys_clk.0 { + let latency = match hclk1.0 { 0..=16_000_000 => 0, 0..=32_000_000 => 1, 0..=48_000_000 => 2, @@ -274,7 +307,7 @@ pub(crate) unsafe fn init(config: Config) { _ => 4, }; #[cfg(stm32l5)] - let latency = match sys_clk.0 { + let latency = match hclk1.0 { // VCORE Range 0 (performance), others TODO 0..=20_000_000 => 0, 0..=40_000_000 => 1, @@ -284,12 +317,21 @@ pub(crate) unsafe fn init(config: Config) { _ => 5, }; #[cfg(stm32wl)] - let latency = match ahb3_freq.0 { + let latency = match hclk3.0 { // VOS RANGE1, others TODO. ..=18_000_000 => 0, ..=36_000_000 => 1, _ => 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)); while FLASH.acr().read().latency() != latency {} @@ -302,28 +344,29 @@ pub(crate) unsafe fn init(config: Config) { }); while RCC.cfgr().read().sws() != config.mux {} - #[cfg(stm32wl)] + #[cfg(any(stm32wl, stm32wb))] { RCC.extcfgr().modify(|w| { w.set_shdhpre(config.shared_ahb_pre); + #[cfg(any(stm32wl5x, stm32wb))] + w.set_c2hpre(config.core2_ahb_pre); }); while !RCC.extcfgr().read().shdhpref() {} + #[cfg(any(stm32wl5x, stm32wb))] + while !RCC.extcfgr().read().c2hpref() {} } set_freqs(Clocks { sys: sys_clk, - hclk1: ahb_freq, - hclk2: ahb_freq, - #[cfg(not(stm32wl))] - hclk3: ahb_freq, - pclk1: apb1_freq, - pclk2: apb2_freq, - pclk1_tim: apb1_tim_freq, - pclk2_tim: apb2_tim_freq, + hclk1, + hclk2, + hclk3, + pclk1, + pclk2, + pclk1_tim, + pclk2_tim, #[cfg(stm32wl)] - hclk3: ahb3_freq, - #[cfg(stm32wl)] - pclk3: ahb3_freq, + pclk3: hclk3, #[cfg(rcc_l4)] hsi: None, #[cfg(rcc_l4)] @@ -362,60 +405,56 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz { } } -#[allow(unused)] -fn get_equal(mut iter: impl Iterator) -> Result, ()> { - let Some(x) = iter.next() else { return Ok(None) }; - if !iter.all(|y| y == x) { - return Err(()); - } - return Ok(Some(x)); -} - struct PllInput { hsi: Option, hse: Option, msi: Option, } +#[allow(unused)] #[derive(Default)] struct PllOutput { - _p: Option, - _q: Option, - _r: Option, + p: Option, + q: Option, + r: Option, } #[derive(PartialEq, Eq, Clone, Copy)] enum PllInstance { Pll, - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] Pllsai1, #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] Pllsai2, } -fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> PllOutput { - // Disable PLL +fn pll_enable(instance: PllInstance, enabled: bool) { match instance { PllInstance::Pll => { - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} + RCC.cr().modify(|w| w.set_pllon(enabled)); + while RCC.cr().read().pllrdy() != enabled {} } - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] PllInstance::Pllsai1 => { - RCC.cr().modify(|w| w.set_pllsai1on(false)); - while RCC.cr().read().pllsai1rdy() {} + RCC.cr().modify(|w| w.set_pllsai1on(enabled)); + while RCC.cr().read().pllsai1rdy() != enabled {} } #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] PllInstance::Pllsai2 => { - RCC.cr().modify(|w| w.set_pllsai2on(false)); - while RCC.cr().read().pllsai2rdy() {} + RCC.cr().modify(|w| w.set_pllsai2on(enabled)); + while RCC.cr().read().pllsai2rdy() != enabled {} } } +} + +fn init_pll(instance: PllInstance, config: Option, 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 NONE"), + PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"), PLLSource::HSE => input.hse, PLLSource::HSI => input.hsi, PLLSource::MSI => input.msi, @@ -459,7 +498,7 @@ fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> Pll w.set_pllsrc(pll.source); write_fields!(w); }), - #[cfg(any(stm32l4, stm32l5))] + #[cfg(any(stm32l4, stm32l5, stm32wb))] PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { #[cfg(any(rcc_l4plus, stm32l5))] w.set_pllm(pll.prediv); @@ -478,22 +517,7 @@ fn init_pll(instance: PllInstance, config: Option, input: &PllInput) -> Pll } // Enable PLL - match instance { - 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() {} - } - } + pll_enable(instance, true); - PllOutput { _p: p, _q: q, _r: r } + PllOutput { p, q, r } } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 78d54f80..8cf2d6ab 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -19,9 +19,8 @@ pub use mco::*; #[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_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_wb, path = "wb.rs")] #[cfg_attr(rcc_wba, path = "wba.rs")] mod _version; #[cfg(feature = "low-power")] @@ -247,3 +246,33 @@ pub(crate) mod sealed { } pub trait RccPeripheral: sealed::RccPeripheral + 'static {} + +#[allow(unused)] +mod util { + use crate::time::Hertz; + + pub fn calc_pclk(hclk: Hertz, ppre: D) -> (Hertz, Hertz) + where + Hertz: core::ops::Div, + { + let pclk = hclk / ppre; + let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 }; + (pclk, pclk_tim) + } + + pub fn all_equal(mut iter: impl Iterator) -> bool { + let Some(x) = iter.next() else { return true }; + if !iter.all(|y| y == x) { + return false; + } + true + } + + pub fn get_equal(mut iter: impl Iterator) -> Result, ()> { + let Some(x) = iter.next() else { return Ok(None) }; + if !iter.all(|y| y == x) { + return Err(()); + } + Ok(Some(x)) + } +} diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs deleted file mode 100644 index 2d0b2711..00000000 --- a/embassy-stm32/src/rcc/wb.rs +++ /dev/null @@ -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, - /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. - pub divq: Option, - /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. - pub divr: Option, -} - -/// Clocks configutation -pub struct Config { - pub hse: Option, - pub sys: Sysclk, - pub mux: Option, - pub hsi48: bool, - - pub pll: Option, - pub pllsai: Option, - - 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, - }) -} diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 6e40f0ac..5bec9d44 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -43,7 +43,7 @@ async fn main(spawner: Spawner) -> ! { mode: HseMode::BypassDigital, }); config.rcc.pll1 = Some(Pll { - source: PllSource::Hse, + source: PllSource::HSE, prediv: PllPreDiv::DIV2, mul: PllMul::MUL125, divp: Some(PllDiv::DIV2), @@ -54,7 +54,7 @@ async fn main(spawner: Spawner) -> ! { config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb2_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; let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index 3b3c38e1..735826a6 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs @@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) { mode: HseMode::BypassDigital, }); config.rcc.pll1 = Some(Pll { - source: PllSource::Hse, + source: PllSource::HSE, prediv: PllPreDiv::DIV2, mul: PllMul::MUL125, divp: Some(PllDiv::DIV2), // 250mhz @@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.apb3_pre = APBPrescaler::DIV4; - config.rcc.sys = Sysclk::Pll1P; + config.rcc.sys = Sysclk::PLL1_P; config.rcc.voltage_scale = VoltageScale::Scale0; let p = embassy_stm32::init(config); diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index 4a358a35..e367827e 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs @@ -14,10 +14,10 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), @@ -25,13 +25,14 @@ async fn main(_spawner: Spawner) { divr: None, }); config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV8), // 100mhz divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 8195430b..23ece1c3 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -28,17 +28,17 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV8), // 100mhz 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs index 82122189..35fd6550 100644 --- a/examples/stm32h7/src/bin/dac.rs +++ b/examples/stm32h7/src/bin/dac.rs @@ -16,10 +16,10 @@ fn main() -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), @@ -27,13 +27,14 @@ fn main() -> ! { divr: None, }); config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV8), // 100mhz divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 334986a0..e141fc48 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -24,10 +24,10 @@ async fn main(spawner: Spawner) { let mut config = embassy_stm32::Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), @@ -35,13 +35,14 @@ async fn main(spawner: Spawner) { divr: None, }); config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV8), // 100mhz divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 81d9c734..e37d8797 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -34,18 +34,18 @@ async fn main(spawner: Spawner) -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for RNG - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 33813706..88df53f0 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -35,18 +35,18 @@ async fn main(spawner: Spawner) -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for RNG - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs index cffd4709..54e2c362 100644 --- a/examples/stm32h7/src/bin/fmc.rs +++ b/examples/stm32h7/src/bin/fmc.rs @@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV8), // 100mhz 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 0355ac07..e4bac8a5 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -17,18 +17,18 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for RNG - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV8), // 100mhz 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index 973a10cd..c55d780a 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs @@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs index ecb8d654..be968ff7 100644 --- a/examples/stm32h7/src/bin/sdmmc.rs +++ b/examples/stm32h7/src/bin/sdmmc.rs @@ -18,17 +18,17 @@ async fn main(_spawner: Spawner) -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index f128d4a5..a8db0ff7 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs @@ -40,17 +40,17 @@ fn main() -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index d4c0bcdb..561052e4 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs @@ -36,17 +36,17 @@ fn main() -> ! { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs index c1e5144b..19d77183 100644 --- a/examples/stm32h7/src/bin/usb_serial.rs +++ b/examples/stm32h7/src/bin/usb_serial.rs @@ -23,18 +23,18 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for USB - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), divq: 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.apb1_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index e26c274a..35a6a842 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs @@ -39,6 +39,7 @@ async fn main(_spawner: Spawner) { 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 { diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs index be33f39c..1c485d73 100644 --- a/examples/stm32wl/src/bin/lora_p2p_receive.rs +++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs @@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; use embassy_stm32::bind_interrupts; use embassy_stm32::gpio::{Level, Output, Pin, Speed}; use embassy_stm32::spi::Spi; +use embassy_stm32::time::Hertz; use embassy_time::{Delay, Timer}; use lora_phy::mod_params::*; use lora_phy::sx1261_2::SX1261_2; @@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { 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 spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs index 85f6a84b..3afa78ac 100644 --- a/examples/stm32wl/src/bin/lora_p2p_send.rs +++ b/examples/stm32wl/src/bin/lora_p2p_send.rs @@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; use embassy_stm32::bind_interrupts; use embassy_stm32::gpio::{Level, Output, Pin, Speed}; use embassy_stm32::spi::Spi; +use embassy_stm32::time::Hertz; use embassy_time::Delay; use lora_phy::mod_params::*; use lora_phy::sx1261_2::SX1261_2; @@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { 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 spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 2cf7ef9d..1a8822b4 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -21,6 +21,7 @@ async fn main(_spawner: Spawner) { 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 { diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index 9ebb05f2..b3b7f9c5 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -5,20 +5,34 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{ClockSrc, LsConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::time::Hertz; use embassy_stm32::Config; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = { - let mut config = Config::default(); - config.rcc.mux = ClockSrc::HSE; + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; 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!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index cb173815..ff808281 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -227,6 +227,11 @@ pub fn config() -> Config { #[allow(unused_mut)] let mut config = Config::default(); + #[cfg(feature = "stm32wb55rg")] + { + config.rcc = embassy_stm32::rcc::WPAN_DEFAULT; + } + #[cfg(feature = "stm32f207zg")] { use embassy_stm32::rcc::*; @@ -307,7 +312,7 @@ pub fn config() -> Config { mode: HseMode::BypassDigital, }); config.rcc.pll1 = Some(Pll { - source: PllSource::Hse, + source: PllSource::HSE, prediv: PllPreDiv::DIV2, mul: PllMul::MUL125, divp: Some(PllDiv::DIV2), @@ -318,18 +323,18 @@ pub fn config() -> Config { config.rcc.apb1_pre = APBPrescaler::DIV1; config.rcc.apb2_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; } #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for RNG - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV2), @@ -337,13 +342,14 @@ pub fn config() -> Config { divr: None, }); config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL50, divp: Some(PllDiv::DIV8), // 100mhz divq: 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.apb1_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"))] { use embassy_stm32::rcc::*; - config.rcc.hsi = Some(Hsi::Mhz64); + config.rcc.hsi = Some(HSIPrescaler::DIV1); config.rcc.csi = true; config.rcc.hsi48 = true; // needed for RNG - config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL35, divp: Some(PllDiv::DIV2), // 280 Mhz @@ -368,13 +374,14 @@ pub fn config() -> Config { divr: None, }); config.rcc.pll2 = Some(Pll { + source: PllSource::HSI, prediv: PllPreDiv::DIV4, mul: PllMul::MUL35, divp: Some(PllDiv::DIV8), // 70 Mhz divq: 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.apb1_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 { freq: Hertz(32_000_000), mode: HseMode::Bypass, + prescaler: HsePrescaler::DIV1, }); config.rcc.mux = ClockSrc::PLL1_R; config.rcc.pll = Some(Pll {