diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 5258e4c7..20c5155a 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,7 +59,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index a6a83088..3f85d9e6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -52,7 +52,11 @@ fn main() { "rcc" => { for pin in p.pins { if pin.signal.starts_with("MCO") { - singletons.push(pin.signal.replace('_', "").to_string()); + let name = pin.signal.replace('_', "").to_string(); + if !singletons.contains(&name) { + println!("cargo:rustc-cfg={}", name.to_ascii_lowercase()); + singletons.push(name); + } } } singletons.push(p.name.to_string()); diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 5ba958a0..ad106ce3 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -1,16 +1,8 @@ -use core::marker::PhantomData; - -use embassy_hal_internal::into_ref; -use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre}; - -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -use crate::{peripherals, Peripheral}; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); @@ -197,164 +189,6 @@ fn setup_pll( } } -pub enum McoClock { - DIV1, - DIV2, - DIV3, - DIV4, - DIV5, -} - -impl McoClock { - fn into_raw(&self) -> Mcopre { - match self { - McoClock::DIV1 => Mcopre::DIV1, - McoClock::DIV2 => Mcopre::DIV2, - McoClock::DIV3 => Mcopre::DIV3, - McoClock::DIV4 => Mcopre::DIV4, - McoClock::DIV5 => Mcopre::DIV5, - } - } -} - -#[derive(Copy, Clone)] -pub enum Mco1Source { - Hsi, - Lse, - Hse, - Pll, -} - -impl Default for Mco1Source { - fn default() -> Self { - Self::Hsi - } -} - -pub trait McoSource { - type Raw; - - fn into_raw(&self) -> Self::Raw; -} - -impl McoSource for Mco1Source { - type Raw = Mco1; - fn into_raw(&self) -> Self::Raw { - match self { - Mco1Source::Hsi => Mco1::HSI, - Mco1Source::Lse => Mco1::LSE, - Mco1Source::Hse => Mco1::HSE, - Mco1Source::Pll => Mco1::PLL, - } - } -} - -#[derive(Copy, Clone)] -pub enum Mco2Source { - SysClk, - Plli2s, - Hse, - Pll, -} - -impl Default for Mco2Source { - fn default() -> Self { - Self::SysClk - } -} - -impl McoSource for Mco2Source { - type Raw = Mco2; - fn into_raw(&self) -> Self::Raw { - match self { - Mco2Source::SysClk => Mco2::SYSCLK, - Mco2Source::Plli2s => Mco2::PLLI2S, - Mco2Source::Hse => Mco2::HSE, - Mco2Source::Pll => Mco2::PLL, - } - } -} - -pub(crate) mod sealed { - use stm32_metapac::rcc::vals::Mcopre; - pub trait McoInstance { - type Source; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre); - } -} - -pub trait McoInstance: sealed::McoInstance + 'static {} - -pin_trait!(McoPin, McoInstance); - -impl sealed::McoInstance for peripherals::MCO1 { - type Source = Mco1; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { - RCC.cfgr().modify(|w| { - w.set_mco1(source); - w.set_mco1pre(prescaler); - }); - match source { - Mco1::PLL => { - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - } - Mco1::HSI => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - } - _ => {} - } - } -} -impl McoInstance for peripherals::MCO1 {} - -impl sealed::McoInstance for peripherals::MCO2 { - type Source = Mco2; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { - RCC.cfgr().modify(|w| { - w.set_mco2(source); - w.set_mco2pre(prescaler); - }); - match source { - Mco2::PLL => { - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - } - #[cfg(not(stm32f410))] - Mco2::PLLI2S => { - RCC.cr().modify(|w| w.set_plli2son(true)); - while !RCC.cr().read().plli2srdy() {} - } - _ => {} - } - } -} -impl McoInstance for peripherals::MCO2 {} - -pub struct Mco<'d, T: McoInstance> { - phantom: PhantomData<&'d mut T>, -} - -impl<'d, T: McoInstance> Mco<'d, T> { - pub fn new( - _peri: impl Peripheral

+ 'd, - pin: impl Peripheral

