From 9a159a8db0638ea2971eed130a2ae34743da640a Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Thu, 16 Jan 2025 11:56:46 +0100 Subject: [PATCH 1/4] Full RCC support for STM32F107 --- embassy-stm32/src/rcc/f013.rs | 112 +++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index 57c5cd5b2e..27e43fa56c 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -4,11 +4,15 @@ pub use crate::pac::rcc::vals::Adcpre as ADCPrescaler; #[cfg(stm32f3)] pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; use crate::pac::rcc::vals::Pllsrc; -#[cfg(stm32f1)] +#[cfg(all(stm32f1, not(stm32f107)))] pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; #[cfg(any(stm32f0, stm32f3))] pub use crate::pac::rcc::vals::Prediv as PllPreDiv; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk}; +#[cfg(stm32f107)] +pub use crate::pac::rcc::vals::{ + I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src as PreDiv1Src, Usbpre as UsbPre, +}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; @@ -52,6 +56,12 @@ pub struct Pll { pub mul: PllMul, } +#[cfg(stm32f107)] +#[derive(Clone, Copy)] +pub struct Pll2Or3 { + pub mul: Pll2Mul, +} + #[cfg(all(stm32f3, not(rcc_f37)))] #[derive(Clone, Copy)] pub enum AdcClockSource { @@ -85,6 +95,14 @@ pub struct Config { pub sys: Sysclk, pub pll: Option, + #[cfg(stm32f107)] + pub pll2: Option, + #[cfg(stm32f107)] + pub pll3: Option, + #[cfg(stm32f107)] + pub prediv1_src: Option, + #[cfg(stm32f107)] + pub prediv2: Option, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, @@ -99,6 +117,11 @@ pub struct Config { #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] pub adc34: AdcClockSource, + #[cfg(stm32f107)] + pub i2s2_src: Option, + #[cfg(stm32f107)] + pub i2s3_src: Option, + /// Per-peripheral kernel clock selection muxes pub mux: super::mux::ClockMux, @@ -114,6 +137,16 @@ impl Default for Config { hsi48: Some(Default::default()), sys: Sysclk::HSI, pll: None, + + #[cfg(stm32f107)] + pll2: None, + #[cfg(stm32f107)] + pll3: None, + #[cfg(stm32f107)] + prediv1_src: None, + #[cfg(stm32f107)] + prediv2: None, + ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, #[cfg(not(stm32f0))] @@ -129,6 +162,11 @@ impl Default for Config { #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), + #[cfg(stm32f107)] + i2s2_src: None, + #[cfg(stm32f107)] + i2s3_src: None, + mux: Default::default(), } } @@ -169,6 +207,13 @@ pub(crate) unsafe fn init(config: Config) { } }; + #[cfg(stm32f107)] + let pll2freq = config.pll2.map(|pll2| { + let prediv2 = config.prediv2.unwrap_or(PllPreDiv::DIV1); + let in_freq = hse.unwrap() / (prediv2.to_bits() + 1); + in_freq * pll2.mul + }); + // configure HSI48 #[cfg(crs)] let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); @@ -177,6 +222,8 @@ pub(crate) unsafe fn init(config: Config) { // Enable PLL let pll = config.pll.map(|pll| { + #[cfg(stm32f107)] + let prediv1_src = config.prediv1_src.unwrap_or(PreDiv1Src::HSE); let (src_val, src_freq) = match pll.src { #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), @@ -187,21 +234,39 @@ pub(crate) unsafe fn init(config: Config) { } (Pllsrc::HSI_DIV2, unwrap!(hsi)) } + #[cfg(not(stm32f107))] PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), + #[cfg(stm32f107)] + PllSource::HSE => ( + Pllsrc::HSE_DIV_PREDIV, + match prediv1_src { + PreDiv1Src::HSE => unwrap!(hse), + PreDiv1Src::PLL2 => unwrap!(pll2freq), + }, + ), #[cfg(rcc_f0v4)] PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), }; + #[cfg(not(stm32f107))] let in_freq = src_freq / pll.prediv; + + #[cfg(stm32f107)] + let in_freq = src_freq / (pll.prediv.to_bits() + 1); + rcc_assert!(max::PLL_IN.contains(&in_freq)); let out_freq = in_freq * pll.mul; rcc_assert!(max::PLL_OUT.contains(&out_freq)); #[cfg(not(stm32f1))] RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); + + #[cfg(stm32f107)] + RCC.cfgr2().modify(|w| w.set_prediv1(pll.prediv)); + RCC.cfgr().modify(|w| { w.set_pllmul(pll.mul); w.set_pllsrc(src_val); - #[cfg(stm32f1)] + #[cfg(all(stm32f1, not(stm32f107)))] w.set_pllxtpre(pll.prediv); }); RCC.cr().modify(|w| w.set_pllon(true)); @@ -210,10 +275,39 @@ pub(crate) unsafe fn init(config: Config) { out_freq }); + // Prediv1 Source Mux (HSE or PLL2) + #[cfg(stm32f107)] + if let Some(prediv1_src) = config.prediv1_src { + RCC.cfgr2().modify(|w| w.set_prediv1src(prediv1_src)); + } + + // pll2 and pll3 + #[cfg(stm32f107)] + { + // Common prediv for PLL2 and PLL3 + if let Some(prediv) = config.prediv2 { + RCC.cfgr2().modify(|w| w.set_prediv2(prediv)); + } + + // Configure PLL2 + if let Some(pll2) = config.pll2 { + RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul)); + RCC.cr().modify(|w| w.set_pll2on(true)); + while !RCC.cr().read().pll2rdy() {} + } + + // Configure PLL3 + if let Some(pll3) = config.pll3 { + RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul)); + RCC.cr().modify(|w| w.set_pll3on(true)); + while !RCC.cr().read().pll3rdy() {} + } + } + #[cfg(stm32f3)] let pll_mul_2 = pll.map(|pll| pll * 2u32); - #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] + #[cfg(any(rcc_f1, rcc_f1cl, stm32f3, stm32f107))] let usb = match pll { Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5), Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1), @@ -293,6 +387,18 @@ pub(crate) unsafe fn init(config: Config) { w.set_adcpre(config.adc_pre); }); + // I2S2 and I2S3 + #[cfg(stm32f107)] + { + if let Some(i2s2_src) = config.i2s2_src { + RCC.cfgr2().modify(|w| w.set_i2s2src(i2s2_src)); + } + + if let Some(i2s3_src) = config.i2s3_src { + RCC.cfgr2().modify(|w| w.set_i2s3src(i2s3_src)); + } + } + // Wait for the new prescalers to kick in // "The clocks are divided with the new prescaler factor from // 1 to 16 AHB cycles after write" From c72d9ec8599e3474344f8daf8c2e5a7236201e03 Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Fri, 24 Jan 2025 09:08:11 +0100 Subject: [PATCH 2/4] Review fixes --- embassy-stm32/build.rs | 2 +- embassy-stm32/src/rcc/f013.rs | 77 +++++++++++++---------------------- 2 files changed, 29 insertions(+), 50 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 4abbf8d694..09fcc0d03e 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1383,7 +1383,7 @@ fn main() { for e in rcc_registers.ir.enums { fn is_rcc_name(e: &str) -> bool { match e { - "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, + "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true, "Timpre" | "Pllrclkpre" => false, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index 27e43fa56c..d256ace8fc 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -41,6 +41,8 @@ pub enum PllSource { HSI, #[cfg(rcc_f0v4)] HSI48, + #[cfg(stm32f107)] + PLL2, } #[derive(Clone, Copy)] @@ -100,9 +102,7 @@ pub struct Config { #[cfg(stm32f107)] pub pll3: Option, #[cfg(stm32f107)] - pub prediv1_src: Option, - #[cfg(stm32f107)] - pub prediv2: Option, + pub prediv2: PllPreDiv, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, @@ -118,9 +118,9 @@ pub struct Config { pub adc34: AdcClockSource, #[cfg(stm32f107)] - pub i2s2_src: Option, + pub i2s2_src: I2s2src, #[cfg(stm32f107)] - pub i2s3_src: Option, + pub i2s3_src: I2s2src, /// Per-peripheral kernel clock selection muxes pub mux: super::mux::ClockMux, @@ -143,9 +143,7 @@ impl Default for Config { #[cfg(stm32f107)] pll3: None, #[cfg(stm32f107)] - prediv1_src: None, - #[cfg(stm32f107)] - prediv2: None, + prediv2: PllPreDiv::DIV1, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, @@ -163,9 +161,9 @@ impl Default for Config { adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), #[cfg(stm32f107)] - i2s2_src: None, + i2s2_src: I2s2src::SYS, #[cfg(stm32f107)] - i2s3_src: None, + i2s3_src: I2s2src::SYS, mux: Default::default(), } @@ -207,13 +205,6 @@ pub(crate) unsafe fn init(config: Config) { } }; - #[cfg(stm32f107)] - let pll2freq = config.pll2.map(|pll2| { - let prediv2 = config.prediv2.unwrap_or(PllPreDiv::DIV1); - let in_freq = hse.unwrap() / (prediv2.to_bits() + 1); - in_freq * pll2.mul - }); - // configure HSI48 #[cfg(crs)] let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); @@ -222,8 +213,6 @@ pub(crate) unsafe fn init(config: Config) { // Enable PLL let pll = config.pll.map(|pll| { - #[cfg(stm32f107)] - let prediv1_src = config.prediv1_src.unwrap_or(PreDiv1Src::HSE); let (src_val, src_freq) = match pll.src { #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), @@ -234,25 +223,28 @@ pub(crate) unsafe fn init(config: Config) { } (Pllsrc::HSI_DIV2, unwrap!(hsi)) } - #[cfg(not(stm32f107))] - PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), - #[cfg(stm32f107)] - PllSource::HSE => ( - Pllsrc::HSE_DIV_PREDIV, - match prediv1_src { - PreDiv1Src::HSE => unwrap!(hse), - PreDiv1Src::PLL2 => unwrap!(pll2freq), - }, - ), + PllSource::HSE => { + #[cfg(stm32f107)] + RCC.cfgr2().modify(|w| w.set_prediv1src(PreDiv1Src::HSE)); + + (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)) + } #[cfg(rcc_f0v4)] PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), + #[cfg(stm32f107)] + PllSource::PLL2 => { + if config.pll2.is_none() { + panic!("if PLL source is PLL2, Config::pll2 must also be set."); + } + let pll2 = unwrap!(config.pll2); + let in_freq = hse.unwrap() / config.prediv2; + let pll2freq = in_freq * pll2.mul; + RCC.cfgr2().modify(|w| w.set_prediv1src(PreDiv1Src::PLL2)); + (Pllsrc::HSE_DIV_PREDIV, pll2freq) + } }; - #[cfg(not(stm32f107))] let in_freq = src_freq / pll.prediv; - #[cfg(stm32f107)] - let in_freq = src_freq / (pll.prediv.to_bits() + 1); - rcc_assert!(max::PLL_IN.contains(&in_freq)); let out_freq = in_freq * pll.mul; rcc_assert!(max::PLL_OUT.contains(&out_freq)); @@ -275,19 +267,11 @@ pub(crate) unsafe fn init(config: Config) { out_freq }); - // Prediv1 Source Mux (HSE or PLL2) - #[cfg(stm32f107)] - if let Some(prediv1_src) = config.prediv1_src { - RCC.cfgr2().modify(|w| w.set_prediv1src(prediv1_src)); - } - // pll2 and pll3 #[cfg(stm32f107)] { // Common prediv for PLL2 and PLL3 - if let Some(prediv) = config.prediv2 { - RCC.cfgr2().modify(|w| w.set_prediv2(prediv)); - } + RCC.cfgr2().modify(|w| w.set_prediv2(config.prediv2)); // Configure PLL2 if let Some(pll2) = config.pll2 { @@ -390,13 +374,8 @@ pub(crate) unsafe fn init(config: Config) { // I2S2 and I2S3 #[cfg(stm32f107)] { - if let Some(i2s2_src) = config.i2s2_src { - RCC.cfgr2().modify(|w| w.set_i2s2src(i2s2_src)); - } - - if let Some(i2s3_src) = config.i2s3_src { - RCC.cfgr2().modify(|w| w.set_i2s3src(i2s3_src)); - } + RCC.cfgr2().modify(|w| w.set_i2s2src(config.i2s2_src)); + RCC.cfgr2().modify(|w| w.set_i2s3src(config.i2s3_src)); } // Wait for the new prescalers to kick in From 3ba94c0ab3fcb859619fa70fcf37a3505392f05c Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Fri, 24 Jan 2025 09:33:48 +0100 Subject: [PATCH 3/4] Fix init order of set_prediv1src --- embassy-stm32/src/rcc/f013.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index d256ace8fc..8d86629b5c 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -10,9 +10,7 @@ pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; pub use crate::pac::rcc::vals::Prediv as PllPreDiv; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk}; #[cfg(stm32f107)] -pub use crate::pac::rcc::vals::{ - I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src as PreDiv1Src, Usbpre as UsbPre, -}; +pub use crate::pac::rcc::vals::{I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src, Usbpre as UsbPre}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; @@ -223,12 +221,7 @@ pub(crate) unsafe fn init(config: Config) { } (Pllsrc::HSI_DIV2, unwrap!(hsi)) } - PllSource::HSE => { - #[cfg(stm32f107)] - RCC.cfgr2().modify(|w| w.set_prediv1src(PreDiv1Src::HSE)); - - (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)) - } + PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), #[cfg(rcc_f0v4)] PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), #[cfg(stm32f107)] @@ -239,7 +232,6 @@ pub(crate) unsafe fn init(config: Config) { let pll2 = unwrap!(config.pll2); let in_freq = hse.unwrap() / config.prediv2; let pll2freq = in_freq * pll2.mul; - RCC.cfgr2().modify(|w| w.set_prediv1src(PreDiv1Src::PLL2)); (Pllsrc::HSE_DIV_PREDIV, pll2freq) } }; @@ -267,6 +259,13 @@ pub(crate) unsafe fn init(config: Config) { out_freq }); + #[cfg(stm32f107)] + match config.pll.map(|pll| pll.src) { + Some(PllSource::HSE) => RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::HSE)), + Some(PllSource::PLL2) => RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::PLL2)), + _ => {} + } + // pll2 and pll3 #[cfg(stm32f107)] { From 4743501172dadc405f71dec34b0b9fa933c916b8 Mon Sep 17 00:00:00 2001 From: Martin Algesten Date: Fri, 24 Jan 2025 10:06:32 +0100 Subject: [PATCH 4/4] Move PLL2/3 config to before PLL --- embassy-stm32/src/rcc/f013.rs | 60 ++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index 8d86629b5c..13b0ae38e3 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -209,6 +209,28 @@ pub(crate) unsafe fn init(config: Config) { #[cfg(not(crs))] let hsi48: Option = None; + // PLL2 and PLL3 + // Configure this before PLL since PLL2 can be the source for PLL. + #[cfg(stm32f107)] + { + // Common prediv for PLL2 and PLL3 + RCC.cfgr2().modify(|w| w.set_prediv2(config.prediv2)); + + // Configure PLL2 + if let Some(pll2) = config.pll2 { + RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul)); + RCC.cr().modify(|w| w.set_pll2on(true)); + while !RCC.cr().read().pll2rdy() {} + } + + // Configure PLL3 + if let Some(pll3) = config.pll3 { + RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul)); + RCC.cr().modify(|w| w.set_pll3on(true)); + while !RCC.cr().read().pll3rdy() {} + } + } + // Enable PLL let pll = config.pll.map(|pll| { let (src_val, src_freq) = match pll.src { @@ -221,7 +243,12 @@ pub(crate) unsafe fn init(config: Config) { } (Pllsrc::HSI_DIV2, unwrap!(hsi)) } - PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), + PllSource::HSE => { + #[cfg(stm32f107)] + RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::HSE)); + + (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)) + } #[cfg(rcc_f0v4)] PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), #[cfg(stm32f107)] @@ -229,9 +256,12 @@ pub(crate) unsafe fn init(config: Config) { if config.pll2.is_none() { panic!("if PLL source is PLL2, Config::pll2 must also be set."); } + RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::PLL2)); + let pll2 = unwrap!(config.pll2); let in_freq = hse.unwrap() / config.prediv2; let pll2freq = in_freq * pll2.mul; + (Pllsrc::HSE_DIV_PREDIV, pll2freq) } }; @@ -259,34 +289,6 @@ pub(crate) unsafe fn init(config: Config) { out_freq }); - #[cfg(stm32f107)] - match config.pll.map(|pll| pll.src) { - Some(PllSource::HSE) => RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::HSE)), - Some(PllSource::PLL2) => RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::PLL2)), - _ => {} - } - - // pll2 and pll3 - #[cfg(stm32f107)] - { - // Common prediv for PLL2 and PLL3 - RCC.cfgr2().modify(|w| w.set_prediv2(config.prediv2)); - - // Configure PLL2 - if let Some(pll2) = config.pll2 { - RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul)); - RCC.cr().modify(|w| w.set_pll2on(true)); - while !RCC.cr().read().pll2rdy() {} - } - - // Configure PLL3 - if let Some(pll3) = config.pll3 { - RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul)); - RCC.cr().modify(|w| w.set_pll3on(true)); - while !RCC.cr().read().pll3rdy() {} - } - } - #[cfg(stm32f3)] let pll_mul_2 = pll.map(|pll| pll * 2u32);