From b9e13cb5d1ca3e85a02b2a37b7ee14f73663b1bd Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Mon, 23 Oct 2023 00:28:54 +0200
Subject: [PATCH] stm32/rcc: merge wl into l4/l5.

---
 embassy-stm32/Cargo.toml                      |   4 +-
 embassy-stm32/src/ipcc.rs                     |   5 +-
 embassy-stm32/src/rcc/l4l5.rs                 | 153 ++++++++++-----
 embassy-stm32/src/rcc/mod.rs                  |   3 +-
 embassy-stm32/src/rcc/u5.rs                   |   2 +-
 embassy-stm32/src/rcc/wl.rs                   | 184 ------------------
 examples/stm32l4/src/bin/rtc.rs               |  29 +--
 .../src/bin/spe_adin1110_http_server.rs       |  34 ++--
 examples/stm32wl/src/bin/lora_lorawan.rs      |  22 ++-
 examples/stm32wl/src/bin/random.rs            |  23 ++-
 tests/stm32/src/common.rs                     |  15 +-
 11 files changed, 198 insertions(+), 276 deletions(-)
 delete mode 100644 embassy-stm32/src/rcc/wl.rs

diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 2d694267a..568a7eeb9 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-ee64389697d9234af374a89788aa52bb93d59284" }
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc" }
 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-ee64389697d9234af374a89788aa52bb93d59284", default-features = false, features = ["metadata"]}
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]}
 
 
 [features]
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 1b1e182f0..4006dee19 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -5,6 +5,7 @@ use core::task::Poll;
 use self::sealed::Instance;
 use crate::interrupt;
 use crate::interrupt::typelevel::Interrupt;
+use crate::pac::rcc::vals::{Lptim1sel, Lptim2sel};
 use crate::peripherals::IPCC;
 use crate::rcc::sealed::RccPeripheral;
 
@@ -273,7 +274,7 @@ fn _configure_pwr() {
 
     // set LPTIM1 & LPTIM2 clock source
     rcc.ccipr().modify(|w| {
-        w.set_lptim1sel(0b00); // PCLK
-        w.set_lptim2sel(0b00); // PCLK
+        w.set_lptim1sel(Lptim1sel::PCLK1);
+        w.set_lptim2sel(Lptim2sel::PCLK1);
     });
 }
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index 8cf284d1e..b56962270 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -1,8 +1,10 @@
 use crate::pac::rcc::regs::Cfgr;
+#[cfg(not(stm32wl))]
+pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
 use crate::pac::rcc::vals::Msirgsel;
 pub use crate::pac::rcc::vals::{
-    Clk48sel as Clk48Src, 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,
+    Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
+    Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
 };
 use crate::pac::{FLASH, RCC};
 use crate::rcc::{set_freqs, Clocks};