> + 'd, - source: impl McoSource, - prescaler: McoClock, - ) -> Self { - into_ref!(pin); - - critical_section::with(|_| unsafe { - T::apply_clock_settings(source.into_raw(), prescaler.into_raw()); - pin.set_as_af(pin.af_num(), AFType::OutputPushPull); - pin.set_speed(Speed::VeryHigh); - }); - - Self { phantom: PhantomData } - } -} - fn flash_setup(sysclk: u32) { use crate::pac::flash::vals::Latency; diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 3a24eca8..2fbb9920 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -1,18 +1,11 @@ -use core::marker::PhantomData; - -use embassy_hal_internal::into_ref; use stm32_metapac::rcc::regs::Cfgr; -use stm32_metapac::rcc::vals::{Mcopre, Mcosel}; pub use super::bus::{AHBPrescaler, APBPrescaler}; -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -use crate::{peripherals, Peripheral}; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); @@ -263,131 +256,6 @@ impl Default for Config { } } -pub enum McoClock { - DIV1, - DIV2, - DIV4, - DIV8, - DIV16, -} - -impl McoClock { - fn into_raw(&self) -> Mcopre { - match self { - McoClock::DIV1 => Mcopre::DIV1, - McoClock::DIV2 => Mcopre::DIV2, - McoClock::DIV4 => Mcopre::DIV4, - McoClock::DIV8 => Mcopre::DIV8, - McoClock::DIV16 => Mcopre::DIV16, - } - } -} - -#[derive(Copy, Clone)] -pub enum Mco1Source { - Disabled, - Lse, - Lsi, - Hse, - Hsi16, - PllClk, - SysClk, - Msi, - #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] - Hsi48, -} - -impl Default for Mco1Source { - fn default() -> Self { - Self::Hsi16 - } -} - -pub trait McoSource { - type Raw; - - fn into_raw(&self) -> Self::Raw; -} - -impl McoSource for Mco1Source { - type Raw = Mcosel; - fn into_raw(&self) -> Self::Raw { - match self { - Mco1Source::Disabled => Mcosel::NOCLOCK, - Mco1Source::Lse => Mcosel::LSE, - Mco1Source::Lsi => Mcosel::LSI, - Mco1Source::Hse => Mcosel::HSE, - Mco1Source::Hsi16 => Mcosel::HSI16, - Mco1Source::PllClk => Mcosel::PLL, - Mco1Source::SysClk => Mcosel::SYSCLK, - Mco1Source::Msi => Mcosel::MSI, - #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] - Mco1Source::Hsi48 => Mcosel::HSI48, - } - } -} - -pub(crate) mod sealed { - use stm32_metapac::rcc::vals::Mcopre; - pub trait McoInstance { - type Source; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre); - } -} - -pub trait McoInstance: sealed::McoInstance + 'static {} - -pin_trait!(McoPin, McoInstance); - -impl sealed::McoInstance for peripherals::MCO { - type Source = Mcosel; - - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { - RCC.cfgr().modify(|w| { - w.set_mcosel(source); - w.set_mcopre(prescaler); - }); - - match source { - Mcosel::HSI16 => { - RCC.cr().modify(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - } - #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] - Mcosel::HSI48 => { - RCC.crrcr().modify(|w| w.set_hsi48on(true)); - while !RCC.crrcr().read().hsi48rdy() {} - } - _ => {} - } - } -} - -impl McoInstance for peripherals::MCO {} - -pub struct Mco<'d, T: McoInstance> { - phantom: PhantomData<&'d mut T>, -} - -impl<'d, T: McoInstance> Mco<'d, T> { - pub fn new( - _peri: impl Peripheral

+ 'd, - pin: impl Peripheral

> + 'd, - source: impl McoSource, - prescaler: McoClock, - ) -> Self { - into_ref!(pin); - - critical_section::with(|_| unsafe { - T::apply_clock_settings(source.into_raw(), prescaler.into_raw()); - pin.set_as_af(pin.af_num(), AFType::OutputPushPull); - pin.set_speed(Speed::VeryHigh); - }); - - Self { phantom: PhantomData } - } -} - pub(crate) unsafe fn init(config: Config) { // Switch to MSI to prevent problems with PLL configuration. if !RCC.cr().read().msion() { diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 85665fd2..eaaf8071 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -4,18 +4,19 @@ use embassy_hal_internal::into_ref; use crate::gpio::sealed::AFType; use crate::gpio::Speed; -#[cfg(not(stm32wl))] -pub use crate::pac::rcc::vals::{Mco1 as Mco1Source, Mco2 as Mco2Source}; -#[cfg(stm32wl)] -pub use crate::pac::rcc::vals::{Mcopre, Mcosel}; +#[cfg(not(stm32f1))] +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; +#[cfg(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::{Mco1sel as Mco1Source, Mco2sel as Mco2Source}; use crate::pac::RCC; use crate::{peripherals, Peripheral}; pub(crate) mod sealed { pub trait McoInstance { type Source; - type Prescaler; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Self::Prescaler); + unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler); } } @@ -24,14 +25,19 @@ pub trait McoInstance: sealed::McoInstance + 'static {} pin_trait!(McoPin, McoInstance); macro_rules! impl_peri { - ($peri:ident, $source:ident, $prescaler:ident, $set_source:ident, $set_prescaler:ident) => { + ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { impl sealed::McoInstance for peripherals::$peri { type Source = $source; - type Prescaler = $prescaler; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: Self::Prescaler) { - RCC.cfgr().modify(|w| { + unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) { + #[cfg(not(any(stm32u5, stm32wba)))] + let r = RCC.cfgr(); + #[cfg(any(stm32u5, stm32wba))] + let r = RCC.cfgr1(); + + r.modify(|w| { w.$set_source(source); + #[cfg(not(stm32f1))] w.$set_prescaler(prescaler); }); } @@ -41,12 +47,16 @@ macro_rules! impl_peri { }; } -#[cfg(not(stm32wl))] -impl_peri!(MCO1, Mco1Source, u8, set_mco1, set_mco1pre); -#[cfg(not(stm32wl))] -impl_peri!(MCO2, Mco2Source, u8, set_mco2, set_mco2pre); -#[cfg(stm32wl)] -impl_peri!(MCO, Mcosel, Mcopre, set_mcosel, set_mcopre); +#[cfg(any(rcc_c0, rcc_g0))] +#[allow(unused_imports)] +use self::{McoSource as Mco1Source, McoSource as Mco2Source}; + +#[cfg(mco)] +impl_peri!(MCO, McoSource, set_mcosel, set_mcopre); +#[cfg(mco1)] +impl_peri!(MCO1, Mco1Source, set_mco1sel, set_mco1pre); +#[cfg(mco2)] +impl_peri!(MCO2, Mco2Source, set_mco2sel, set_mco2pre); pub struct Mco<'d, T: McoInstance> { phantom: PhantomData<&'d mut T>, @@ -54,24 +64,20 @@ pub struct Mco<'d, T: McoInstance> { impl<'d, T: McoInstance> Mco<'d, T> { /// Create a new MCO instance. - /// - /// `prescaler` must be between 1 and 15 for implementations not using Presel enum. pub fn new( _peri: impl Peripheral

+ 'd, pin: impl Peripheral

> + 'd, source: T::Source, - prescaler: T::Prescaler, + #[cfg(not(stm32f1))] prescaler: McoPrescaler, ) -> Self { into_ref!(pin); - #[cfg(not(stm32wl))] - assert!( - 1 <= prescaler && prescaler <= 15, - "Mco prescaler must be between 1 and 15. Refer to the reference manual for more information." - ); - critical_section::with(|_| unsafe { - T::apply_clock_settings(source, prescaler); + T::apply_clock_settings( + source, + #[cfg(not(stm32f1))] + prescaler, + ); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); pin.set_speed(Speed::VeryHigh); }); diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index f7e3ecdb..a3299089 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -7,9 +7,7 @@ use crate::time::Hertz; pub(crate) mod bd; mod bus; -#[cfg(any(stm32h5, stm32h7, stm32wl))] mod mco; -#[cfg(any(stm32h5, stm32h7, stm32wl))] pub use mco::*; #[cfg_attr(rcc_f0, path = "f0.rs")] diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs index 2b9ceebc..5144a78c 100644 --- a/examples/stm32f4/src/bin/mco.rs +++ b/examples/stm32f4/src/bin/mco.rs @@ -5,7 +5,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; -use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoClock}; +use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,8 +14,8 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::DIV1); - let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::Pll, McoClock::DIV4); + let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1); + let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4); let mut led = Output::new(p.PB7, Level::High, Speed::Low); loop { diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index de8ddc29..0ea8b449 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -6,7 +6,7 @@ use embassy_executor::Spawner; use embassy_stm32::dcmi::{self, *}; use embassy_stm32::gpio::{Level, Output, Speed}; use embassy_stm32::i2c::I2c; -use embassy_stm32::rcc::{Mco, Mco1Source}; +use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; use embassy_stm32::time::khz; use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; use embassy_time::{Duration, Timer}; @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); defmt::info!("Hello World!"); - let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 3); + let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); let mut led = Output::new(p.PE3, Level::High, Speed::Low); let cam_i2c = I2c::new( diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs index 9d6d805a..de89aee2 100644 --- a/examples/stm32h7/src/bin/mco.rs +++ b/examples/stm32h7/src/bin/mco.rs @@ -5,7 +5,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; -use embassy_stm32::rcc::{Mco, Mco1Source}; +use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let mut led = Output::new(p.PB14, Level::High, Speed::Low); - let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 8); + let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); loop { info!("high"); diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs index dea0c66e..8d35af78 100644 --- a/examples/stm32l4/src/bin/mco.rs +++ b/examples/stm32l4/src/bin/mco.rs @@ -5,7 +5,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; -use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; +use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let _mco = Mco::new(p.MCO, p.PA8, Mco1Source::Hsi16, McoClock::DIV1); + let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI16, McoPrescaler::DIV1); let mut led = Output::new(p.PB14, Level::High, Speed::Low);