From 739c69bd637baf471585648db4d253089301d6c8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 13 Feb 2024 00:58:18 +0100 Subject: [PATCH 1/4] stm32/rcc: some f3 fixes. --- embassy-stm32/src/rcc/f3.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index 0a5e67b4a..580aa389f 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -222,8 +222,8 @@ pub(crate) unsafe fn init(config: Config) { // Set prescalers // CFGR has been written before (PLL, PLL48) don't overwrite these settings RCC.cfgr().modify(|w| { - w.set_ppre2(config.apb1_pre); - w.set_ppre1(config.apb2_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); w.set_hpre(config.ahb_pre); }); @@ -234,6 +234,7 @@ pub(crate) unsafe fn init(config: Config) { // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings RCC.cfgr().modify(|w| w.set_sw(config.sys)); + while RCC.cfgr().read().sws() != config.sys {} let rtc = config.ls.init(); From b7c147445a98ced9557ca6c0950f6083d0cf09af Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 12 Feb 2024 21:54:53 +0100 Subject: [PATCH 2/4] stm32/rcc: port F1 to new API. --- embassy-stm32/src/rcc/f1.rs | 390 +++++++++++++++---------- examples/stm32f1/src/bin/hello.rs | 4 +- examples/stm32f1/src/bin/usb_serial.rs | 20 +- tests/stm32/.cargo/config.toml | 4 +- tests/stm32/src/common.rs | 18 ++ 5 files changed, 266 insertions(+), 170 deletions(-) diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs index 7f0adab27..9fdd4c11c 100644 --- a/embassy-stm32/src/rcc/f1.rs +++ b/embassy-stm32/src/rcc/f1.rs @@ -1,191 +1,257 @@ -use core::convert::TryFrom; - use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::*; +use crate::pac::rcc::vals::Pllsrc; +#[cfg(any(rcc_f1, rcc_f1cl))] +use crate::pac::rcc::vals::Usbpre; +pub use crate::pac::rcc::vals::{ + Adcpre as ADCPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Pllxtpre as PllPreDiv, Ppre as APBPrescaler, + Sw as Sysclk, +}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// Configuration of the clocks -/// -#[non_exhaustive] -#[derive(Default)] -pub struct Config { - pub hse: Option, +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum HseMode { + /// crystal/ceramic oscillator (HSEBYP=0) + Oscillator, + /// external analog clock (low swing) (HSEBYP=1) + Bypass, +} - pub sys_ck: Option, - pub hclk: Option, - pub pclk1: Option, - pub pclk2: Option, - pub adcclk: Option, - pub pllxtpre: bool, +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct Hse { + /// HSE frequency. + pub freq: Hertz, + /// HSE mode. + pub mode: HseMode, +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum PllSource { + HSE, + HSI, +} + +#[derive(Clone, Copy)] +pub struct Pll { + pub src: PllSource, + + /// PLL pre-divider. + /// + /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. + pub prediv: PllPreDiv, + + /// PLL multiplication factor. + pub mul: PllMul, +} + +/// Clocks configutation +#[non_exhaustive] +pub struct Config { + pub hsi: bool, + pub hse: Option, + pub sys: Sysclk, + + pub pll: Option, + + pub ahb_pre: AHBPrescaler, + pub apb1_pre: APBPrescaler, + pub apb2_pre: APBPrescaler, + + pub adc_pre: ADCPrescaler, pub ls: super::LsConfig, } -pub(crate) unsafe fn init(config: Config) { - let pllxtpre_div = if config.pllxtpre { 2 } else { 1 }; - let pllsrcclk = config.hse.map(|hse| hse.0 / pllxtpre_div).unwrap_or(HSI_FREQ.0 / 2); +impl Default for Config { + fn default() -> Self { + Self { + hsi: true, + hse: None, + sys: Sysclk::HSI, + pll: None, + ahb_pre: AHBPrescaler::DIV1, + apb1_pre: APBPrescaler::DIV1, + apb2_pre: APBPrescaler::DIV1, + ls: Default::default(), - let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); - let pllmul = sysclk / pllsrcclk; - - let (pllmul_bits, real_sysclk) = if pllmul == 1 { - (None, config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0)) - } else { - let pllmul = core::cmp::min(core::cmp::max(pllmul, 1), 16); - (Some(pllmul as u8 - 2), pllsrcclk * pllmul) - }; - - assert!(real_sysclk <= 72_000_000); - - let hpre_bits = config - .hclk - .map(|hclk| match real_sysclk / hclk.0 { - 0 => unreachable!(), - 1 => 0b0111, - 2 => 0b1000, - 3..=5 => 0b1001, - 6..=11 => 0b1010, - 12..=39 => 0b1011, - 40..=95 => 0b1100, - 96..=191 => 0b1101, - 192..=383 => 0b1110, - _ => 0b1111, - }) - .unwrap_or(0b0111); - - let hclk = if hpre_bits >= 0b1100 { - real_sysclk / (1 << (hpre_bits - 0b0110)) - } else { - real_sysclk / (1 << (hpre_bits - 0b0111)) - }; - - assert!(hclk <= 72_000_000); - - let ppre1_bits = config - .pclk1 - .map(|pclk1| match hclk / pclk1.0 { - 0 => unreachable!(), - 1 => 0b011, - 2 => 0b100, - 3..=5 => 0b101, - 6..=11 => 0b110, - _ => 0b111, - }) - .unwrap_or(0b011); - - let ppre1 = 1 << (ppre1_bits - 0b011); - let pclk1 = hclk / u32::try_from(ppre1).unwrap(); - let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; - - assert!(pclk1 <= 36_000_000); - - let ppre2_bits = config - .pclk2 - .map(|pclk2| match hclk / pclk2.0 { - 0 => unreachable!(), - 1 => 0b011, - 2 => 0b100, - 3..=5 => 0b101, - 6..=11 => 0b110, - _ => 0b111, - }) - .unwrap_or(0b011); - - let ppre2 = 1 << (ppre2_bits - 0b011); - let pclk2 = hclk / u32::try_from(ppre2).unwrap(); - let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; - - assert!(pclk2 <= 72_000_000); - - FLASH.acr().write(|w| { - w.set_latency(if real_sysclk <= 24_000_000 { - Latency::WS0 - } else if real_sysclk <= 48_000_000 { - Latency::WS1 - } else { - Latency::WS2 - }); - // the prefetch buffer is enabled by default, let's keep it enabled - w.set_prftbe(true); - }); - - // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the - // PLL output frequency is a supported one. - // usbpre == false: divide clock by 1.5, otherwise no division - #[cfg(not(rcc_f100))] - let (usbpre, _usbclk_valid) = match (config.hse, pllmul_bits, real_sysclk) { - (Some(_), Some(_), 72_000_000) => (false, true), - (Some(_), Some(_), 48_000_000) => (true, true), - _ => (true, false), - }; - - let apre_bits: u8 = config - .adcclk - .map(|adcclk| match pclk2 / adcclk.0 { - 0..=2 => 0b00, - 3..=4 => 0b01, - 5..=7 => 0b10, - _ => 0b11, - }) - .unwrap_or(0b11); - - let apre = (apre_bits + 1) << 1; - let adcclk = pclk2 / unwrap!(u32::try_from(apre)); - - assert!(adcclk <= 14_000_000); - - if config.hse.is_some() { - // enable HSE and wait for it to be ready - RCC.cr().modify(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} + // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) + adc_pre: ADCPrescaler::DIV6, + } } +} - if let Some(pllmul_bits) = pllmul_bits { - let pllctpre_flag: u8 = if config.pllxtpre { 1 } else { 0 }; - RCC.cfgr() - .modify(|w| w.set_pllxtpre(Pllxtpre::from_bits(pllctpre_flag))); +/// Initialize and Set the clock frequencies +pub(crate) unsafe fn init(config: Config) { + // Configure HSI + let hsi = match config.hsi { + false => { + RCC.cr().modify(|w| w.set_hsion(false)); + None + } + true => { + RCC.cr().modify(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + Some(HSI_FREQ) + } + }; + + // Configure HSE + let hse = match config.hse { + None => { + RCC.cr().modify(|w| w.set_hseon(false)); + None + } + Some(hse) => { + match hse.mode { + HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), + HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), + } + + RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); + RCC.cr().modify(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + Some(hse.freq) + } + }; + + // Enable PLL + let pll = config.pll.map(|pll| { + let (src_val, src_freq) = match pll.src { + PllSource::HSI => { + if pll.prediv != PllPreDiv::DIV2 { + panic!("if PLL source is HSI, PLL prediv must be 2."); + } + (Pllsrc::HSI_DIV2, unwrap!(hsi)) + } + PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), + }; + let in_freq = src_freq / pll.prediv; + assert!(max::PLL_IN.contains(&in_freq)); + let out_freq = in_freq * pll.mul; + assert!(max::PLL_OUT.contains(&out_freq)); - // enable PLL and wait for it to be ready RCC.cfgr().modify(|w| { - w.set_pllmul(Pllmul::from_bits(pllmul_bits)); - w.set_pllsrc(Pllsrc::from_bits(config.hse.is_some() as u8)); + w.set_pllmul(pll.mul); + w.set_pllsrc(src_val); + w.set_pllxtpre(pll.prediv); }); - RCC.cr().modify(|w| w.set_pllon(true)); while !RCC.cr().read().pllrdy() {} - } - // Only needed for stm32f103? - RCC.cfgr().modify(|w| { - w.set_adcpre(Adcpre::from_bits(apre_bits)); - w.set_ppre2(Ppre::from_bits(ppre2_bits)); - w.set_ppre1(Ppre::from_bits(ppre1_bits)); - w.set_hpre(Hpre::from_bits(hpre_bits)); - #[cfg(not(rcc_f100))] - w.set_usbpre(Usbpre::from_bits(usbpre as u8)); - w.set_sw(if pllmul_bits.is_some() { - Sw::PLL1_P - } else if config.hse.is_some() { - Sw::HSE - } else { - Sw::HSI - }); + out_freq }); + #[cfg(any(rcc_f1, rcc_f1cl))] + let usb = match pll { + Some(Hertz(72_000_000)) => { + RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5)); + Some(Hertz(48_000_000)) + } + Some(Hertz(48_000_000)) => { + RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1)); + Some(Hertz(48_000_000)) + } + _ => None, + }; + + // Configure sysclk + let sys = match config.sys { + Sysclk::HSI => unwrap!(hsi), + Sysclk::HSE => unwrap!(hse), + Sysclk::PLL1_P => unwrap!(pll), + _ => unreachable!(), + }; + + let hclk = sys / config.ahb_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::HCLK.contains(&hclk)); + assert!(max::PCLK1.contains(&pclk1)); + assert!(max::PCLK2.contains(&pclk2)); + + let adc = pclk2 / config.adc_pre; + assert!(max::ADC.contains(&adc)); + + // Set latency based on HCLK frquency + let latency = match hclk.0 { + ..=24_000_000 => Latency::WS0, + ..=48_000_000 => Latency::WS1, + _ => Latency::WS2, + }; + FLASH.acr().modify(|w| { + w.set_latency(latency); + // RM0316: "The prefetch buffer must be kept on when using a prescaler + // different from 1 on the AHB clock.", "Half-cycle access cannot be + // used when there is a prescaler different from 1 on the AHB clock" + if config.ahb_pre != AHBPrescaler::DIV1 { + w.set_hlfcya(false); + w.set_prftbe(true); + } + }); + + // Set prescalers + // CFGR has been written before (PLL, PLL48) don't overwrite these settings + RCC.cfgr().modify(|w| { + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); + w.set_hpre(config.ahb_pre); + w.set_adcpre(config.adc_pre); + }); + + // 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" + cortex_m::asm::delay(16); + + // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings + RCC.cfgr().modify(|w| w.set_sw(config.sys)); + while RCC.cfgr().read().sws() != config.sys {} + let rtc = config.ls.init(); set_clocks!( - sys: Some(Hertz(real_sysclk)), - pclk1: Some(Hertz(pclk1)), - pclk2: Some(Hertz(pclk2)), - pclk1_tim: Some(Hertz(pclk1 * timer_mul1)), - pclk2_tim: Some(Hertz(pclk2 * timer_mul2)), - hclk1: Some(Hertz(hclk)), - adc: Some(Hertz(adcclk)), + hsi: hsi, + hse: hse, + pll1_p: pll, + sys: Some(sys), + pclk1: Some(pclk1), + pclk2: Some(pclk2), + pclk1_tim: Some(pclk1_tim), + pclk2_tim: Some(pclk2_tim), + hclk1: Some(hclk), + adc: Some(adc), rtc: rtc, + #[cfg(any(rcc_f1, rcc_f1cl))] + usb: usb, + lse: None, ); } + +mod max { + use core::ops::RangeInclusive; + + use crate::time::Hertz; + + #[cfg(not(rcc_f1cl))] + pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(16_000_000); + #[cfg(not(rcc_f1cl))] + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); + + #[cfg(rcc_f1cl)] + pub(crate) const HSE_OSC: RangeInclusive = Hertz(3_000_000)..=Hertz(25_000_000); + #[cfg(rcc_f1cl)] + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(50_000_000); + + pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(72_000_000); + pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(36_000_000); + pub(crate) const PCLK2: RangeInclusive = Hertz(0)..=Hertz(72_000_000); + + pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); + pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(72_000_000); + + pub(crate) const ADC: RangeInclusive = Hertz(0)..=Hertz(14_000_000); +} diff --git a/examples/stm32f1/src/bin/hello.rs b/examples/stm32f1/src/bin/hello.rs index 7b761ecc1..3c295612c 100644 --- a/examples/stm32f1/src/bin/hello.rs +++ b/examples/stm32f1/src/bin/hello.rs @@ -3,15 +3,13 @@ use defmt::info; use embassy_executor::Spawner; -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 mut config = Config::default(); - config.rcc.sys_ck = Some(Hertz(36_000_000)); + let config = Config::default(); let _p = embassy_stm32::init(config); loop { diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs index e28381893..1ae6c1dee 100644 --- a/examples/stm32f1/src/bin/usb_serial.rs +++ b/examples/stm32f1/src/bin/usb_serial.rs @@ -21,9 +21,23 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.hse = Some(Hertz(8_000_000)); - config.rcc.sys_ck = Some(Hertz(48_000_000)); - config.rcc.pclk1 = Some(Hertz(24_000_000)); + { + use embassy_stm32::rcc::*; + config.rcc.hse = Some(Hse { + freq: Hertz(8_000_000), + // Oscillator for bluepill, Bypass for nucleos. + mode: HseMode::Oscillator, + }); + config.rcc.pll = Some(Pll { + src: PllSource::HSE, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL9, + }); + config.rcc.sys = Sysclk::PLL1_P; + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + } let mut p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/tests/stm32/.cargo/config.toml b/tests/stm32/.cargo/config.toml index 8e32b4cee..528bd3451 100644 --- a/tests/stm32/.cargo/config.toml +++ b/tests/stm32/.cargo/config.toml @@ -14,9 +14,9 @@ rustflags = [ ] [build] -target = "thumbv6m-none-eabi" +#target = "thumbv6m-none-eabi" #target = "thumbv7m-none-eabi" -#target = "thumbv7em-none-eabi" +target = "thumbv7em-none-eabi" #target = "thumbv8m.main-none-eabihf" [env] diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 36fe8a235..182ad6298 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -247,6 +247,24 @@ pub fn config() -> Config { config.rcc = embassy_stm32::rcc::WPAN_DEFAULT; } + #[cfg(feature = "stm32f103c8")] + { + use embassy_stm32::rcc::*; + config.rcc.hse = Some(Hse { + freq: Hertz(8_000_000), + mode: HseMode::Oscillator, + }); + config.rcc.pll = Some(Pll { + src: PllSource::HSE, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL9, + }); + config.rcc.sys = Sysclk::PLL1_P; + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV2; + config.rcc.apb2_pre = APBPrescaler::DIV1; + } + #[cfg(feature = "stm32f207zg")] { use embassy_stm32::rcc::*; From ccd2c574c37d26d09f67d6410d79e7e3e16e6119 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 13 Feb 2024 01:15:20 +0100 Subject: [PATCH 3/4] stm32/rcc: port F0 to new API. --- ci.sh | 7 + embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/f0.rs | 338 +++++++++++++++++++---------------- embassy-stm32/src/rcc/mco.rs | 6 +- embassy-stm32/src/rcc/mod.rs | 16 +- 5 files changed, 207 insertions(+), 164 deletions(-) diff --git a/ci.sh b/ci.sh index 58a288441..7ecca92af 100755 --- a/ci.sh +++ b/ci.sh @@ -88,6 +88,13 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt,exti \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32l552ze,defmt \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f038f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f030c6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f058t8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f030r8,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f031k6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f030rc,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f070f6,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f078vb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f042g4,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f072c8,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f401ve,defmt,exti,time-driver-any \ diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index cc76408f3..4c27164ce 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -68,7 +68,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a3ad0b738292ae40af201d79b28db60fe876e11" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] } proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a3ad0b738292ae40af201d79b28db60fe876e11", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs index 1042a1cb2..d6f995e45 100644 --- a/embassy-stm32/src/rcc/f0.rs +++ b/embassy-stm32/src/rcc/f0.rs @@ -1,27 +1,64 @@ -use stm32_metapac::flash::vals::Latency; - -use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Sw, Usbsw}; +use crate::pac::flash::vals::Latency; +use crate::pac::rcc::vals::Pllsrc; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv, Sw as Sysclk, +}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// Configuration of the clocks -/// -/// hse takes precedence over hsi48 if both are enabled +#[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, Eq, PartialEq)] +pub enum PllSource { + HSE, + HSI, + #[cfg(rcc_f0v4)] + HSI48, +} + +#[derive(Clone, Copy)] +pub struct Pll { + pub src: PllSource, + + /// PLL pre-divider. + /// + /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. + pub prediv: PllPreDiv, + + /// PLL multiplication factor. + pub mul: PllMul, +} + +/// Clocks configutation #[non_exhaustive] pub struct Config { - pub hse: Option, - pub bypass_hse: bool, - pub usb_pll: bool, - + pub hsi: bool, + pub hse: Option, #[cfg(crs)] pub hsi48: Option, + pub sys: Sysclk, - pub sys_ck: Option, - pub hclk: Option, - pub pclk: Option, + pub pll: Option, + + pub ahb_pre: AHBPrescaler, + pub apb1_pre: APBPrescaler, pub ls: super::LsConfig, } @@ -29,168 +66,167 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { - hse: Default::default(), - bypass_hse: Default::default(), - usb_pll: Default::default(), + hsi: true, + hse: None, #[cfg(crs)] hsi48: Some(Default::default()), - sys_ck: Default::default(), - hclk: Default::default(), - pclk: Default::default(), + sys: Sysclk::HSI, + pll: None, + ahb_pre: AHBPrescaler::DIV1, + apb1_pre: APBPrescaler::DIV1, ls: Default::default(), } } } +/// Initialize and Set the clock frequencies pub(crate) unsafe fn init(config: Config) { - let sysclk = config.sys_ck.map(|v| v.0).unwrap_or(HSI_FREQ.0); + // Configure HSI + let hsi = match config.hsi { + false => { + RCC.cr().modify(|w| w.set_hsion(false)); + None + } + true => { + RCC.cr().modify(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + Some(HSI_FREQ) + } + }; + // Configure HSE + let hse = match config.hse { + None => { + RCC.cr().modify(|w| w.set_hseon(false)); + None + } + Some(hse) => { + match hse.mode { + HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), + HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), + } + + RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); + RCC.cr().modify(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + Some(hse.freq) + } + }; + + // configure HSI48 #[cfg(crs)] let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); #[cfg(not(crs))] let hsi48: Option = None; - let (src_clk, use_hsi48) = config.hse.map(|v| (v.0, false)).unwrap_or_else(|| { - if hsi48.is_some() { - return (48_000_000, true); - } - (HSI_FREQ.0, false) - }); + // Enable PLL + let pll = config.pll.map(|pll| { + let (src_val, src_freq) = match pll.src { + #[cfg(not(any(rcc_f0v1, rcc_f0v2)))] + PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), + #[cfg(any(rcc_f0v1, rcc_f0v2))] + PllSource::HSI => { + if pll.prediv != PllPreDiv::DIV2 { + panic!("if PLL source is HSI, PLL prediv must be 2."); + } + (Pllsrc::HSI_DIV2, unwrap!(hsi)) + } + PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), + #[cfg(rcc_f0v4)] + PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), + }; + let in_freq = src_freq / pll.prediv; + assert!(max::PLL_IN.contains(&in_freq)); + let out_freq = in_freq * pll.mul; + assert!(max::PLL_OUT.contains(&out_freq)); - let (pllmul_bits, real_sysclk) = if sysclk == src_clk { - (None, sysclk) - } else { - let prediv = if config.hse.is_some() { 1 } else { 2 }; - let pllmul = (2 * prediv * sysclk + src_clk) / src_clk / 2; - let pllmul = pllmul.max(2).min(16); - - let pllmul_bits = pllmul as u8 - 2; - let real_sysclk = pllmul * src_clk / prediv; - (Some(pllmul_bits), real_sysclk) - }; - - let hpre_bits = config - .hclk - .map(|hclk| match real_sysclk / hclk.0 { - 0 => unreachable!(), - 1 => 0b0111, - 2 => 0b1000, - 3..=5 => 0b1001, - 6..=11 => 0b1010, - 12..=39 => 0b1011, - 40..=95 => 0b1100, - 96..=191 => 0b1101, - 192..=383 => 0b1110, - _ => 0b1111, - }) - .unwrap_or(0b0111); - let hclk = real_sysclk / (1 << (hpre_bits - 0b0111)); - - let ppre_bits = config - .pclk - .map(|pclk| match hclk / pclk.0 { - 0 => unreachable!(), - 1 => 0b011, - 2 => 0b100, - 3..=5 => 0b101, - 6..=11 => 0b110, - _ => 0b111, - }) - .unwrap_or(0b011); - - let ppre: u8 = 1 << (ppre_bits - 0b011); - let pclk = hclk / u32::from(ppre); - - let timer_mul = if ppre == 1 { 1 } else { 2 }; - - FLASH.acr().write(|w| { - w.set_latency(if real_sysclk <= 24_000_000 { - Latency::WS0 - } else { - Latency::WS1 + RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); + RCC.cfgr().modify(|w| { + w.set_pllmul(pll.mul); + w.set_pllsrc(src_val); }); - }); - - match (config.hse.is_some(), use_hsi48) { - (true, _) => { - RCC.cr().modify(|w| { - w.set_csson(true); - w.set_hseon(true); - w.set_hsebyp(config.bypass_hse); - }); - while !RCC.cr().read().hserdy() {} - - if pllmul_bits.is_some() { - RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSE_DIV_PREDIV)) - } - } - // use_hsi48 will always be false for stm32f0x0 - #[cfg(not(stm32f0x0))] - (false, true) => { - RCC.cr2().modify(|w| w.set_hsi48on(true)); - while !RCC.cr2().read().hsi48rdy() {} - - if pllmul_bits.is_some() { - RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI48_DIV_PREDIV)) - } - } - _ => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - if pllmul_bits.is_some() { - RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI_DIV2)) - } - } - } - - if config.usb_pll { - RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLL1_P)); - } - // TODO: Option to use CRS (Clock Recovery) - - if let Some(pllmul_bits) = pllmul_bits { - RCC.cfgr().modify(|w| w.set_pllmul(Pllmul::from_bits(pllmul_bits))); - RCC.cr().modify(|w| w.set_pllon(true)); while !RCC.cr().read().pllrdy() {} - RCC.cfgr().modify(|w| { - w.set_ppre(Ppre::from_bits(ppre_bits)); - w.set_hpre(Hpre::from_bits(hpre_bits)); - w.set_sw(Sw::PLL1_P) - }); - } else { - RCC.cfgr().modify(|w| { - w.set_ppre(Ppre::from_bits(ppre_bits)); - w.set_hpre(Hpre::from_bits(hpre_bits)); + out_freq + }); - if config.hse.is_some() { - w.set_sw(Sw::HSE); - } else if use_hsi48 { - #[cfg(not(stm32f0x0))] - w.set_sw(Sw::HSI48); - } else { - w.set_sw(Sw::HSI) - } - }) - } + // Configure sysclk + let sys = match config.sys { + Sysclk::HSI => unwrap!(hsi), + Sysclk::HSE => unwrap!(hse), + Sysclk::PLL1_P => unwrap!(pll), + #[cfg(rcc_f0v4)] + Sysclk::HSI48 => unwrap!(hsi48), + #[allow(unreachable_patterns)] + _ => unreachable!(), + }; + + let hclk = sys / config.ahb_pre; + let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); + + assert!(max::HCLK.contains(&hclk)); + assert!(max::PCLK1.contains(&pclk1)); + + // Set latency based on HCLK frquency + let latency = match hclk.0 { + ..=24_000_000 => Latency::WS0, + _ => Latency::WS1, + }; + FLASH.acr().modify(|w| { + w.set_latency(latency); + w.set_prftbe(true); + }); + + // Set prescalers + // CFGR has been written before (PLL, PLL48) don't overwrite these settings + RCC.cfgr().modify(|w| { + w.set_ppre(config.apb1_pre); + w.set_hpre(config.ahb_pre); + }); + + // 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" + cortex_m::asm::delay(16); + + // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings + RCC.cfgr().modify(|w| w.set_sw(config.sys)); + while RCC.cfgr().read().sws() != config.sys {} let rtc = config.ls.init(); set_clocks!( - hsi: None, - lse: None, - sys: Some(Hertz(real_sysclk)), - pclk1: Some(Hertz(pclk)), - pclk2: Some(Hertz(pclk)), - pclk1_tim: Some(Hertz(pclk * timer_mul)), - pclk2_tim: Some(Hertz(pclk * timer_mul)), - hclk1: Some(Hertz(hclk)), - rtc: rtc, + hsi: hsi, + hse: hse, + pll1_p: pll, + sys: Some(sys), + pclk1: Some(pclk1), + pclk2: Some(pclk1), + pclk1_tim: Some(pclk1_tim), + pclk2_tim: Some(pclk1_tim), + hclk1: Some(hclk), + #[cfg(all(not(rcc_f37), adc3_common))] + adc34: Some(adc34), + #[cfg(stm32f334)] + hrtim: hrtim, hsi48: hsi48, - - // TODO: - pll1_p: None, + rtc: rtc, + lse: None, ); } + +mod max { + use core::ops::RangeInclusive; + + use crate::time::Hertz; + + pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(32_000_000); + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(32_000_000); + + pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(48_000_000); + pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(48_000_000); + + pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(24_000_000); + pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(48_000_000); +} diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index db0df9fac..654943bc1 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -4,7 +4,7 @@ use embassy_hal_internal::into_ref; use crate::gpio::sealed::AFType; use crate::gpio::Speed; -#[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))] +#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; #[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] pub use crate::pac::rcc::vals::Mcosel as McoSource; @@ -13,7 +13,7 @@ pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source}; use crate::pac::RCC; use crate::{peripherals, Peripheral}; -#[cfg(any(stm32f1, rcc_f3v1, rcc_f37))] +#[cfg(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37))] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] pub enum McoPrescaler { DIV1, @@ -43,7 +43,7 @@ macro_rules! impl_peri { r.modify(|w| { w.$set_source(source); - #[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))] + #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] w.$set_prescaler(_prescaler); }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 05937cc5d..b7eca0615 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -18,17 +18,17 @@ mod hsi48; #[cfg(crs)] pub use hsi48::*; -#[cfg_attr(rcc_f0, path = "f0.rs")] -#[cfg_attr(any(stm32f1), path = "f1.rs")] -#[cfg_attr(any(stm32f3), path = "f3.rs")] +#[cfg_attr(stm32f0, path = "f0.rs")] +#[cfg_attr(stm32f1, path = "f1.rs")] +#[cfg_attr(stm32f3, path = "f3.rs")] #[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f.rs")] -#[cfg_attr(rcc_c0, path = "c0.rs")] -#[cfg_attr(rcc_g0, path = "g0.rs")] -#[cfg_attr(rcc_g4, path = "g4.rs")] +#[cfg_attr(stm32c0, path = "c0.rs")] +#[cfg_attr(stm32g0, path = "g0.rs")] +#[cfg_attr(stm32g4, path = "g4.rs")] #[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")] #[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")] -#[cfg_attr(rcc_u5, path = "u5.rs")] -#[cfg_attr(rcc_wba, path = "wba.rs")] +#[cfg_attr(stm32u5, path = "u5.rs")] +#[cfg_attr(stm32wba, path = "wba.rs")] mod _version; pub use _version::*; From 1860e2269311df018a47a9a52f9f942c0285c97b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 14 Feb 2024 00:10:59 +0100 Subject: [PATCH 4/4] stm32/rcc: unify f0, f1, f3. --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/rcc/f0.rs | 232 -------------------- embassy-stm32/src/rcc/{f3.rs => f013.rs} | 163 +++++++++++--- embassy-stm32/src/rcc/f1.rs | 257 ----------------------- embassy-stm32/src/rcc/{f.rs => f247.rs} | 0 embassy-stm32/src/rcc/mod.rs | 6 +- 6 files changed, 137 insertions(+), 525 deletions(-) delete mode 100644 embassy-stm32/src/rcc/f0.rs rename embassy-stm32/src/rcc/{f3.rs => f013.rs} (65%) delete mode 100644 embassy-stm32/src/rcc/f1.rs rename embassy-stm32/src/rcc/{f.rs => f247.rs} (100%) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4c27164ce..c384f14f1 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -68,7 +68,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cc1a1603e61881a6f0a1a47c12c16c57c245ba8" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] } proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cc1a1603e61881a6f0a1a47c12c16c57c245ba8", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs deleted file mode 100644 index d6f995e45..000000000 --- a/embassy-stm32/src/rcc/f0.rs +++ /dev/null @@ -1,232 +0,0 @@ -use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::Pllsrc; -pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv, Sw as Sysclk, -}; -use crate::pac::{FLASH, RCC}; -use crate::time::Hertz; - -/// HSI speed -pub const HSI_FREQ: Hertz = Hertz(8_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, Eq, PartialEq)] -pub enum PllSource { - HSE, - HSI, - #[cfg(rcc_f0v4)] - HSI48, -} - -#[derive(Clone, Copy)] -pub struct Pll { - pub src: PllSource, - - /// PLL pre-divider. - /// - /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. - pub prediv: PllPreDiv, - - /// PLL multiplication factor. - pub mul: PllMul, -} - -/// Clocks configutation -#[non_exhaustive] -pub struct Config { - pub hsi: bool, - pub hse: Option, - #[cfg(crs)] - pub hsi48: Option, - pub sys: Sysclk, - - pub pll: Option, - - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - - pub ls: super::LsConfig, -} - -impl Default for Config { - fn default() -> Self { - Self { - hsi: true, - hse: None, - #[cfg(crs)] - hsi48: Some(Default::default()), - sys: Sysclk::HSI, - pll: None, - ahb_pre: AHBPrescaler::DIV1, - apb1_pre: APBPrescaler::DIV1, - ls: Default::default(), - } - } -} - -/// Initialize and Set the clock frequencies -pub(crate) unsafe fn init(config: Config) { - // Configure HSI - let hsi = match config.hsi { - false => { - RCC.cr().modify(|w| w.set_hsion(false)); - None - } - true => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - Some(HSI_FREQ) - } - }; - - // Configure HSE - let hse = match config.hse { - None => { - RCC.cr().modify(|w| w.set_hseon(false)); - None - } - Some(hse) => { - match hse.mode { - HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), - HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), - } - - RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); - RCC.cr().modify(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - Some(hse.freq) - } - }; - - // configure HSI48 - #[cfg(crs)] - let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); - #[cfg(not(crs))] - let hsi48: Option = None; - - // Enable PLL - let pll = config.pll.map(|pll| { - let (src_val, src_freq) = match pll.src { - #[cfg(not(any(rcc_f0v1, rcc_f0v2)))] - PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), - #[cfg(any(rcc_f0v1, rcc_f0v2))] - PllSource::HSI => { - if pll.prediv != PllPreDiv::DIV2 { - panic!("if PLL source is HSI, PLL prediv must be 2."); - } - (Pllsrc::HSI_DIV2, unwrap!(hsi)) - } - PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), - #[cfg(rcc_f0v4)] - PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), - }; - let in_freq = src_freq / pll.prediv; - assert!(max::PLL_IN.contains(&in_freq)); - let out_freq = in_freq * pll.mul; - assert!(max::PLL_OUT.contains(&out_freq)); - - RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); - RCC.cfgr().modify(|w| { - w.set_pllmul(pll.mul); - w.set_pllsrc(src_val); - }); - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - out_freq - }); - - // Configure sysclk - let sys = match config.sys { - Sysclk::HSI => unwrap!(hsi), - Sysclk::HSE => unwrap!(hse), - Sysclk::PLL1_P => unwrap!(pll), - #[cfg(rcc_f0v4)] - Sysclk::HSI48 => unwrap!(hsi48), - #[allow(unreachable_patterns)] - _ => unreachable!(), - }; - - let hclk = sys / config.ahb_pre; - let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); - - assert!(max::HCLK.contains(&hclk)); - assert!(max::PCLK1.contains(&pclk1)); - - // Set latency based on HCLK frquency - let latency = match hclk.0 { - ..=24_000_000 => Latency::WS0, - _ => Latency::WS1, - }; - FLASH.acr().modify(|w| { - w.set_latency(latency); - w.set_prftbe(true); - }); - - // Set prescalers - // CFGR has been written before (PLL, PLL48) don't overwrite these settings - RCC.cfgr().modify(|w| { - w.set_ppre(config.apb1_pre); - w.set_hpre(config.ahb_pre); - }); - - // 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" - cortex_m::asm::delay(16); - - // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings - RCC.cfgr().modify(|w| w.set_sw(config.sys)); - while RCC.cfgr().read().sws() != config.sys {} - - let rtc = config.ls.init(); - - set_clocks!( - hsi: hsi, - hse: hse, - pll1_p: pll, - sys: Some(sys), - pclk1: Some(pclk1), - pclk2: Some(pclk1), - pclk1_tim: Some(pclk1_tim), - pclk2_tim: Some(pclk1_tim), - hclk1: Some(hclk), - #[cfg(all(not(rcc_f37), adc3_common))] - adc34: Some(adc34), - #[cfg(stm32f334)] - hrtim: hrtim, - hsi48: hsi48, - rtc: rtc, - lse: None, - ); -} - -mod max { - use core::ops::RangeInclusive; - - use crate::time::Hertz; - - pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(32_000_000); - pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(32_000_000); - - pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(48_000_000); - pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(48_000_000); - - pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(24_000_000); - pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(48_000_000); -} diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f013.rs similarity index 65% rename from embassy-stm32/src/rcc/f3.rs rename to embassy-stm32/src/rcc/f013.rs index 580aa389f..c2933186c 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f013.rs @@ -1,9 +1,14 @@ use crate::pac::flash::vals::Latency; -pub use crate::pac::rcc::vals::{ - Adcpres as AdcPllPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv, - Sw as Sysclk, -}; -use crate::pac::rcc::vals::{Pllsrc, Usbpre}; +#[cfg(stm32f1)] +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)] +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}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; @@ -30,6 +35,8 @@ pub struct Hse { pub enum PllSource { HSE, HSI, + #[cfg(rcc_f0v4)] + HSI48, } #[derive(Clone, Copy)] @@ -38,19 +45,21 @@ pub struct Pll { /// PLL pre-divider. /// - /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. + /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. pub prediv: PllPreDiv, /// PLL multiplication factor. pub mul: PllMul, } +#[cfg(all(stm32f3, not(rcc_f37)))] #[derive(Clone, Copy)] pub enum AdcClockSource { Pll(AdcPllPrescaler), Hclk(AdcHclkPrescaler), } +#[cfg(all(stm32f3, not(rcc_f37)))] #[derive(Clone, Copy, PartialEq, Eq)] pub enum AdcHclkPrescaler { Div1, @@ -58,6 +67,7 @@ pub enum AdcHclkPrescaler { Div4, } +#[cfg(stm32f334)] #[derive(Clone, Copy, PartialEq, Eq)] pub enum HrtimClockSource { BusClk, @@ -69,17 +79,23 @@ pub enum HrtimClockSource { pub struct Config { pub hsi: bool, pub hse: Option, + #[cfg(crs)] + pub hsi48: Option, pub sys: Sysclk, pub pll: Option, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, + #[cfg(not(stm32f0))] pub apb2_pre: APBPrescaler, - #[cfg(not(rcc_f37))] + #[cfg(stm32f1)] + pub adc_pre: ADCPrescaler, + + #[cfg(all(stm32f3, not(rcc_f37)))] pub adc: AdcClockSource, - #[cfg(all(not(rcc_f37), adc3_common))] + #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] pub adc34: AdcClockSource, #[cfg(stm32f334)] pub hrtim: HrtimClockSource, @@ -92,16 +108,24 @@ impl Default for Config { Self { hsi: true, hse: None, + #[cfg(crs)] + hsi48: Some(Default::default()), sys: Sysclk::HSI, pll: None, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, + #[cfg(not(stm32f0))] apb2_pre: APBPrescaler::DIV1, ls: Default::default(), - #[cfg(not(rcc_f37))] + #[cfg(stm32f1)] + // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) + adc_pre: ADCPrescaler::DIV6, + + + #[cfg(all(stm32f3, not(rcc_f37)))] adc: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), - #[cfg(all(not(rcc_f37), adc3_common))] + #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), #[cfg(stm32f334)] hrtim: HrtimClockSource::BusClk, @@ -143,13 +167,18 @@ pub(crate) unsafe fn init(config: Config) { } }; + // configure HSI48 + #[cfg(crs)] + let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); + #[cfg(not(crs))] + let hsi48: Option = None; + // Enable PLL - // RM0316: "Reserved, must be kept at reset value." let pll = config.pll.map(|pll| { let (src_val, src_freq) = match pll.src { - #[cfg(rcc_f3v3)] + #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), - #[cfg(not(rcc_f3v3))] + #[cfg(not(any(rcc_f0v3, rcc_f0v4, rcc_f3v3)))] PllSource::HSI => { if pll.prediv != PllPreDiv::DIV2 { panic!("if PLL source is HSI, PLL prediv must be 2."); @@ -157,16 +186,21 @@ pub(crate) unsafe fn init(config: Config) { (Pllsrc::HSI_DIV2, unwrap!(hsi)) } PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), + #[cfg(rcc_f0v4)] + PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), }; let in_freq = src_freq / pll.prediv; assert!(max::PLL_IN.contains(&in_freq)); let out_freq = in_freq * pll.mul; assert!(max::PLL_OUT.contains(&out_freq)); + #[cfg(not(stm32f1))] RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); RCC.cfgr().modify(|w| { w.set_pllmul(pll.mul); w.set_pllsrc(src_val); + #[cfg(stm32f1)] + w.set_pllxtpre(pll.prediv); }); RCC.cr().modify(|w| w.set_pllon(true)); while !RCC.cr().read().pllrdy() {} @@ -174,17 +208,16 @@ pub(crate) unsafe fn init(config: Config) { out_freq }); + #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] let usb = match pll { - Some(Hertz(72_000_000)) => { - RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5)); - Some(Hertz(48_000_000)) - } - Some(Hertz(48_000_000)) => { - RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1)); - Some(Hertz(48_000_000)) - } + 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), _ => None, - }; + } + .map(|usbpre| { + RCC.cfgr().modify(|w| w.set_usbpre(usbpre)); + Hertz(48_000_000) + }); // Configure sysclk let sys = match config.sys { @@ -196,13 +229,28 @@ pub(crate) unsafe fn init(config: Config) { let hclk = sys / config.ahb_pre; let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); + #[cfg(not(stm32f0))] let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); + #[cfg(stm32f0)] + let (pclk2, pclk2_tim) = (pclk1, pclk1_tim); assert!(max::HCLK.contains(&hclk)); assert!(max::PCLK1.contains(&pclk1)); + #[cfg(not(stm32f0))] assert!(max::PCLK2.contains(&pclk2)); + #[cfg(stm32f1)] + let adc = pclk2 / config.adc_pre; + #[cfg(stm32f1)] + assert!(max::ADC.contains(&adc)); + // Set latency based on HCLK frquency + #[cfg(stm32f0)] + let latency = match hclk.0 { + ..=24_000_000 => Latency::WS0, + _ => Latency::WS1, + }; + #[cfg(any(stm32f1, stm32f3))] let latency = match hclk.0 { ..=24_000_000 => Latency::WS0, ..=48_000_000 => Latency::WS1, @@ -213,18 +261,28 @@ pub(crate) unsafe fn init(config: Config) { // RM0316: "The prefetch buffer must be kept on when using a prescaler // different from 1 on the AHB clock.", "Half-cycle access cannot be // used when there is a prescaler different from 1 on the AHB clock" + #[cfg(stm32f3)] if config.ahb_pre != AHBPrescaler::DIV1 { w.set_hlfcya(false); w.set_prftbe(true); } + #[cfg(not(stm32f3))] + w.set_prftbe(true); }); // Set prescalers // CFGR has been written before (PLL, PLL48) don't overwrite these settings - RCC.cfgr().modify(|w| { - w.set_ppre1(config.apb1_pre); - w.set_ppre2(config.apb2_pre); + RCC.cfgr().modify(|w: &mut stm32_metapac::rcc::regs::Cfgr| { + #[cfg(not(stm32f0))] + { + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); + } + #[cfg(stm32f0)] + w.set_ppre(config.apb1_pre); w.set_hpre(config.ahb_pre); + #[cfg(stm32f1)] + w.set_adcpre(config.adc_pre); }); // Wait for the new prescalers to kick in @@ -238,10 +296,10 @@ pub(crate) unsafe fn init(config: Config) { let rtc = config.ls.init(); - #[cfg(not(rcc_f37))] + #[cfg(all(stm32f3, not(rcc_f37)))] use crate::pac::adccommon::vals::Ckmode; - #[cfg(not(rcc_f37))] + #[cfg(all(stm32f3, not(rcc_f37)))] let adc = match config.adc { AdcClockSource::Pll(adcpres) => { RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres)); @@ -265,7 +323,7 @@ pub(crate) unsafe fn init(config: Config) { } }; - #[cfg(all(not(rcc_f37), adc3_common))] + #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] let adc34 = match config.adc34 { AdcClockSource::Pll(adcpres) => { RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres)); @@ -316,18 +374,63 @@ pub(crate) unsafe fn init(config: Config) { pclk1_tim: Some(pclk1_tim), pclk2_tim: Some(pclk2_tim), hclk1: Some(hclk), - #[cfg(not(rcc_f37))] + #[cfg(all(stm32f3, not(rcc_f37)))] adc: Some(adc), - #[cfg(all(not(rcc_f37), adc3_common))] + #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] adc34: Some(adc34), #[cfg(stm32f334)] hrtim: hrtim, rtc: rtc, + hsi48: hsi48, + #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] usb: usb, lse: None, ); } +#[cfg(stm32f0)] +mod max { + use core::ops::RangeInclusive; + + use crate::time::Hertz; + + pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(32_000_000); + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(32_000_000); + + pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(48_000_000); + pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(48_000_000); + + pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(24_000_000); + pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(48_000_000); +} + +#[cfg(stm32f1)] +mod max { + use core::ops::RangeInclusive; + + use crate::time::Hertz; + + #[cfg(not(rcc_f1cl))] + pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(16_000_000); + #[cfg(not(rcc_f1cl))] + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); + + #[cfg(rcc_f1cl)] + pub(crate) const HSE_OSC: RangeInclusive = Hertz(3_000_000)..=Hertz(25_000_000); + #[cfg(rcc_f1cl)] + pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(50_000_000); + + pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(72_000_000); + pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(36_000_000); + pub(crate) const PCLK2: RangeInclusive = Hertz(0)..=Hertz(72_000_000); + + pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); + pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(72_000_000); + + pub(crate) const ADC: RangeInclusive = Hertz(0)..=Hertz(14_000_000); +} + +#[cfg(stm32f3)] mod max { use core::ops::RangeInclusive; diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs deleted file mode 100644 index 9fdd4c11c..000000000 --- a/embassy-stm32/src/rcc/f1.rs +++ /dev/null @@ -1,257 +0,0 @@ -use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::Pllsrc; -#[cfg(any(rcc_f1, rcc_f1cl))] -use crate::pac::rcc::vals::Usbpre; -pub use crate::pac::rcc::vals::{ - Adcpre as ADCPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Pllxtpre as PllPreDiv, Ppre as APBPrescaler, - Sw as Sysclk, -}; -use crate::pac::{FLASH, RCC}; -use crate::time::Hertz; - -/// HSI speed -pub const HSI_FREQ: Hertz = Hertz(8_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, Eq, PartialEq)] -pub enum PllSource { - HSE, - HSI, -} - -#[derive(Clone, Copy)] -pub struct Pll { - pub src: PllSource, - - /// PLL pre-divider. - /// - /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. - pub prediv: PllPreDiv, - - /// PLL multiplication factor. - pub mul: PllMul, -} - -/// Clocks configutation -#[non_exhaustive] -pub struct Config { - pub hsi: bool, - pub hse: Option, - pub sys: Sysclk, - - pub pll: Option, - - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - pub apb2_pre: APBPrescaler, - - pub adc_pre: ADCPrescaler, - - pub ls: super::LsConfig, -} - -impl Default for Config { - fn default() -> Self { - Self { - hsi: true, - hse: None, - sys: Sysclk::HSI, - pll: None, - ahb_pre: AHBPrescaler::DIV1, - apb1_pre: APBPrescaler::DIV1, - apb2_pre: APBPrescaler::DIV1, - ls: Default::default(), - - // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) - adc_pre: ADCPrescaler::DIV6, - } - } -} - -/// Initialize and Set the clock frequencies -pub(crate) unsafe fn init(config: Config) { - // Configure HSI - let hsi = match config.hsi { - false => { - RCC.cr().modify(|w| w.set_hsion(false)); - None - } - true => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - Some(HSI_FREQ) - } - }; - - // Configure HSE - let hse = match config.hse { - None => { - RCC.cr().modify(|w| w.set_hseon(false)); - None - } - Some(hse) => { - match hse.mode { - HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), - HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), - } - - RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); - RCC.cr().modify(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - Some(hse.freq) - } - }; - - // Enable PLL - let pll = config.pll.map(|pll| { - let (src_val, src_freq) = match pll.src { - PllSource::HSI => { - if pll.prediv != PllPreDiv::DIV2 { - panic!("if PLL source is HSI, PLL prediv must be 2."); - } - (Pllsrc::HSI_DIV2, unwrap!(hsi)) - } - PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), - }; - let in_freq = src_freq / pll.prediv; - assert!(max::PLL_IN.contains(&in_freq)); - let out_freq = in_freq * pll.mul; - assert!(max::PLL_OUT.contains(&out_freq)); - - RCC.cfgr().modify(|w| { - w.set_pllmul(pll.mul); - w.set_pllsrc(src_val); - w.set_pllxtpre(pll.prediv); - }); - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - out_freq - }); - - #[cfg(any(rcc_f1, rcc_f1cl))] - let usb = match pll { - Some(Hertz(72_000_000)) => { - RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5)); - Some(Hertz(48_000_000)) - } - Some(Hertz(48_000_000)) => { - RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1)); - Some(Hertz(48_000_000)) - } - _ => None, - }; - - // Configure sysclk - let sys = match config.sys { - Sysclk::HSI => unwrap!(hsi), - Sysclk::HSE => unwrap!(hse), - Sysclk::PLL1_P => unwrap!(pll), - _ => unreachable!(), - }; - - let hclk = sys / config.ahb_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::HCLK.contains(&hclk)); - assert!(max::PCLK1.contains(&pclk1)); - assert!(max::PCLK2.contains(&pclk2)); - - let adc = pclk2 / config.adc_pre; - assert!(max::ADC.contains(&adc)); - - // Set latency based on HCLK frquency - let latency = match hclk.0 { - ..=24_000_000 => Latency::WS0, - ..=48_000_000 => Latency::WS1, - _ => Latency::WS2, - }; - FLASH.acr().modify(|w| { - w.set_latency(latency); - // RM0316: "The prefetch buffer must be kept on when using a prescaler - // different from 1 on the AHB clock.", "Half-cycle access cannot be - // used when there is a prescaler different from 1 on the AHB clock" - if config.ahb_pre != AHBPrescaler::DIV1 { - w.set_hlfcya(false); - w.set_prftbe(true); - } - }); - - // Set prescalers - // CFGR has been written before (PLL, PLL48) don't overwrite these settings - RCC.cfgr().modify(|w| { - w.set_ppre1(config.apb1_pre); - w.set_ppre2(config.apb2_pre); - w.set_hpre(config.ahb_pre); - w.set_adcpre(config.adc_pre); - }); - - // 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" - cortex_m::asm::delay(16); - - // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings - RCC.cfgr().modify(|w| w.set_sw(config.sys)); - while RCC.cfgr().read().sws() != config.sys {} - - let rtc = config.ls.init(); - - set_clocks!( - hsi: hsi, - hse: hse, - pll1_p: pll, - sys: Some(sys), - pclk1: Some(pclk1), - pclk2: Some(pclk2), - pclk1_tim: Some(pclk1_tim), - pclk2_tim: Some(pclk2_tim), - hclk1: Some(hclk), - adc: Some(adc), - rtc: rtc, - #[cfg(any(rcc_f1, rcc_f1cl))] - usb: usb, - lse: None, - ); -} - -mod max { - use core::ops::RangeInclusive; - - use crate::time::Hertz; - - #[cfg(not(rcc_f1cl))] - pub(crate) const HSE_OSC: RangeInclusive = Hertz(4_000_000)..=Hertz(16_000_000); - #[cfg(not(rcc_f1cl))] - pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); - - #[cfg(rcc_f1cl)] - pub(crate) const HSE_OSC: RangeInclusive = Hertz(3_000_000)..=Hertz(25_000_000); - #[cfg(rcc_f1cl)] - pub(crate) const HSE_BYP: RangeInclusive = Hertz(1_000_000)..=Hertz(50_000_000); - - pub(crate) const HCLK: RangeInclusive = Hertz(0)..=Hertz(72_000_000); - pub(crate) const PCLK1: RangeInclusive = Hertz(0)..=Hertz(36_000_000); - pub(crate) const PCLK2: RangeInclusive = Hertz(0)..=Hertz(72_000_000); - - pub(crate) const PLL_IN: RangeInclusive = Hertz(1_000_000)..=Hertz(25_000_000); - pub(crate) const PLL_OUT: RangeInclusive = Hertz(16_000_000)..=Hertz(72_000_000); - - pub(crate) const ADC: RangeInclusive = Hertz(0)..=Hertz(14_000_000); -} diff --git a/embassy-stm32/src/rcc/f.rs b/embassy-stm32/src/rcc/f247.rs similarity index 100% rename from embassy-stm32/src/rcc/f.rs rename to embassy-stm32/src/rcc/f247.rs diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index b7eca0615..0f3467151 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -18,10 +18,8 @@ mod hsi48; #[cfg(crs)] pub use hsi48::*; -#[cfg_attr(stm32f0, path = "f0.rs")] -#[cfg_attr(stm32f1, path = "f1.rs")] -#[cfg_attr(stm32f3, path = "f3.rs")] -#[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f.rs")] +#[cfg_attr(any(stm32f0, stm32f1, stm32f3), path = "f013.rs")] +#[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f247.rs")] #[cfg_attr(stm32c0, path = "c0.rs")] #[cfg_attr(stm32g0, path = "g0.rs")] #[cfg_attr(stm32g4, path = "g4.rs")]