Merge pull request #3779 from algesten/fix/f107-rcc

Full RCC support for STM32F107
This commit is contained in:
Dario Nieuwenhuis 2025-01-24 09:13:45 +00:00 committed by GitHub
commit 4e3d066251
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 91 additions and 5 deletions

View File

@ -1387,7 +1387,7 @@ fn main() {
for e in rcc_registers.ir.enums { for e in rcc_registers.ir.enums {
fn is_rcc_name(e: &str) -> bool { fn is_rcc_name(e: &str) -> bool {
match e { match e {
"Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true,
"Timpre" | "Pllrclkpre" => false, "Timpre" | "Pllrclkpre" => false,
e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
_ => false, _ => false,

View File

@ -4,11 +4,13 @@ pub use crate::pac::rcc::vals::Adcpre as ADCPrescaler;
#[cfg(stm32f3)] #[cfg(stm32f3)]
pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler;
use crate::pac::rcc::vals::Pllsrc; use crate::pac::rcc::vals::Pllsrc;
#[cfg(stm32f1)] #[cfg(all(stm32f1, not(stm32f107)))]
pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv;
#[cfg(any(stm32f0, stm32f3))] #[cfg(any(stm32f0, stm32f3))]
pub use crate::pac::rcc::vals::Prediv 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}; 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, Usbpre as UsbPre};
use crate::pac::{FLASH, RCC}; use crate::pac::{FLASH, RCC};
use crate::time::Hertz; use crate::time::Hertz;
@ -37,6 +39,8 @@ pub enum PllSource {
HSI, HSI,
#[cfg(rcc_f0v4)] #[cfg(rcc_f0v4)]
HSI48, HSI48,
#[cfg(stm32f107)]
PLL2,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -52,6 +56,12 @@ pub struct Pll {
pub mul: PllMul, pub mul: PllMul,
} }
#[cfg(stm32f107)]
#[derive(Clone, Copy)]
pub struct Pll2Or3 {
pub mul: Pll2Mul,
}
#[cfg(all(stm32f3, not(rcc_f37)))] #[cfg(all(stm32f3, not(rcc_f37)))]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum AdcClockSource { pub enum AdcClockSource {
@ -85,6 +95,12 @@ pub struct Config {
pub sys: Sysclk, pub sys: Sysclk,
pub pll: Option<Pll>, pub pll: Option<Pll>,
#[cfg(stm32f107)]
pub pll2: Option<Pll2Or3>,
#[cfg(stm32f107)]
pub pll3: Option<Pll2Or3>,
#[cfg(stm32f107)]
pub prediv2: PllPreDiv,
pub ahb_pre: AHBPrescaler, pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler, pub apb1_pre: APBPrescaler,
@ -99,6 +115,11 @@ pub struct Config {
#[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))]
pub adc34: AdcClockSource, pub adc34: AdcClockSource,
#[cfg(stm32f107)]
pub i2s2_src: I2s2src,
#[cfg(stm32f107)]
pub i2s3_src: I2s2src,
/// Per-peripheral kernel clock selection muxes /// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux, pub mux: super::mux::ClockMux,
@ -114,6 +135,14 @@ impl Default for Config {
hsi48: Some(Default::default()), hsi48: Some(Default::default()),
sys: Sysclk::HSI, sys: Sysclk::HSI,
pll: None, pll: None,
#[cfg(stm32f107)]
pll2: None,
#[cfg(stm32f107)]
pll3: None,
#[cfg(stm32f107)]
prediv2: PllPreDiv::DIV1,
ahb_pre: AHBPrescaler::DIV1, ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1,
#[cfg(not(stm32f0))] #[cfg(not(stm32f0))]
@ -129,6 +158,11 @@ impl Default for Config {
#[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))]
adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
#[cfg(stm32f107)]
i2s2_src: I2s2src::SYS,
#[cfg(stm32f107)]
i2s3_src: I2s2src::SYS,
mux: Default::default(), mux: Default::default(),
} }
} }
@ -175,6 +209,28 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(not(crs))] #[cfg(not(crs))]
let hsi48: Option<Hertz> = None; let hsi48: Option<Hertz> = 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 // Enable PLL
let pll = config.pll.map(|pll| { let pll = config.pll.map(|pll| {
let (src_val, src_freq) = match pll.src { let (src_val, src_freq) = match pll.src {
@ -187,21 +243,44 @@ pub(crate) unsafe fn init(config: Config) {
} }
(Pllsrc::HSI_DIV2, unwrap!(hsi)) (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)] #[cfg(rcc_f0v4)]
PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), 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.");
}
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)
}
}; };
let in_freq = src_freq / pll.prediv; let in_freq = src_freq / pll.prediv;
rcc_assert!(max::PLL_IN.contains(&in_freq)); rcc_assert!(max::PLL_IN.contains(&in_freq));
let out_freq = in_freq * pll.mul; let out_freq = in_freq * pll.mul;
rcc_assert!(max::PLL_OUT.contains(&out_freq)); rcc_assert!(max::PLL_OUT.contains(&out_freq));
#[cfg(not(stm32f1))] #[cfg(not(stm32f1))]
RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv));
#[cfg(stm32f107)]
RCC.cfgr2().modify(|w| w.set_prediv1(pll.prediv));
RCC.cfgr().modify(|w| { RCC.cfgr().modify(|w| {
w.set_pllmul(pll.mul); w.set_pllmul(pll.mul);
w.set_pllsrc(src_val); w.set_pllsrc(src_val);
#[cfg(stm32f1)] #[cfg(all(stm32f1, not(stm32f107)))]
w.set_pllxtpre(pll.prediv); w.set_pllxtpre(pll.prediv);
}); });
RCC.cr().modify(|w| w.set_pllon(true)); RCC.cr().modify(|w| w.set_pllon(true));
@ -213,7 +292,7 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(stm32f3)] #[cfg(stm32f3)]
let pll_mul_2 = pll.map(|pll| pll * 2u32); 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 { let usb = match pll {
Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5), 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), Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1),
@ -293,6 +372,13 @@ pub(crate) unsafe fn init(config: Config) {
w.set_adcpre(config.adc_pre); w.set_adcpre(config.adc_pre);
}); });
// I2S2 and I2S3
#[cfg(stm32f107)]
{
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 // Wait for the new prescalers to kick in
// "The clocks are divided with the new prescaler factor from // "The clocks are divided with the new prescaler factor from
// 1 to 16 AHB cycles after write" // 1 to 16 AHB cycles after write"