From 8911a4d8558cd41244af2be2bce2b0969a4ffbea Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Sun, 5 Nov 2023 03:06:13 +0100
Subject: [PATCH] stm32/rcc: switch to modern api for l0, l1.

---
 embassy-stm32/src/rcc/l0l1.rs                | 197 ++++++++++---------
 embassy-stm32/src/rcc/l4l5.rs                |   3 -
 examples/stm32l0/src/bin/button_exti.rs      |   2 +-
 examples/stm32l0/src/bin/lora_cad.rs         |   2 +-
 examples/stm32l0/src/bin/lora_lorawan.rs     |   2 +-
 examples/stm32l0/src/bin/lora_p2p_receive.rs |   2 +-
 examples/stm32l0/src/bin/lora_p2p_send.rs    |   2 +-
 tests/stm32/src/common.rs                    |  26 +--
 8 files changed, 124 insertions(+), 112 deletions(-)

diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs
index 9fb2062d6..3af279595 100644
--- a/embassy-stm32/src/rcc/l0l1.rs
+++ b/embassy-stm32/src/rcc/l0l1.rs
@@ -1,8 +1,8 @@
 pub use crate::pac::pwr::vals::Vos as VoltageScale;
 pub use crate::pac::rcc::vals::{
-    Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler,
+    Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul,
+    Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
 };
-use crate::pac::rcc::vals::{Pllsrc, Sw};
 #[cfg(crs)]
 use crate::pac::{crs, CRS, SYSCFG};
 use crate::pac::{FLASH, PWR, RCC};
@@ -12,39 +12,50 @@ use crate::time::Hertz;
 /// HSI speed
 pub const HSI_FREQ: Hertz = Hertz(16_000_000);
 