@@ -11,6 +13,22 @@ use crate::time::Hertz;
 /// HSI speed
 pub const HSI_FREQ: Hertz = Hertz(16_000_000);
 
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub enum HseMode {
+    /// crystal/ceramic oscillator (HSEBYP=0)
+    Oscillator,
+    /// external analog clock (low swing) (HSEBYP=1)
+    Bypass,
+}
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Hse {
+    /// HSE frequency.
+    pub freq: Hertz,
+    /// HSE mode.
+    pub mode: HseMode,
+}
+
 #[derive(Clone, Copy)]
 pub struct Pll {
     /// PLL source
@@ -35,12 +53,13 @@ pub struct Config {
     // base clock sources
     pub msi: Option<MSIRange>,
     pub hsi: bool,
-    pub hse: Option<Hertz>,
-    #[cfg(not(any(stm32l47x, stm32l48x)))]
+    pub hse: Option<Hse>,
+    #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
     pub hsi48: bool,
 
     // pll
     pub pll: Option<Pll>,
+    #[cfg(any(stm32l4, stm32l5))]
     pub pllsai1: Option<Pll>,
     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
     pub pllsai2: Option<Pll>,
@@ -50,8 +69,11 @@ pub struct Config {
     pub ahb_pre: AHBPrescaler,
     pub apb1_pre: APBPrescaler,
     pub apb2_pre: APBPrescaler,
+    #[cfg(stm32wl)]
+    pub shared_ahb_pre: AHBPrescaler,
 
     // muxes
+    #[cfg(not(stm32wl))]
     pub clk48_src: Clk48Src,
 
     // low speed LSI/LSE/RTC
@@ -69,12 +91,16 @@ impl Default for Config {
             ahb_pre: AHBPrescaler::DIV1,
             apb1_pre: APBPrescaler::DIV1,
             apb2_pre: APBPrescaler::DIV1,
+            #[cfg(stm32wl)]
+            shared_ahb_pre: AHBPrescaler::DIV1,
             pll: None,
+            #[cfg(any(stm32l4, stm32l5))]
             pllsai1: None,
             #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
             pllsai2: None,
-            #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
+            #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
             hsi48: true,
+            #[cfg(not(stm32wl))]
             clk48_src: Clk48Src::HSI48,
             ls: Default::default(),
         }
@@ -111,7 +137,7 @@ pub(crate) unsafe fn init(config: Config) {
 
     let msi = config.msi.map(|range| {
         // Enable MSI
-        RCC.cr().write(|w| {
+        RCC.cr().modify(|w| {
             w.set_msirange(range);
             w.set_msirgsel(Msirgsel::CR);
             w.set_msion(true);
@@ -128,20 +154,26 @@ pub(crate) unsafe fn init(config: Config) {
     });
 
     let hsi = config.hsi.then(|| {
-        RCC.cr().write(|w| w.set_hsion(true));
+        RCC.cr().modify(|w| w.set_hsion(true));
         while !RCC.cr().read().hsirdy() {}
 
         HSI_FREQ
     });
 
-    let hse = config.hse.map(|freq| {
-        RCC.cr().write(|w| w.set_hseon(true));
+    let hse = config.hse.map(|hse| {
+        RCC.cr().modify(|w| {
+            #[cfg(stm32wl)]
+            w.set_hsebyppwr(hse.mode == HseMode::Bypass);
+            #[cfg(not(stm32wl))]
+            w.set_hsebyp(hse.mode == HseMode::Bypass);
+            w.set_hseon(true);
+        });
         while !RCC.cr().read().hserdy() {}
 
-        freq
+        hse.freq
     });
 
-    #[cfg(not(any(stm32l47x, stm32l48x)))]
+    #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
     let hsi48 = config.hsi48.then(|| {
         RCC.crrcr().modify(|w| w.set_hsi48on(true));
         while !RCC.crrcr().read().hsi48rdy() {}
@@ -153,6 +185,7 @@ pub(crate) unsafe fn init(config: Config) {
 
     let _plls = [
         &config.pll,
+        #[cfg(any(stm32l4, stm32l5))]
         &config.pllsai1,
         #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
         &config.pllsai2,
@@ -169,8 +202,8 @@ pub(crate) unsafe fn init(config: Config) {
         }),
     };
 
-    // L4+ has shared PLLSRC, check it's equal in all PLLs.
-    #[cfg(any(rcc_l4plus))]
+    // 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)) {
         Err(()) => panic!("Source must be equal across all enabled PLLs."),
         Ok(None) => {}
@@ -181,6 +214,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))]
     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);
@@ -196,6 +230,7 @@ pub(crate) unsafe fn init(config: Config) {
     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))]
     let _clk48 = match config.clk48_src {
         Clk48Src::HSI48 => hsi48,
         Clk48Src::MSI => msi,
@@ -208,38 +243,6 @@ pub(crate) unsafe fn init(config: Config) {
     #[cfg(all(stm32l4, not(rcc_l4plus)))]
     assert!(sys_clk.0 <= 80_000_000);
 
-    // Set flash wait states
-    #[cfg(stm32l4)]
-    FLASH.acr().modify(|w| {
-        w.set_latency(match sys_clk.0 {
-            0..=16_000_000 => 0,
-            0..=32_000_000 => 1,
-            0..=48_000_000 => 2,
-            0..=64_000_000 => 3,
-            _ => 4,
-        })
-    });
-    // VCORE Range 0 (performance), others TODO
-    #[cfg(stm32l5)]
-    FLASH.acr().modify(|w| {
-        w.set_latency(match sys_clk.0 {
-            0..=20_000_000 => 0,
-            0..=40_000_000 => 1,
-            0..=60_000_000 => 2,
-            0..=80_000_000 => 3,
-            0..=100_000_000 => 4,
-            _ => 5,
-        })
-    });
-
-    RCC.cfgr().modify(|w| {
-        w.set_sw(config.mux);
-        w.set_hpre(config.ahb_pre);
-        w.set_ppre1(config.apb1_pre);
-        w.set_ppre2(config.apb2_pre);
-    });
-    while RCC.cfgr().read().sws() != config.mux {}
-
     let ahb_freq = sys_clk / config.ahb_pre;
 
     let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
@@ -258,15 +261,69 @@ pub(crate) unsafe fn init(config: Config) {
         }
     };
 
+    #[cfg(stm32wl)]
+    let ahb3_freq = sys_clk / config.shared_ahb_pre;
+
+    // Set flash wait states
+    #[cfg(stm32l4)]
+    let latency = match sys_clk.0 {
+        0..=16_000_000 => 0,
+        0..=32_000_000 => 1,
+        0..=48_000_000 => 2,
+        0..=64_000_000 => 3,
+        _ => 4,
+    };
+    #[cfg(stm32l5)]
+    let latency = match sys_clk.0 {
+        // VCORE Range 0 (performance), others TODO
+        0..=20_000_000 => 0,
+        0..=40_000_000 => 1,
+        0..=60_000_000 => 2,
+        0..=80_000_000 => 3,
+        0..=100_000_000 => 4,
+        _ => 5,
+    };
+    #[cfg(stm32wl)]
+    let latency = match ahb3_freq.0 {
+        // VOS RANGE1, others TODO.
+        ..=18_000_000 => 0,
+        ..=36_000_000 => 1,
+        _ => 2,
+    };
+
+    FLASH.acr().modify(|w| w.set_latency(latency));
+    while FLASH.acr().read().latency() != latency {}
+
+    RCC.cfgr().modify(|w| {
+        w.set_sw(config.mux);
+        w.set_hpre(config.ahb_pre);
+        w.set_ppre1(config.apb1_pre);
+        w.set_ppre2(config.apb2_pre);
+    });
+    while RCC.cfgr().read().sws() != config.mux {}
+
+    #[cfg(stm32wl)]
+    {
+        RCC.extcfgr().modify(|w| {
+            w.set_shdhpre(config.shared_ahb_pre);
+        });
+        while !RCC.extcfgr().read().shdhpref() {}
+    }
+
     set_freqs(Clocks {
         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,
+        #[cfg(stm32wl)]
+        hclk3: ahb3_freq,
+        #[cfg(stm32wl)]
+        pclk3: ahb3_freq,
         #[cfg(rcc_l4)]
         hsi: None,
         #[cfg(rcc_l4)]
@@ -330,6 +387,7 @@ struct PllOutput {
 #[derive(PartialEq, Eq, Clone, Copy)]
 enum PllInstance {
     Pll,
+    #[cfg(any(stm32l4, stm32l5))]
     Pllsai1,
     #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
     Pllsai2,
@@ -342,6 +400,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
             RCC.cr().modify(|w| w.set_pllon(false));
             while RCC.cr().read().pllrdy() {}
         }
+        #[cfg(any(stm32l4, stm32l5))]
         PllInstance::Pllsai1 => {
             RCC.cr().modify(|w| w.set_pllsai1on(false));
             while RCC.cr().read().pllsai1rdy() {}
@@ -356,7 +415,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
     let Some(pll) = config else { return PllOutput::default() };
 
     let pll_src = match pll.source {
-        PLLSource::NONE => panic!("must not select PLL source as NONE"),
+        PLLSource::DISABLE => panic!("must not select PLL source as NONE"),
         PLLSource::HSE => input.hse,
         PLLSource::HSI => input.hsi,
         PLLSource::MSI => input.msi,
@@ -400,6 +459,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
             w.set_pllsrc(pll.source);
             write_fields!(w);
         }),
+        #[cfg(any(stm32l4, stm32l5))]
         PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
             #[cfg(any(rcc_l4plus, stm32l5))]
             w.set_pllm(pll.prediv);
@@ -423,6 +483,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
             RCC.cr().modify(|w| w.set_pllon(true));
             while !RCC.cr().read().pllrdy() {}
         }
+        #[cfg(any(stm32l4, stm32l5))]
         PllInstance::Pllsai1 => {
             RCC.cr().modify(|w| w.set_pllsai1on(true));
             while !RCC.cr().read().pllsai1rdy() {}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 49174b27f..78d54f803 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -19,11 +19,10 @@ 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), path = "l4l5.rs")]
+#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle), path = "l4l5.rs")]
 #[cfg_attr(rcc_u5, path = "u5.rs")]
 #[cfg_attr(rcc_wb, path = "wb.rs")]
 #[cfg_attr(rcc_wba, path = "wba.rs")]
-#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
 mod _version;
 #[cfg(feature = "low-power")]
 use core::sync::atomic::{AtomicU32, Ordering};
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 7664557e9..2bbacbbdc 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -170,7 +170,7 @@ impl Config {
 
         RCC.icscr1().modify(|w| {
             w.set_msisrange(range);
-            w.set_msirgsel(Msirgsel::RCC_ICSCR1);
+            w.set_msirgsel(Msirgsel::ICSCR1);
         });
         RCC.cr().write(|w| {
             w.set_msipllen(false);
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
deleted file mode 100644
index 4d68b55c2..000000000
--- a/embassy-stm32/src/rcc/wl.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-pub use crate::pac::pwr::vals::Vos as VoltageScale;
-use crate::pac::rcc::vals::Sw;
-pub use crate::pac::rcc::vals::{
-    Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
-    Pllsrc as PllSource, Ppre as APBPrescaler,
-};
-use crate::pac::{FLASH, RCC};
-use crate::rcc::{set_freqs, Clocks};
-use crate::time::Hertz;
-
-/// HSI speed
-pub const HSI_FREQ: Hertz = Hertz(16_000_000);
-
-/// HSE speed
-pub const HSE_FREQ: Hertz = Hertz(32_000_000);
-
-/// System clock mux source
-#[derive(Clone, Copy)]
-pub enum ClockSrc {
-    MSI(MSIRange),
-    HSE,
-    HSI,
-}
-
-/// Clocks configutation
-pub struct Config {
-    pub mux: ClockSrc,
-    pub ahb_pre: AHBPrescaler,
-    pub shd_ahb_pre: AHBPrescaler,
-    pub apb1_pre: APBPrescaler,
-    pub apb2_pre: APBPrescaler,
-    pub adc_clock_source: AdcClockSource,
-    pub ls: super::LsConfig,
-}
-
-impl Default for Config {
-    #[inline]
-    fn default() -> Config {
-        Config {
-            mux: ClockSrc::MSI(MSIRange::RANGE4M),
-            ahb_pre: AHBPrescaler::DIV1,
-            shd_ahb_pre: AHBPrescaler::DIV1,
-            apb1_pre: APBPrescaler::DIV1,
-            apb2_pre: APBPrescaler::DIV1,
-            adc_clock_source: AdcClockSource::HSI,
-            ls: Default::default(),
-        }
-    }
-}
-
-pub(crate) unsafe fn init(config: Config) {
-    let (sys_clk, sw, vos) = match config.mux {
-        ClockSrc::HSI => (HSI_FREQ, Sw::HSI, VoltageScale::RANGE2),
-        ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1),
-        ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
-    };
-
-    let ahb_freq = sys_clk / config.ahb_pre;
-    let shd_ahb_freq = sys_clk / config.shd_ahb_pre;
-
-    let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
-        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
-        pre => {
-            let freq = ahb_freq / pre;
-            (freq, freq * 2u32)
-        }
-    };
-
-    let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
-        APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
-        pre => {
-            let freq = ahb_freq / pre;
-            (freq, freq * 2u32)
-        }
-    };
-
-    // Adjust flash latency
-    let flash_clk_src_freq = shd_ahb_freq;
-    let ws = match vos {
-        VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
-            0..=18_000_000 => 0b000,
-            18_000_001..=36_000_000 => 0b001,
-            _ => 0b010,
-        },
-        VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
-            0..=6_000_000 => 0b000,
-            6_000_001..=12_000_000 => 0b001,
-            _ => 0b010,
-        },
-        _ => unreachable!(),
-    };
-
-    FLASH.acr().modify(|w| {
-        w.set_latency(ws);
-    });
-
-    while FLASH.acr().read().latency() != ws {}
-
-    match config.mux {
-        ClockSrc::HSI => {
-            // Enable HSI
-            RCC.cr().write(|w| w.set_hsion(true));
-            while !RCC.cr().read().hsirdy() {}
-        }
-        ClockSrc::HSE => {
-            // Enable HSE
-            RCC.cr().write(|w| {
-                w.set_hsebyppwr(true);
-                w.set_hseon(true);
-            });
-            while !RCC.cr().read().hserdy() {}
-        }
-        ClockSrc::MSI(range) => {
-            let cr = RCC.cr().read();
-            assert!(!cr.msion() || cr.msirdy());
-            RCC.cr().write(|w| {
-                w.set_msirgsel(true);
-                w.set_msirange(range);
-                w.set_msion(true);
-
-                // If LSE is enabled, enable calibration of MSI
-                w.set_msipllen(config.ls.lse.is_some());
-            });
-            while !RCC.cr().read().msirdy() {}
-        }
-    }
-
-    RCC.extcfgr().modify(|w| {
-        w.set_shdhpre(config.shd_ahb_pre);
-    });
-
-    RCC.cfgr().modify(|w| {
-        w.set_sw(sw.into());
-        w.set_hpre(config.ahb_pre);
-        w.set_ppre1(config.apb1_pre);
-        w.set_ppre2(config.apb2_pre);
-    });
-
-    // ADC clock MUX
-    RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
-
-    // TODO: switch voltage range
-
-    let rtc = config.ls.init();
-
-    set_freqs(Clocks {
-        sys: sys_clk,
-        hclk1: ahb_freq,
-        hclk2: ahb_freq,
-        hclk3: shd_ahb_freq,
-        pclk1: apb1_freq,
-        pclk2: apb2_freq,
-        pclk3: shd_ahb_freq,
-        pclk1_tim: apb1_tim_freq,
-        pclk2_tim: apb2_tim_freq,
-        rtc,
-    });
-}
-
-fn msirange_to_hertz(range: MSIRange) -> Hertz {
-    match range {
-        MSIRange::RANGE100K => Hertz(100_000),
-        MSIRange::RANGE200K => Hertz(200_000),
-        MSIRange::RANGE400K => Hertz(400_000),
-        MSIRange::RANGE800K => Hertz(800_000),
-        MSIRange::RANGE1M => Hertz(1_000_000),
-        MSIRange::RANGE2M => Hertz(2_000_000),
-        MSIRange::RANGE4M => Hertz(4_000_000),
-        MSIRange::RANGE8M => Hertz(8_000_000),
-        MSIRange::RANGE16M => Hertz(16_000_000),
-        MSIRange::RANGE24M => Hertz(24_000_000),
-        MSIRange::RANGE32M => Hertz(32_000_000),
-        MSIRange::RANGE48M => Hertz(48_000_000),
-        _ => unreachable!(),
-    }
-}
-
-fn msirange_to_vos(range: MSIRange) -> VoltageScale {
-    if range.to_bits() > MSIRange::RANGE16M.to_bits() {
-        VoltageScale::RANGE1
-    } else {
-        VoltageScale::RANGE2
-    }
-}
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index fec0a349d..69527c9ad 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -5,7 +5,6 @@
 use chrono::{NaiveDate, NaiveDateTime};
 use defmt::*;
 use embassy_executor::Spawner;
-use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
 use embassy_stm32::rtc::{Rtc, RtcConfig};
 use embassy_stm32::time::Hertz;
 use embassy_stm32::Config;
@@ -15,17 +14,23 @@ use {defmt_rtt as _, panic_probe as _};
 #[embassy_executor::main]
 async fn main(_spawner: Spawner) {
     let mut config = Config::default();
-    config.rcc.mux = ClockSrc::PLL1_R;
-    config.rcc.hse = Some(Hertz::mhz(8));
-    config.rcc.pll = Some(Pll {
-        source: PLLSource::HSE,
-        prediv: PllPreDiv::DIV1,
-        mul: PllMul::MUL20,
-        divp: None,
-        divq: None,
-        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
-    });
-    config.rcc.ls = LsConfig::default_lse();
+    {
+        use embassy_stm32::rcc::*;
+        config.rcc.mux = ClockSrc::PLL1_R;
+        config.rcc.hse = Some(Hse {
+            freq: Hertz::mhz(8),
+            mode: HseMode::Oscillator,
+        });
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSE,
+            prediv: PllPreDiv::DIV1,
+            mul: PllMul::MUL20,
+            divp: None,
+            divq: None,
+            divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
+        });
+        config.rcc.ls = LsConfig::default_lse();
+    }
     let p = embassy_stm32::init(config);
 
     info!("Hello World!");
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 3c9d2cfc0..f76b504a7 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -48,7 +48,6 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
 use embedded_hal_bus::spi::ExclusiveDevice;
 use hal::gpio::Pull;
 use hal::i2c::Config as I2C_Config;
-use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
 use hal::spi::{Config as SPI_Config, Spi};
 use hal::time::Hertz;
 
@@ -74,20 +73,25 @@ async fn main(spawner: Spawner) {
     defmt::println!("Start main()");
 
     let mut config = embassy_stm32::Config::default();
-
-    // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
-    // 80MHz highest frequency for flash 0 wait.
-    config.rcc.mux = ClockSrc::PLL1_R;
-    config.rcc.hse = Some(Hertz::mhz(8));
-    config.rcc.pll = Some(Pll {
-        source: PLLSource::HSE,
-        prediv: PllPreDiv::DIV1,
-        mul: PllMul::MUL20,
-        divp: None,
-        divq: None,
-        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
-    });
-    config.rcc.hsi48 = true; // needed for rng
+    {
+        use embassy_stm32::rcc::*;
+        // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
+        // 80MHz highest frequency for flash 0 wait.
+        config.rcc.mux = ClockSrc::PLL1_R;
+        config.rcc.hse = Some(Hse {
+            freq: Hertz::mhz(8),
+            mode: HseMode::Oscillator,
+        });
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSE,
+            prediv: PllPreDiv::DIV1,
+            mul: PllMul::MUL20,
+            divp: None,
+            divq: None,
+            divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
+        });
+        config.rcc.hsi48 = true; // needed for rng
+    }
 
     let dp = embassy_stm32::init(config);
 
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index 8c789afbc..e26c274ad 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -12,7 +12,8 @@ use embassy_lora::LoraTimer;
 use embassy_stm32::gpio::{Level, Output, Pin, Speed};
 use embassy_stm32::rng::{self, Rng};
 use embassy_stm32::spi::Spi;
-use embassy_stm32::{bind_interrupts, pac, peripherals};
+use embassy_stm32::time::Hertz;
+use embassy_stm32::{bind_interrupts, peripherals};
 use embassy_time::Delay;
 use lora_phy::mod_params::*;
 use lora_phy::sx1261_2::SX1261_2;
@@ -33,11 +34,24 @@ 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,
+        });
+        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);
 
-    pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
-
     let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
 
     // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 70676c704..2cf7ef9d0 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -4,9 +4,9 @@
 
 use defmt::*;
 use embassy_executor::Spawner;
-use embassy_stm32::rcc::{ClockSrc, MSIRange};
 use embassy_stm32::rng::{self, Rng};
-use embassy_stm32::{bind_interrupts, pac, peripherals};
+use embassy_stm32::time::Hertz;
+use embassy_stm32::{bind_interrupts, peripherals};
 use {defmt_rtt as _, panic_probe as _};
 
 bind_interrupts!(struct Irqs{
@@ -16,11 +16,24 @@ bind_interrupts!(struct Irqs{
 #[embassy_executor::main]
 async fn main(_spawner: Spawner) {
     let mut config = embassy_stm32::Config::default();
-    config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
+    {
+        use embassy_stm32::rcc::*;
+        config.rcc.hse = Some(Hse {
+            freq: Hertz(32_000_000),
+            mode: HseMode::Bypass,
+        });
+        config.rcc.mux = ClockSrc::PLL1_R;
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSE,
+            prediv: PllPreDiv::DIV2,
+            mul: PllMul::MUL6,
+            divp: None,
+            divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
+            divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
+        });
+    }
     let p = embassy_stm32::init(config);
 
-    pac::RCC.ccipr().modify(|w| w.set_rngsel(0b11)); // msi
-
     info!("Hello World!");
 
     let mut rng = Rng::new(p.RNG, Irqs);
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 0a70e6a7e..cb1738154 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -402,9 +402,18 @@ pub fn config() -> Config {
     #[cfg(feature = "stm32wl55jc")]
     {
         use embassy_stm32::rcc::*;
-        config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
-        embassy_stm32::pac::RCC.ccipr().modify(|w| {
-            w.set_rngsel(0b11); // msi
+        config.rcc.hse = Some(Hse {
+            freq: Hertz(32_000_000),
+            mode: HseMode::Bypass,
+        });
+        config.rcc.mux = ClockSrc::PLL1_R;
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSE,
+            prediv: PllPreDiv::DIV2,
+            mul: PllMul::MUL6,
+            divp: None,
+            divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
+            divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
         });
     }