diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-06 23:31:32 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-06 23:31:32 +0000 |
| commit | 7a2b8481f7f574947e346b51ed3fe938f3a0fb58 (patch) | |
| tree | a466956f72979861a52fdcf1377caf6e36b49958 | |
| parent | f30fc949ff34683bd9b9330d09583da4a35428ea (diff) | |
| parent | 3a8e0d4a279f750e82689ce362c898f66cc81486 (diff) | |
Merge pull request #2021 from embassy-rs/stm32-mco
stm32: add MCO for all chips
| -rw-r--r-- | embassy-stm32/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-stm32/build.rs | 35 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f4.rs | 166 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l4.rs | 132 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mco.rs | 46 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/mco.rs | 6 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/camera.rs | 4 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/mco.rs | 4 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/mco.rs | 4 |
10 files changed, 52 insertions, 351 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 5258e4c7c..20c5155ae 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -59,7 +59,7 @@ sdio-host = "0.5.0" | |||
| 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } | 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } |
| 60 | critical-section = "1.1" | 60 | critical-section = "1.1" |
| 61 | atomic-polyfill = "1.0.1" | 61 | atomic-polyfill = "1.0.1" |
| 62 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594" } | 62 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365" } |
| 63 | vcell = "0.1.3" | 63 | vcell = "0.1.3" |
| 64 | bxcan = "0.7.0" | 64 | bxcan = "0.7.0" |
| 65 | nb = "1.0.0" | 65 | nb = "1.0.0" |
| @@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] } | |||
| 78 | [build-dependencies] | 78 | [build-dependencies] |
| 79 | proc-macro2 = "1.0.36" | 79 | proc-macro2 = "1.0.36" |
| 80 | quote = "1.0.15" | 80 | quote = "1.0.15" |
| 81 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594", default-features = false, features = ["metadata"]} | 81 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365", default-features = false, features = ["metadata"]} |
| 82 | 82 | ||
| 83 | 83 | ||
| 84 | [features] | 84 | [features] |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index f825dbeeb..3f85d9e61 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -50,12 +50,14 @@ fn main() { | |||
| 50 | // We *shouldn't* have singletons for these, but the HAL currently requires | 50 | // We *shouldn't* have singletons for these, but the HAL currently requires |
| 51 | // singletons, for using with RccPeripheral to enable/disable clocks to them. | 51 | // singletons, for using with RccPeripheral to enable/disable clocks to them. |
| 52 | "rcc" => { | 52 | "rcc" => { |
| 53 | if r.version.starts_with("h5") || r.version.starts_with("h7") || r.version.starts_with("f4") { | 53 | for pin in p.pins { |
| 54 | singletons.push("MCO1".to_string()); | 54 | if pin.signal.starts_with("MCO") { |
| 55 | singletons.push("MCO2".to_string()); | 55 | let name = pin.signal.replace('_', "").to_string(); |
| 56 | } | 56 | if !singletons.contains(&name) { |
| 57 | if r.version.starts_with("l4") { | 57 | println!("cargo:rustc-cfg={}", name.to_ascii_lowercase()); |
| 58 | singletons.push("MCO".to_string()); | 58 | singletons.push(name); |
| 59 | } | ||
| 60 | } | ||
| 59 | } | 61 | } |
| 60 | singletons.push(p.name.to_string()); | 62 | singletons.push(p.name.to_string()); |
| 61 | } | 63 | } |
| @@ -751,25 +753,8 @@ fn main() { | |||
| 751 | let af = pin.af.unwrap_or(0); | 753 | let af = pin.af.unwrap_or(0); |
| 752 | 754 | ||
| 753 | // MCO is special | 755 | // MCO is special |
| 754 | if pin.signal.starts_with("MCO_") { | 756 | if pin.signal.starts_with("MCO") { |
| 755 | // Supported in H7 only for now | 757 | peri = format_ident!("{}", pin.signal.replace('_', "")); |
| 756 | if regs.version.starts_with("h5") | ||
| 757 | || regs.version.starts_with("h7") | ||
| 758 | || regs.version.starts_with("f4") | ||
| 759 | { | ||
| 760 | peri = format_ident!("{}", pin.signal.replace('_', "")); | ||
| 761 | } else { | ||
| 762 | continue; | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | if pin.signal == "MCO" { | ||
| 767 | // Supported in H7 only for now | ||
| 768 | if regs.version.starts_with("l4") { | ||
| 769 | peri = format_ident!("MCO"); | ||
| 770 | } else { | ||
| 771 | continue; | ||
| 772 | } | ||
| 773 | } | 758 | } |
| 774 | 759 | ||
| 775 | g.extend(quote! { | 760 | g.extend(quote! { |
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 5ba958a02..ad106ce38 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs | |||
| @@ -1,16 +1,8 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 3 | use embassy_hal_internal::into_ref; | ||
| 4 | use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre}; | ||
| 5 | |||
| 6 | use crate::gpio::sealed::AFType; | ||
| 7 | use crate::gpio::Speed; | ||
| 8 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; | 1 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; |
| 9 | use crate::pac::{FLASH, PWR, RCC}; | 2 | use crate::pac::{FLASH, PWR, RCC}; |
| 10 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 3 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 11 | use crate::rcc::{set_freqs, Clocks}; | 4 | use crate::rcc::{set_freqs, Clocks}; |
| 12 | use crate::time::Hertz; | 5 | use crate::time::Hertz; |
| 13 | use crate::{peripherals, Peripheral}; | ||
| 14 | 6 | ||
| 15 | /// HSI speed | 7 | /// HSI speed |
| 16 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); | 8 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); |
| @@ -197,164 +189,6 @@ fn setup_pll( | |||
| 197 | } | 189 | } |
| 198 | } | 190 | } |
| 199 | 191 | ||
| 200 | pub enum McoClock { | ||
| 201 | DIV1, | ||
| 202 | DIV2, | ||
| 203 | DIV3, | ||
| 204 | DIV4, | ||
| 205 | DIV5, | ||
| 206 | } | ||
| 207 | |||
| 208 | impl McoClock { | ||
| 209 | fn into_raw(&self) -> Mcopre { | ||
| 210 | match self { | ||
| 211 | McoClock::DIV1 => Mcopre::DIV1, | ||
| 212 | McoClock::DIV2 => Mcopre::DIV2, | ||
| 213 | McoClock::DIV3 => Mcopre::DIV3, | ||
| 214 | McoClock::DIV4 => Mcopre::DIV4, | ||
| 215 | McoClock::DIV5 => Mcopre::DIV5, | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | #[derive(Copy, Clone)] | ||
| 221 | pub enum Mco1Source { | ||
| 222 | Hsi, | ||
| 223 | Lse, | ||
| 224 | Hse, | ||
| 225 | Pll, | ||
| 226 | } | ||
| 227 | |||
| 228 | impl Default for Mco1Source { | ||
| 229 | fn default() -> Self { | ||
| 230 | Self::Hsi | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | pub trait McoSource { | ||
| 235 | type Raw; | ||
| 236 | |||
| 237 | fn into_raw(&self) -> Self::Raw; | ||
| 238 | } | ||
| 239 | |||
| 240 | impl McoSource for Mco1Source { | ||
| 241 | type Raw = Mco1; | ||
| 242 | fn into_raw(&self) -> Self::Raw { | ||
| 243 | match self { | ||
| 244 | Mco1Source::Hsi => Mco1::HSI, | ||
| 245 | Mco1Source::Lse => Mco1::LSE, | ||
| 246 | Mco1Source::Hse => Mco1::HSE, | ||
| 247 | Mco1Source::Pll => Mco1::PLL, | ||
| 248 | } | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | #[derive(Copy, Clone)] | ||
| 253 | pub enum Mco2Source { | ||
| 254 | SysClk, | ||
| 255 | Plli2s, | ||
| 256 | Hse, | ||
| 257 | Pll, | ||
| 258 | } | ||
| 259 | |||
| 260 | impl Default for Mco2Source { | ||
| 261 | fn default() -> Self { | ||
| 262 | Self::SysClk | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | impl McoSource for Mco2Source { | ||
| 267 | type Raw = Mco2; | ||
| 268 | fn into_raw(&self) -> Self::Raw { | ||
| 269 | match self { | ||
| 270 | Mco2Source::SysClk => Mco2::SYSCLK, | ||
| 271 | Mco2Source::Plli2s => Mco2::PLLI2S, | ||
| 272 | Mco2Source::Hse => Mco2::HSE, | ||
| 273 | Mco2Source::Pll => Mco2::PLL, | ||
| 274 | } | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | pub(crate) mod sealed { | ||
| 279 | use stm32_metapac::rcc::vals::Mcopre; | ||
| 280 | pub trait McoInstance { | ||
| 281 | type Source; | ||
| 282 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre); | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | pub trait McoInstance: sealed::McoInstance + 'static {} | ||
| 287 | |||
| 288 | pin_trait!(McoPin, McoInstance); | ||
| 289 | |||
| 290 | impl sealed::McoInstance for peripherals::MCO1 { | ||
| 291 | type Source = Mco1; | ||
| 292 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { | ||
| 293 | RCC.cfgr().modify(|w| { | ||
| 294 | w.set_mco1(source); | ||
| 295 | w.set_mco1pre(prescaler); | ||
| 296 | }); | ||
| 297 | match source { | ||
| 298 | Mco1::PLL => { | ||
| 299 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 300 | while !RCC.cr().read().pllrdy() {} | ||
| 301 | } | ||
| 302 | Mco1::HSI => { | ||
| 303 | RCC.cr().modify(|w| w.set_hsion(true)); | ||
| 304 | while !RCC.cr().read().hsirdy() {} | ||
| 305 | } | ||
| 306 | _ => {} | ||
| 307 | } | ||
| 308 | } | ||
| 309 | } | ||
| 310 | impl McoInstance for peripherals::MCO1 {} | ||
| 311 | |||
| 312 | impl sealed::McoInstance for peripherals::MCO2 { | ||
| 313 | type Source = Mco2; | ||
| 314 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { | ||
| 315 | RCC.cfgr().modify(|w| { | ||
| 316 | w.set_mco2(source); | ||
| 317 | w.set_mco2pre(prescaler); | ||
| 318 | }); | ||
| 319 | match source { | ||
| 320 | Mco2::PLL => { | ||
| 321 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 322 | while !RCC.cr().read().pllrdy() {} | ||
| 323 | } | ||
| 324 | #[cfg(not(stm32f410))] | ||
| 325 | Mco2::PLLI2S => { | ||
| 326 | RCC.cr().modify(|w| w.set_plli2son(true)); | ||
| 327 | while !RCC.cr().read().plli2srdy() {} | ||
| 328 | } | ||
| 329 | _ => {} | ||
| 330 | } | ||
| 331 | } | ||
| 332 | } | ||
| 333 | impl McoInstance for peripherals::MCO2 {} | ||
| 334 | |||
| 335 | pub struct Mco<'d, T: McoInstance> { | ||
| 336 | phantom: PhantomData<&'d mut T>, | ||
| 337 | } | ||
| 338 | |||
| 339 | impl<'d, T: McoInstance> Mco<'d, T> { | ||
| 340 | pub fn new( | ||
| 341 | _peri: impl Peripheral<P = T> + 'd, | ||
| 342 | pin: impl Peripheral<P = impl McoPin<T>> + 'd, | ||
| 343 | source: impl McoSource<Raw = T::Source>, | ||
| 344 | prescaler: McoClock, | ||
| 345 | ) -> Self { | ||
| 346 | into_ref!(pin); | ||
| 347 | |||
| 348 | critical_section::with(|_| unsafe { | ||
| 349 | T::apply_clock_settings(source.into_raw(), prescaler.into_raw()); | ||
| 350 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | ||
| 351 | pin.set_speed(Speed::VeryHigh); | ||
| 352 | }); | ||
| 353 | |||
| 354 | Self { phantom: PhantomData } | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | fn flash_setup(sysclk: u32) { | 192 | fn flash_setup(sysclk: u32) { |
| 359 | use crate::pac::flash::vals::Latency; | 193 | use crate::pac::flash::vals::Latency; |
| 360 | 194 | ||
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 3a24eca82..2fbb9920e 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs | |||
| @@ -1,18 +1,11 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 3 | use embassy_hal_internal::into_ref; | ||
| 4 | use stm32_metapac::rcc::regs::Cfgr; | 1 | use stm32_metapac::rcc::regs::Cfgr; |
| 5 | use stm32_metapac::rcc::vals::{Mcopre, Mcosel}; | ||
| 6 | 2 | ||
| 7 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 3 | pub use super::bus::{AHBPrescaler, APBPrescaler}; |
| 8 | use crate::gpio::sealed::AFType; | ||
| 9 | use crate::gpio::Speed; | ||
| 10 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; | 4 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; |
| 11 | use crate::pac::{FLASH, RCC}; | 5 | use crate::pac::{FLASH, RCC}; |
| 12 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 6 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 13 | use crate::rcc::{set_freqs, Clocks}; | 7 | use crate::rcc::{set_freqs, Clocks}; |
| 14 | use crate::time::Hertz; | 8 | use crate::time::Hertz; |
| 15 | use crate::{peripherals, Peripheral}; | ||
| 16 | 9 | ||
| 17 | /// HSI speed | 10 | /// HSI speed |
| 18 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); | 11 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); |
| @@ -263,131 +256,6 @@ impl Default for Config { | |||
| 263 | } | 256 | } |
| 264 | } | 257 | } |
| 265 | 258 | ||
| 266 | pub enum McoClock { | ||
| 267 | DIV1, | ||
| 268 | DIV2, | ||
| 269 | DIV4, | ||
| 270 | DIV8, | ||
| 271 | DIV16, | ||
| 272 | } | ||
| 273 | |||
| 274 | impl McoClock { | ||
| 275 | fn into_raw(&self) -> Mcopre { | ||
| 276 | match self { | ||
| 277 | McoClock::DIV1 => Mcopre::DIV1, | ||
| 278 | McoClock::DIV2 => Mcopre::DIV2, | ||
| 279 | McoClock::DIV4 => Mcopre::DIV4, | ||
| 280 | McoClock::DIV8 => Mcopre::DIV8, | ||
| 281 | McoClock::DIV16 => Mcopre::DIV16, | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | #[derive(Copy, Clone)] | ||
| 287 | pub enum Mco1Source { | ||
| 288 | Disabled, | ||
| 289 | Lse, | ||
| 290 | Lsi, | ||
| 291 | Hse, | ||
| 292 | Hsi16, | ||
| 293 | PllClk, | ||
| 294 | SysClk, | ||
| 295 | Msi, | ||
| 296 | #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||
| 297 | Hsi48, | ||
| 298 | } | ||
| 299 | |||
| 300 | impl Default for Mco1Source { | ||
| 301 | fn default() -> Self { | ||
| 302 | Self::Hsi16 | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | pub trait McoSource { | ||
| 307 | type Raw; | ||
| 308 | |||
| 309 | fn into_raw(&self) -> Self::Raw; | ||
| 310 | } | ||
| 311 | |||
| 312 | impl McoSource for Mco1Source { | ||
| 313 | type Raw = Mcosel; | ||
| 314 | fn into_raw(&self) -> Self::Raw { | ||
| 315 | match self { | ||
| 316 | Mco1Source::Disabled => Mcosel::NOCLOCK, | ||
| 317 | Mco1Source::Lse => Mcosel::LSE, | ||
| 318 | Mco1Source::Lsi => Mcosel::LSI, | ||
| 319 | Mco1Source::Hse => Mcosel::HSE, | ||
| 320 | Mco1Source::Hsi16 => Mcosel::HSI16, | ||
| 321 | Mco1Source::PllClk => Mcosel::PLL, | ||
| 322 | Mco1Source::SysClk => Mcosel::SYSCLK, | ||
| 323 | Mco1Source::Msi => Mcosel::MSI, | ||
| 324 | #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||
| 325 | Mco1Source::Hsi48 => Mcosel::HSI48, | ||
| 326 | } | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | pub(crate) mod sealed { | ||
| 331 | use stm32_metapac::rcc::vals::Mcopre; | ||
| 332 | pub trait McoInstance { | ||
| 333 | type Source; | ||
| 334 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | pub trait McoInstance: sealed::McoInstance + 'static {} | ||
| 339 | |||
| 340 | pin_trait!(McoPin, McoInstance); | ||
| 341 | |||
| 342 | impl sealed::McoInstance for peripherals::MCO { | ||
| 343 | type Source = Mcosel; | ||
| 344 | |||
| 345 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) { | ||
| 346 | RCC.cfgr().modify(|w| { | ||
| 347 | w.set_mcosel(source); | ||
| 348 | w.set_mcopre(prescaler); | ||
| 349 | }); | ||
| 350 | |||
| 351 | match source { | ||
| 352 | Mcosel::HSI16 => { | ||
| 353 | RCC.cr().modify(|w| w.set_hsion(true)); | ||
| 354 | while !RCC.cr().read().hsirdy() {} | ||
| 355 | } | ||
| 356 | #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | ||
| 357 | Mcosel::HSI48 => { | ||
| 358 | RCC.crrcr().modify(|w| w.set_hsi48on(true)); | ||
| 359 | while !RCC.crrcr().read().hsi48rdy() {} | ||
| 360 | } | ||
| 361 | _ => {} | ||
| 362 | } | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | impl McoInstance for peripherals::MCO {} | ||
| 367 | |||
| 368 | pub struct Mco<'d, T: McoInstance> { | ||
| 369 | phantom: PhantomData<&'d mut T>, | ||
| 370 | } | ||
| 371 | |||
| 372 | impl<'d, T: McoInstance> Mco<'d, T> { | ||
| 373 | pub fn new( | ||
| 374 | _peri: impl Peripheral<P = T> + 'd, | ||
| 375 | pin: impl Peripheral<P = impl McoPin<T>> + 'd, | ||
| 376 | source: impl McoSource<Raw = T::Source>, | ||
| 377 | prescaler: McoClock, | ||
| 378 | ) -> Self { | ||
| 379 | into_ref!(pin); | ||
| 380 | |||
| 381 | critical_section::with(|_| unsafe { | ||
| 382 | T::apply_clock_settings(source.into_raw(), prescaler.into_raw()); | ||
| 383 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | ||
| 384 | pin.set_speed(Speed::VeryHigh); | ||
| 385 | }); | ||
| 386 | |||
| 387 | Self { phantom: PhantomData } | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | pub(crate) unsafe fn init(config: Config) { | 259 | pub(crate) unsafe fn init(config: Config) { |
| 392 | // Switch to MSI to prevent problems with PLL configuration. | 260 | // Switch to MSI to prevent problems with PLL configuration. |
| 393 | if !RCC.cr().read().msion() { | 261 | if !RCC.cr().read().msion() { |
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 2453ed821..eaaf8071c 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs | |||
| @@ -4,14 +4,19 @@ use embassy_hal_internal::into_ref; | |||
| 4 | 4 | ||
| 5 | use crate::gpio::sealed::AFType; | 5 | use crate::gpio::sealed::AFType; |
| 6 | use crate::gpio::Speed; | 6 | use crate::gpio::Speed; |
| 7 | pub use crate::pac::rcc::vals::{Mco1 as Mco1Source, Mco2 as Mco2Source}; | 7 | #[cfg(not(stm32f1))] |
| 8 | pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; | ||
| 9 | #[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] | ||
| 10 | pub use crate::pac::rcc::vals::Mcosel as McoSource; | ||
| 11 | #[cfg(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7))] | ||
| 12 | pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source}; | ||
| 8 | use crate::pac::RCC; | 13 | use crate::pac::RCC; |
| 9 | use crate::{peripherals, Peripheral}; | 14 | use crate::{peripherals, Peripheral}; |
| 10 | 15 | ||
| 11 | pub(crate) mod sealed { | 16 | pub(crate) mod sealed { |
| 12 | pub trait McoInstance { | 17 | pub trait McoInstance { |
| 13 | type Source; | 18 | type Source; |
| 14 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8); | 19 | unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler); |
| 15 | } | 20 | } |
| 16 | } | 21 | } |
| 17 | 22 | ||
| @@ -24,9 +29,15 @@ macro_rules! impl_peri { | |||
| 24 | impl sealed::McoInstance for peripherals::$peri { | 29 | impl sealed::McoInstance for peripherals::$peri { |
| 25 | type Source = $source; | 30 | type Source = $source; |
| 26 | 31 | ||
| 27 | unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) { | 32 | unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) { |
| 28 | RCC.cfgr().modify(|w| { | 33 | #[cfg(not(any(stm32u5, stm32wba)))] |
| 34 | let r = RCC.cfgr(); | ||
| 35 | #[cfg(any(stm32u5, stm32wba))] | ||
| 36 | let r = RCC.cfgr1(); | ||
| 37 | |||
| 38 | r.modify(|w| { | ||
| 29 | w.$set_source(source); | 39 | w.$set_source(source); |
| 40 | #[cfg(not(stm32f1))] | ||
| 30 | w.$set_prescaler(prescaler); | 41 | w.$set_prescaler(prescaler); |
| 31 | }); | 42 | }); |
| 32 | } | 43 | } |
| @@ -36,8 +47,16 @@ macro_rules! impl_peri { | |||
| 36 | }; | 47 | }; |
| 37 | } | 48 | } |
| 38 | 49 | ||
| 39 | impl_peri!(MCO1, Mco1Source, set_mco1, set_mco1pre); | 50 | #[cfg(any(rcc_c0, rcc_g0))] |
| 40 | impl_peri!(MCO2, Mco2Source, set_mco2, set_mco2pre); | 51 | #[allow(unused_imports)] |
| 52 | use self::{McoSource as Mco1Source, McoSource as Mco2Source}; | ||
| 53 | |||
| 54 | #[cfg(mco)] | ||
| 55 | impl_peri!(MCO, McoSource, set_mcosel, set_mcopre); | ||
| 56 | #[cfg(mco1)] | ||
| 57 | impl_peri!(MCO1, Mco1Source, set_mco1sel, set_mco1pre); | ||
| 58 | #[cfg(mco2)] | ||
| 59 | impl_peri!(MCO2, Mco2Source, set_mco2sel, set_mco2pre); | ||
| 41 | 60 | ||
| 42 | pub struct Mco<'d, T: McoInstance> { | 61 | pub struct Mco<'d, T: McoInstance> { |
| 43 | phantom: PhantomData<&'d mut T>, | 62 | phantom: PhantomData<&'d mut T>, |
| @@ -45,23 +64,20 @@ pub struct Mco<'d, T: McoInstance> { | |||
| 45 | 64 | ||
| 46 | impl<'d, T: McoInstance> Mco<'d, T> { | 65 | impl<'d, T: McoInstance> Mco<'d, T> { |
| 47 | /// Create a new MCO instance. | 66 | /// Create a new MCO instance. |
| 48 | /// | ||
| 49 | /// `prescaler` must be between 1 and 15. | ||
| 50 | pub fn new( | 67 | pub fn new( |
| 51 | _peri: impl Peripheral<P = T> + 'd, | 68 | _peri: impl Peripheral<P = T> + 'd, |
| 52 | pin: impl Peripheral<P = impl McoPin<T>> + 'd, | 69 | pin: impl Peripheral<P = impl McoPin<T>> + 'd, |
| 53 | source: T::Source, | 70 | source: T::Source, |
| 54 | prescaler: u8, | 71 | #[cfg(not(stm32f1))] prescaler: McoPrescaler, |
| 55 | ) -> Self { | 72 | ) -> Self { |
| 56 | into_ref!(pin); | 73 | into_ref!(pin); |
| 57 | 74 | ||
| 58 | assert!( | ||
| 59 | 1 <= prescaler && prescaler <= 15, | ||
| 60 | "Mco prescaler must be between 1 and 15. Refer to the reference manual for more information." | ||
| 61 | ); | ||
| 62 | |||
| 63 | critical_section::with(|_| unsafe { | 75 | critical_section::with(|_| unsafe { |
| 64 | T::apply_clock_settings(source, prescaler); | 76 | T::apply_clock_settings( |
| 77 | source, | ||
| 78 | #[cfg(not(stm32f1))] | ||
| 79 | prescaler, | ||
| 80 | ); | ||
| 65 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); | 81 | pin.set_as_af(pin.af_num(), AFType::OutputPushPull); |
| 66 | pin.set_speed(Speed::VeryHigh); | 82 | pin.set_speed(Speed::VeryHigh); |
| 67 | }); | 83 | }); |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index bf497ca12..a32990890 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -7,9 +7,7 @@ use crate::time::Hertz; | |||
| 7 | 7 | ||
| 8 | pub(crate) mod bd; | 8 | pub(crate) mod bd; |
| 9 | mod bus; | 9 | mod bus; |
| 10 | #[cfg(any(stm32h5, stm32h7))] | ||
| 11 | mod mco; | 10 | mod mco; |
| 12 | #[cfg(any(stm32h5, stm32h7))] | ||
| 13 | pub use mco::*; | 11 | pub use mco::*; |
| 14 | 12 | ||
| 15 | #[cfg_attr(rcc_f0, path = "f0.rs")] | 13 | #[cfg_attr(rcc_f0, path = "f0.rs")] |
diff --git a/examples/stm32f4/src/bin/mco.rs b/examples/stm32f4/src/bin/mco.rs index 2b9ceebc3..5144a78c6 100644 --- a/examples/stm32f4/src/bin/mco.rs +++ b/examples/stm32f4/src/bin/mco.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoClock}; | 8 | use embassy_stm32::rcc::{Mco, Mco1Source, Mco2Source, McoPrescaler}; |
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -14,8 +14,8 @@ async fn main(_spawner: Spawner) { | |||
| 14 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 15 | info!("Hello World!"); | 15 | info!("Hello World!"); |
| 16 | 16 | ||
| 17 | let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::Hsi, McoClock::DIV1); | 17 | let _mco1 = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV1); |
| 18 | let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::Pll, McoClock::DIV4); | 18 | let _mco2 = Mco::new(p.MCO2, p.PC9, Mco2Source::PLL, McoPrescaler::DIV4); |
| 19 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); | 19 | let mut led = Output::new(p.PB7, Level::High, Speed::Low); |
| 20 | 20 | ||
| 21 | loop { | 21 | loop { |
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index de8ddc292..0ea8b4498 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs | |||
| @@ -6,7 +6,7 @@ use embassy_executor::Spawner; | |||
| 6 | use embassy_stm32::dcmi::{self, *}; | 6 | use embassy_stm32::dcmi::{self, *}; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::i2c::I2c; | 8 | use embassy_stm32::i2c::I2c; |
| 9 | use embassy_stm32::rcc::{Mco, Mco1Source}; | 9 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; |
| 10 | use embassy_stm32::time::khz; | 10 | use embassy_stm32::time::khz; |
| 11 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; | 11 | use embassy_stm32::{bind_interrupts, i2c, peripherals, Config}; |
| 12 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { | |||
| 49 | let p = embassy_stm32::init(config); | 49 | let p = embassy_stm32::init(config); |
| 50 | 50 | ||
| 51 | defmt::info!("Hello World!"); | 51 | defmt::info!("Hello World!"); |
| 52 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 3); | 52 | let mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV3); |
| 53 | 53 | ||
| 54 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); | 54 | let mut led = Output::new(p.PE3, Level::High, Speed::Low); |
| 55 | let cam_i2c = I2c::new( | 55 | let cam_i2c = I2c::new( |
diff --git a/examples/stm32h7/src/bin/mco.rs b/examples/stm32h7/src/bin/mco.rs index 9d6d805ae..de89aee2f 100644 --- a/examples/stm32h7/src/bin/mco.rs +++ b/examples/stm32h7/src/bin/mco.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::rcc::{Mco, Mco1Source}; | 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoPrescaler}; |
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | 16 | ||
| 17 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | 17 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); |
| 18 | 18 | ||
| 19 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, 8); | 19 | let _mco = Mco::new(p.MCO1, p.PA8, Mco1Source::HSI, McoPrescaler::DIV8); |
| 20 | 20 | ||
| 21 | loop { | 21 | loop { |
| 22 | info!("high"); | 22 | info!("high"); |
diff --git a/examples/stm32l4/src/bin/mco.rs b/examples/stm32l4/src/bin/mco.rs index dea0c66e0..8d35af781 100644 --- a/examples/stm32l4/src/bin/mco.rs +++ b/examples/stm32l4/src/bin/mco.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 7 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::rcc::{Mco, Mco1Source, McoClock}; | 8 | use embassy_stm32::rcc::{Mco, McoPrescaler, McoSource}; |
| 9 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { | |||
| 14 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 15 | info!("Hello World!"); | 15 | info!("Hello World!"); |
| 16 | 16 | ||
| 17 | let _mco = Mco::new(p.MCO, p.PA8, Mco1Source::Hsi16, McoClock::DIV1); | 17 | let _mco = Mco::new(p.MCO, p.PA8, McoSource::HSI16, McoPrescaler::DIV1); |
| 18 | 18 | ||
| 19 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); | 19 | let mut led = Output::new(p.PB14, Level::High, Speed::Low); |
| 20 | 20 | ||