-/// System clock mux source
-#[derive(Clone, Copy)]
-pub enum ClockSrc {
-    MSI(MSIRange),
-    PLL(PLLSource, PLLMul, PLLDiv),
-    HSE(Hertz),
-    HSI,
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub enum HseMode {
+    /// crystal/ceramic oscillator (HSEBYP=0)
+    Oscillator,
+    /// external analog clock (low swing) (HSEBYP=1)
+    Bypass,
 }
 
-/// PLL clock input source
-#[derive(Clone, Copy)]
-pub enum PLLSource {
-    HSI,
-    HSE(Hertz),
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub struct Hse {
+    /// HSE frequency.
+    pub freq: Hertz,
+    /// HSE mode.
+    pub mode: HseMode,
 }
 
-impl From<PLLSource> for Pllsrc {
-    fn from(val: PLLSource) -> Pllsrc {
-        match val {
-            PLLSource::HSI => Pllsrc::HSI,
-            PLLSource::HSE(_) => Pllsrc::HSE,
-        }
-    }
+#[derive(Clone, Copy)]
+pub struct Pll {
+    /// PLL source
+    pub source: PLLSource,
+
+    /// PLL multiplication factor.
+    pub mul: PllMul,
+
+    /// PLL main output division factor.
+    pub div: PllDiv,
 }
 
 /// Clocks configutation
 pub struct Config {
+    // base clock sources
+    pub msi: Option<MSIRange>,
+    pub hsi: bool,
+    pub hse: Option<Hse>,
+    #[cfg(crs)]
+    pub hsi48: bool,
+
+    pub pll: Option<Pll>,
+
     pub mux: ClockSrc,
     pub ahb_pre: AHBPrescaler,
     pub apb1_pre: APBPrescaler,
     pub apb2_pre: APBPrescaler,
-    #[cfg(crs)]
-    pub enable_hsi48: bool,
+
     pub ls: super::LsConfig,
     pub voltage_scale: VoltageScale,
 }
@@ -53,12 +64,18 @@ impl Default for Config {
     #[inline]
     fn default() -> Config {
         Config {
-            mux: ClockSrc::MSI(MSIRange::RANGE5),
+            msi: Some(MSIRange::RANGE5),
+            hse: None,
+            hsi: false,
+            #[cfg(crs)]
+            hsi48: false,
+
+            pll: None,
+
+            mux: ClockSrc::MSI,
             ahb_pre: AHBPrescaler::DIV1,
             apb1_pre: APBPrescaler::DIV1,
             apb2_pre: APBPrescaler::DIV1,
-            #[cfg(crs)]
-            enable_hsi48: false,
             voltage_scale: VoltageScale::RANGE1,
             ls: Default::default(),
         }
@@ -71,72 +88,68 @@ pub(crate) unsafe fn init(config: Config) {
     PWR.cr().write(|w| w.set_vos(config.voltage_scale));
     while PWR.csr().read().vosf() {}
 
-    let (sys_clk, sw) = match config.mux {
-        ClockSrc::MSI(range) => {
-            // Set MSI range
-            RCC.icscr().write(|w| w.set_msirange(range));
-
-            // Enable MSI
-            RCC.cr().write(|w| w.set_msion(true));
-            while !RCC.cr().read().msirdy() {}
-
-            let freq = 32_768 * (1 << (range as u8 + 1));
-            (Hertz(freq), Sw::MSI)
-        }
-        ClockSrc::HSI => {
-            // Enable HSI
-            RCC.cr().write(|w| w.set_hsion(true));
-            while !RCC.cr().read().hsirdy() {}
-
-            (HSI_FREQ, Sw::HSI)
-        }
-        ClockSrc::HSE(freq) => {
-            // Enable HSE
-            RCC.cr().write(|w| w.set_hseon(true));
-            while !RCC.cr().read().hserdy() {}
-
-            (freq, Sw::HSE)
-        }
-        ClockSrc::PLL(src, mul, div) => {
-            let freq = match src {
-                PLLSource::HSE(freq) => {
-                    // Enable HSE
-                    RCC.cr().write(|w| w.set_hseon(true));
-                    while !RCC.cr().read().hserdy() {}
-                    freq
-                }
-                PLLSource::HSI => {
-                    // Enable HSI
-                    RCC.cr().write(|w| w.set_hsion(true));
-                    while !RCC.cr().read().hsirdy() {}
-                    HSI_FREQ
-                }
-            };
-
-            // Disable PLL
-            RCC.cr().modify(|w| w.set_pllon(false));
-            while RCC.cr().read().pllrdy() {}
-
-            let freq = freq * mul / div;
-
-            assert!(freq <= Hertz(32_000_000));
-
-            RCC.cfgr().write(move |w| {
-                w.set_pllmul(mul);
-                w.set_plldiv(div);
-                w.set_pllsrc(src.into());
-            });
-
-            // Enable PLL
-            RCC.cr().modify(|w| w.set_pllon(true));
-            while !RCC.cr().read().pllrdy() {}
-
-            (freq, Sw::PLL1_P)
-        }
-    };
-
     let rtc = config.ls.init();
 
+    let msi = config.msi.map(|range| {
+        RCC.icscr().modify(|w| w.set_msirange(range));
+
+        RCC.cr().modify(|w| w.set_msion(true));
+        while !RCC.cr().read().msirdy() {}
+
+        Hertz(32_768 * (1 << (range as u8 + 1)))
+    });
+
+    let hsi = config.hsi.then(|| {
+        RCC.cr().modify(|w| w.set_hsion(true));
+        while !RCC.cr().read().hsirdy() {}
+
+        HSI_FREQ
+    });
+
+    let hse = config.hse.map(|hse| {
+        RCC.cr().modify(|w| {
+            w.set_hsebyp(hse.mode == HseMode::Bypass);
+            w.set_hseon(true);
+        });
+        while !RCC.cr().read().hserdy() {}
+
+        hse.freq
+    });
+
+    let pll = config.pll.map(|pll| {
+        let freq = match pll.source {
+            PLLSource::HSE => hse.unwrap(),
+            PLLSource::HSI => hsi.unwrap(),
+        };
+
+        // Disable PLL
+        RCC.cr().modify(|w| w.set_pllon(false));
+        while RCC.cr().read().pllrdy() {}
+
+        let freq = freq * pll.mul / pll.div;
+
+        assert!(freq <= Hertz(32_000_000));
+
+        RCC.cfgr().write(move |w| {
+            w.set_pllmul(pll.mul);
+            w.set_plldiv(pll.div);
+            w.set_pllsrc(pll.source);
+        });
+
+        // Enable PLL
+        RCC.cr().modify(|w| w.set_pllon(true));
+        while !RCC.cr().read().pllrdy() {}
+
+        freq
+    });
+
+    let sys_clk = match config.mux {
+        ClockSrc::HSE => hse.unwrap(),
+        ClockSrc::HSI => hsi.unwrap(),
+        ClockSrc::MSI => msi.unwrap(),
+        ClockSrc::PLL1_P => pll.unwrap(),
+    };
+
     let wait_states = match (config.voltage_scale, sys_clk.0) {
         (VoltageScale::RANGE1, ..=16_000_000) => 0,
         (VoltageScale::RANGE2, ..=8_000_000) => 0,
@@ -150,7 +163,7 @@ pub(crate) unsafe fn init(config: Config) {
     FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
 
     RCC.cfgr().modify(|w| {
-        w.set_sw(sw);
+        w.set_sw(config.mux);
         w.set_hpre(config.ahb_pre);
         w.set_ppre1(config.apb1_pre);
         w.set_ppre2(config.apb2_pre);
@@ -161,7 +174,7 @@ pub(crate) unsafe fn init(config: Config) {
     let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
 
     #[cfg(crs)]
-    if config.enable_hsi48 {
+    if config.hsi48 {
         // Reset CRS peripheral
         RCC.apb1rstr().modify(|w| w.set_crsrst(true));
         RCC.apb1rstr().modify(|w| w.set_crsrst(false));
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index 0d052713f..44748620c 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -193,9 +193,6 @@ pub(crate) unsafe fn init(config: Config) {
         });
         while !RCC.cr().read().msirdy() {}
 
-        // Enable as clock source for USB, RNG if running at 48 MHz
-        if range == MSIRange::RANGE48M {}
-
         msirange_to_hertz(range)
     });
 
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index af82b9955..441b00c6d 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -12,7 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
 #[embassy_executor::main]
 async fn main(_spawner: Spawner) {
     let mut config = Config::default();
-    config.rcc.enable_hsi48 = true;
+    config.rcc.hsi48 = true;
     let p = embassy_stm32::init(config);
 
     let button = Input::new(p.PB2, Pull::Up);
diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs
index 5c2b331cc..61024ef79 100644
--- a/examples/stm32l0/src/bin/lora_cad.rs
+++ b/examples/stm32l0/src/bin/lora_cad.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
 async fn main(_spawner: Spawner) {
     let mut config = embassy_stm32::Config::default();
     config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
-    config.rcc.enable_hsi48 = true;
+    config.rcc.hsi48 = true;
     let p = embassy_stm32::init(config);
 
     let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs
index d44d03d3b..9c4f32916 100644
--- a/examples/stm32l0/src/bin/lora_lorawan.rs
+++ b/examples/stm32l0/src/bin/lora_lorawan.rs
@@ -34,7 +34,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th
 async fn main(_spawner: Spawner) {
     let mut config = embassy_stm32::Config::default();
     config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
-    config.rcc.enable_hsi48 = true;
+    config.rcc.hsi48 = true;
     let p = embassy_stm32::init(config);
 
     let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
index 0478ce1ea..4a50182c2 100644
--- a/examples/stm32l0/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
 async fn main(_spawner: Spawner) {
     let mut config = embassy_stm32::Config::default();
     config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
-    config.rcc.enable_hsi48 = true;
+    config.rcc.hsi48 = true;
     let p = embassy_stm32::init(config);
 
     let mut spi_config = spi::Config::default();
diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs
index 88a836d36..f6de6a5cd 100644
--- a/examples/stm32l0/src/bin/lora_p2p_send.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_send.rs
@@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
 async fn main(_spawner: Spawner) {
     let mut config = embassy_stm32::Config::default();
     config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
-    config.rcc.enable_hsi48 = true;
+    config.rcc.hsi48 = true;
     let p = embassy_stm32::init(config);
 
     let mut spi_config = spi::Config::default();
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index ff808281a..54e23e436 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -460,23 +460,25 @@ pub fn config() -> Config {
     #[cfg(feature = "stm32l073rz")]
     {
         use embassy_stm32::rcc::*;
-        config.rcc.mux = ClockSrc::PLL(
-            // 32Mhz clock (16 * 4 / 2)
-            PLLSource::HSI,
-            PLLMul::MUL4,
-            PLLDiv::DIV2,
-        );
+        config.rcc.hsi = true;
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSI,
+            mul: PLLMul::MUL4,
+            div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
+        });
+        config.rcc.mux = ClockSrc::PLL1_P;
     }
 
     #[cfg(any(feature = "stm32l152re"))]
     {
         use embassy_stm32::rcc::*;
-        config.rcc.mux = ClockSrc::PLL(
-            // 32Mhz clock (16 * 4 / 2)
-            PLLSource::HSI,
-            PLLMul::MUL4,
-            PLLDiv::DIV2,
-        );
+        config.rcc.hsi = true;
+        config.rcc.pll = Some(Pll {
+            source: PLLSource::HSI,
+            mul: PLLMul::MUL4,
+            div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
+        });
+        config.rcc.mux = ClockSrc::PLL1_P;
     }
 
     config