diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index dae7419c..c201405e 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -15,7 +15,6 @@ embassy-time = { version = "0.1.3", path = "../embassy-time"} embassy-sync = { version = "0.3.0", path = "../embassy-sync"} embassy-futures = { version = "0.1.0", path = "../embassy-futures"} embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel"} -atomic-polyfill = "0.1.5" defmt = { version = "0.3", optional = true } log = { version = "0.4.17", optional = true } diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index c2fffba8..a3c18046 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -64,4 +64,3 @@ stable_deref_trait = { version = "1.2.0", default-features = false } futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } atomic-pool = "1.0" embedded-nal-async = { version = "0.6.0", optional = true } -atomic-polyfill = { version = "1.0" } diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index a12fd382..b5615cb6 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs @@ -579,11 +579,10 @@ mod embedded_io_impls { /// TCP client compatible with `embedded-nal-async` traits. #[cfg(feature = "nightly")] pub mod client { - use core::cell::UnsafeCell; + use core::cell::{Cell, UnsafeCell}; use core::mem::MaybeUninit; use core::ptr::NonNull; - use atomic_polyfill::{AtomicBool, Ordering}; use embedded_nal_async::IpAddr; use super::*; @@ -702,15 +701,13 @@ pub mod client { } } - unsafe impl Sync for TcpClientState {} - struct Pool { - used: [AtomicBool; N], + used: [Cell; N], data: [UnsafeCell>; N], } impl Pool { - const VALUE: AtomicBool = AtomicBool::new(false); + const VALUE: Cell = Cell::new(false); const UNINIT: UnsafeCell> = UnsafeCell::new(MaybeUninit::uninit()); const fn new() -> Self { @@ -724,7 +721,9 @@ pub mod client { impl Pool { fn alloc(&self) -> Option> { for n in 0..N { - if self.used[n].swap(true, Ordering::SeqCst) == false { + // this can't race because Pool is not Sync. + if !self.used[n].get() { + self.used[n].set(true); let p = self.data[n].get() as *mut T; return Some(unsafe { NonNull::new_unchecked(p) }); } @@ -738,7 +737,7 @@ pub mod client { let n = p.as_ptr().offset_from(origin); assert!(n >= 0); assert!((n as usize) < N); - self.used[n as usize].store(false, Ordering::SeqCst); + self.used[n as usize].set(false); } } } diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 77777ad3..4fe4b27e 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -6,7 +6,6 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::i2c; -use crate::gpio::sealed::Pin; use crate::gpio::AnyPin; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::{interrupt, pac, peripherals, Peripheral}; @@ -295,13 +294,24 @@ impl<'d, T: Instance> I2c<'d, T, Async> { pub async fn read_async(&mut self, addr: u16, buffer: &mut [u8]) -> Result<(), Error> { Self::setup(addr)?; - self.read_async_internal(buffer, false, true).await + self.read_async_internal(buffer, true, true).await } pub async fn write_async(&mut self, addr: u16, bytes: impl IntoIterator) -> Result<(), Error> { Self::setup(addr)?; self.write_async_internal(bytes, true).await } + + pub async fn write_read_async( + &mut self, + addr: u16, + bytes: impl IntoIterator, + buffer: &mut [u8], + ) -> Result<(), Error> { + Self::setup(addr)?; + self.write_async_internal(bytes, false).await?; + self.read_async_internal(buffer, true, true).await + } } pub struct InterruptHandler { @@ -318,6 +328,22 @@ impl interrupt::typelevel::Handler for InterruptHandl } } +pub(crate) fn set_up_i2c_pin<'d, P, T>(pin: &P) +where + P: core::ops::Deref, + T: crate::gpio::Pin, +{ + pin.gpio().ctrl().write(|w| w.set_funcsel(3)); + pin.pad_ctrl().write(|w| { + w.set_schmitt(true); + w.set_slewfast(false); + w.set_ie(true); + w.set_od(false); + w.set_pue(true); + w.set_pde(false); + }); +} + impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { fn new_inner( _peri: impl Peripheral

+ 'd, @@ -355,23 +381,8 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { p.ic_rx_tl().write(|w| w.set_rx_tl(0)); // Configure SCL & SDA pins - scl.gpio().ctrl().write(|w| w.set_funcsel(3)); - sda.gpio().ctrl().write(|w| w.set_funcsel(3)); - - scl.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); - sda.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); + set_up_i2c_pin(&scl); + set_up_i2c_pin(&sda); // Configure baudrate @@ -713,7 +724,7 @@ mod nightly { Self::setup(addr)?; self.write_async_internal(write.iter().cloned(), false).await?; - self.read_async_internal(read, false, true).await + self.read_async_internal(read, true, true).await } async fn transaction(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index 30e78925..9271ede3 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -5,7 +5,9 @@ use core::task::Poll; use embassy_hal_internal::into_ref; use pac::i2c; -use crate::i2c::{i2c_reserved_addr, AbortReason, Instance, InterruptHandler, SclPin, SdaPin, FIFO_SIZE}; +use crate::i2c::{ + i2c_reserved_addr, set_up_i2c_pin, AbortReason, Instance, InterruptHandler, SclPin, SdaPin, FIFO_SIZE, +}; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::{pac, Peripheral}; @@ -100,23 +102,8 @@ impl<'d, T: Instance> I2cSlave<'d, T> { p.ic_rx_tl().write(|w| w.set_rx_tl(0)); // Configure SCL & SDA pins - scl.gpio().ctrl().write(|w| w.set_funcsel(3)); - sda.gpio().ctrl().write(|w| w.set_funcsel(3)); - - scl.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); - sda.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); + set_up_i2c_pin(&scl); + set_up_i2c_pin(&sda); // Clear interrupts p.ic_clr_intr().read(); diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 70e8f2e2..a2c5da2b 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,8 +58,7 @@ rand_core = "0.6.3" 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-e89b8cfc30e480036aaf502f34c874ee42d68026" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -77,7 +76,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-e89b8cfc30e480036aaf502f34c874ee42d68026", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-6bfa5a0dcec6a9bd42cea94ba11eeae1a17a7f2c", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 223e93ff..5b6b22ea 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -9,6 +9,32 @@ use stm32_metapac::metadata::ir::{BlockItemInner, Enum}; use stm32_metapac::metadata::{MemoryRegionKind, PeripheralRccRegister, METADATA}; fn main() { + let target = env::var("TARGET").unwrap(); + + if target.starts_with("thumbv6m-") { + println!("cargo:rustc-cfg=cortex_m"); + println!("cargo:rustc-cfg=armv6m"); + } else if target.starts_with("thumbv7m-") { + println!("cargo:rustc-cfg=cortex_m"); + println!("cargo:rustc-cfg=armv7m"); + } else if target.starts_with("thumbv7em-") { + println!("cargo:rustc-cfg=cortex_m"); + println!("cargo:rustc-cfg=armv7m"); + println!("cargo:rustc-cfg=armv7em"); // (not currently used) + } else if target.starts_with("thumbv8m.base") { + println!("cargo:rustc-cfg=cortex_m"); + println!("cargo:rustc-cfg=armv8m"); + println!("cargo:rustc-cfg=armv8m_base"); + } else if target.starts_with("thumbv8m.main") { + println!("cargo:rustc-cfg=cortex_m"); + println!("cargo:rustc-cfg=armv8m"); + println!("cargo:rustc-cfg=armv8m_main"); + } + + if target.ends_with("-eabihf") { + println!("cargo:rustc-cfg=has_fpu"); + } + let chip_name = match env::vars() .map(|(a, _)| a) .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) @@ -531,20 +557,20 @@ fn main() { #clock_frequency } fn enable() { - critical_section::with(|_| { + critical_section::with(|_cs| { #before_enable #[cfg(feature = "low-power")] - crate::rcc::clock_refcount_add(); + crate::rcc::clock_refcount_add(_cs); crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); #after_enable }) } fn disable() { - critical_section::with(|_| { + critical_section::with(|_cs| { #before_disable crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); #[cfg(feature = "low-power")] - crate::rcc::clock_refcount_sub(); + crate::rcc::clock_refcount_sub(_cs); }) } fn reset() { @@ -1007,7 +1033,7 @@ fn main() { match e { "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, "Timpre" | "Pllrclkpre" => false, - e if e.ends_with("pre") || e.ends_with("div") || e.ends_with("mul") => true, + e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, _ => false, } } diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 20ff29be..62eb65b1 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -2,10 +2,9 @@ use core::future::Future; use core::pin::Pin; -use core::sync::atomic::{fence, Ordering}; +use core::sync::atomic::{fence, AtomicUsize, Ordering}; use core::task::{Context, Poll, Waker}; -use atomic_polyfill::AtomicUsize; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; @@ -127,7 +126,13 @@ pub(crate) unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: usize, index } else if isr.tcif(channel_num) && cr.read().tcie() { // Acknowledge transfer complete interrupt dma.ifcr().write(|w| w.set_tcif(channel_num, true)); + #[cfg(not(armv6m))] STATE.complete_count[index].fetch_add(1, Ordering::Release); + #[cfg(armv6m)] + critical_section::with(|_| { + let x = STATE.complete_count[index].load(Ordering::Relaxed); + STATE.complete_count[index].store(x + 1, Ordering::Release); + }) } else { return; } @@ -391,7 +396,14 @@ impl<'a, C: Channel> DmaCtrl for DmaCtrlImpl<'a, C> { } fn reset_complete_count(&mut self) -> usize { - STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel) + #[cfg(not(armv6m))] + return STATE.complete_count[self.0.index()].swap(0, Ordering::AcqRel); + #[cfg(armv6m)] + return critical_section::with(|_| { + let x = STATE.complete_count[self.0.index()].load(Ordering::Acquire); + STATE.complete_count[self.0.index()].store(0, Ordering::Release); + x + }); } fn set_waker(&mut self, waker: &Waker) { diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 2ed46ca2..1e1094a1 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -41,39 +41,40 @@ mod phy_consts { } use self::phy_consts::*; -/// Generic SMI Ethernet PHY +/// Generic SMI Ethernet PHY implementation pub struct GenericSMI { + phy_addr: u8, #[cfg(feature = "time")] poll_interval: Duration, - #[cfg(not(feature = "time"))] - _private: (), } impl GenericSMI { - pub fn new() -> Self { + /// Construct the PHY. It assumes the address `phy_addr` in the SMI communication + pub fn new(phy_addr: u8) -> Self { Self { + phy_addr, #[cfg(feature = "time")] poll_interval: Duration::from_millis(500), - #[cfg(not(feature = "time"))] - _private: (), } } } unsafe impl PHY for GenericSMI { - /// Reset PHY and wait for it to come out of reset. fn phy_reset(&mut self, sm: &mut S) { - sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); - while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} + sm.smi_write(self.phy_addr, PHY_REG_BCR, PHY_REG_BCR_RESET); + while sm.smi_read(self.phy_addr, PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} } - /// PHY initialisation. fn phy_init(&mut self, sm: &mut S) { // Clear WU CSR self.smi_write_ext(sm, PHY_REG_WUCSR, 0); // Enable auto-negotiation - sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); + sm.smi_write( + self.phy_addr, + PHY_REG_BCR, + PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M, + ); } fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool { @@ -83,7 +84,7 @@ unsafe impl PHY for GenericSMI { #[cfg(feature = "time")] let _ = Timer::after(self.poll_interval).poll_unpin(cx); - let bsr = sm.smi_read(PHY_REG_BSR); + let bsr = sm.smi_read(self.phy_addr, PHY_REG_BSR); // No link without autonegotiate if bsr & PHY_REG_BSR_ANDONE == 0 { @@ -108,9 +109,9 @@ impl GenericSMI { // Writes a value to an extended PHY register in MMD address space fn smi_write_ext(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { - sm.smi_write(PHY_REG_CTL, 0x0003); // set address - sm.smi_write(PHY_REG_ADDAR, reg_addr); - sm.smi_write(PHY_REG_CTL, 0x4003); // set data - sm.smi_write(PHY_REG_ADDAR, reg_data); + sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x0003); // set address + sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_addr); + sm.smi_write(self.phy_addr, PHY_REG_CTL, 0x4003); // set data + sm.smi_write(self.phy_addr, PHY_REG_ADDAR, reg_data); } } diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 1e057235..556aadd7 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -134,9 +134,9 @@ impl<'a, 'd> embassy_net_driver::TxToken for TxToken<'a, 'd> { /// The methods cannot move out of self pub unsafe trait StationManagement { /// Read a register over SMI. - fn smi_read(&mut self, reg: u8) -> u16; + fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16; /// Write a register over SMI. - fn smi_write(&mut self, reg: u8, val: u16); + fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16); } /// Traits for an Ethernet PHY diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 4d19103d..631a9377 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -107,7 +107,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { tx_en: impl Peripheral

> + 'd, phy: P, mac_addr: [u8; 6], - phy_addr: u8, ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); @@ -227,7 +226,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { station_management: EthernetStationManagement { peri: PhantomData, clock_range: clock_range, - phy_addr: phy_addr, }, mac_addr, tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), @@ -271,15 +269,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { pub struct EthernetStationManagement { peri: PhantomData, clock_range: Cr, - phy_addr: u8, } unsafe impl StationManagement for EthernetStationManagement { - fn smi_read(&mut self, reg: u8) -> u16 { + fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { let mac = ETH.ethernet_mac(); mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); + w.set_pa(phy_addr); w.set_mr(reg); w.set_mw(Mw::READ); // read operation w.set_cr(self.clock_range); @@ -289,12 +286,12 @@ unsafe impl StationManagement for EthernetStationManagement { mac.macmiidr().read().md() } - fn smi_write(&mut self, reg: u8, val: u16) { + fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { let mac = ETH.ethernet_mac(); mac.macmiidr().write(|w| w.set_md(val)); mac.macmiiar().modify(|w| { - w.set_pa(self.phy_addr); + w.set_pa(phy_addr); w.set_mr(reg); w.set_mw(Mw::WRITE); // write w.set_cr(self.clock_range); diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 6efd40e3..12cf618a 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -71,7 +71,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { tx_en: impl Peripheral

> + 'd, phy: P, mac_addr: [u8; 6], - phy_addr: u8, ) -> Self { into_ref!(peri, ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); @@ -202,7 +201,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { station_management: EthernetStationManagement { peri: PhantomData, clock_range: clock_range, - phy_addr: phy_addr, }, mac_addr, }; @@ -242,15 +240,14 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { pub struct EthernetStationManagement { peri: PhantomData, clock_range: u8, - phy_addr: u8, } unsafe impl StationManagement for EthernetStationManagement { - fn smi_read(&mut self, reg: u8) -> u16 { + fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { let mac = ETH.ethernet_mac(); mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); + w.set_pa(phy_addr); w.set_rda(reg); w.set_goc(0b11); // read w.set_cr(self.clock_range); @@ -260,12 +257,12 @@ unsafe impl StationManagement for EthernetStationManagement { mac.macmdiodr().read().md() } - fn smi_write(&mut self, reg: u8, val: u16) { + fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { let mac = ETH.ethernet_mac(); mac.macmdiodr().write(|w| w.set_md(val)); mac.macmdioar().modify(|w| { - w.set_pa(self.phy_addr); + w.set_pa(phy_addr); w.set_rda(reg); w.set_goc(0b01); // write w.set_cr(self.clock_range); diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index d011522b..1ab8435a 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); + } } pub(crate) unsafe fn enable_blocking_write() { diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 065369f6..7e6d7ca2 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); + } } pub(crate) unsafe fn enable_blocking_write() { diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 913950fe..81deaa17 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -228,8 +228,10 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_key(0x45670123)); - pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_key(0x45670123)); + pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); + } } pub(crate) unsafe fn enable_write() { diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 3a5bdf9c..b52231ca 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -19,8 +19,10 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); + } } pub(crate) unsafe fn enable_blocking_write() { diff --git a/embassy-stm32/src/flash/g0.rs b/embassy-stm32/src/flash/g0.rs index 3a457601..19a38897 100644 --- a/embassy-stm32/src/flash/g0.rs +++ b/embassy-stm32/src/flash/g0.rs @@ -24,8 +24,10 @@ pub(crate) unsafe fn unlock() { while pac::FLASH.sr().read().bsy() {} // Unlock flash - pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + } } pub(crate) unsafe fn enable_blocking_write() { diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 625bf13f..b064fd6e 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -26,11 +26,15 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0x4567_0123)); - pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + if pac::FLASH.bank(0).cr().read().lock() { + pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0x4567_0123)); + pac::FLASH.bank(0).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + } if is_dual_bank() { - pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0x4567_0123)); - pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + if pac::FLASH.bank(1).cr().read().lock() { + pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0x4567_0123)); + pac::FLASH.bank(1).keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + } } } diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index 24dcf99b..1db0da92 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -28,17 +28,23 @@ pub(crate) unsafe fn lock() { pub(crate) unsafe fn unlock() { #[cfg(any(flash_wl, flash_wb, flash_l4))] { - pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + if pac::FLASH.cr().read().lock() { + pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123)); + pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB)); + } } #[cfg(any(flash_l0, flash_l1))] { - pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF)); - pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405)); + if pac::FLASH.pecr().read().pelock() { + pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF)); + pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405)); + } - pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); - pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516)); + if pac::FLASH.pecr().read().prglock() { + pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); + pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516)); + } } } diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index e883678b..37c94f82 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -225,7 +225,9 @@ pub fn init(config: Config) -> Peripherals { #[cfg(feature = "low-power")] while !crate::rcc::low_power_ready() { - crate::rcc::clock_refcount_sub(); + critical_section::with(|cs| { + crate::rcc::clock_refcount_sub(cs); + }); } } diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index bb714b8c..861a59d7 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs @@ -1,7 +1,7 @@ use core::arch::asm; use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, Ordering}; -use atomic_polyfill::{compiler_fence, Ordering}; use cortex_m::peripheral::SCB; use embassy_executor::*; diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index 9c784c3a..a7c4b4f9 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -1,14 +1,24 @@ +use core::sync::atomic::{compiler_fence, Ordering}; + +use crate::pac::common::{Reg, RW}; +pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; +use crate::time::Hertz; + +#[cfg(any(stm32f0, stm32f1, stm32f3))] +pub const LSI_FREQ: Hertz = Hertz(40_000); +#[cfg(not(any(stm32f0, stm32f1, stm32f3)))] +pub const LSI_FREQ: Hertz = Hertz(32_000); + #[allow(dead_code)] #[derive(Clone, Copy)] -pub enum LseCfg { +pub enum LseMode { Oscillator(LseDrive), Bypass, } -impl Default for LseCfg { - fn default() -> Self { - Self::Oscillator(Default::default()) - } +pub struct LseConfig { + pub frequency: Hertz, + pub mode: LseMode, } #[allow(dead_code)] @@ -36,90 +46,116 @@ impl From for crate::pac::rcc::vals::Lsedrv { } } -pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource; - #[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] -#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Bdcr; - #[cfg(any(rtc_v2l0, rtc_v2l1))] -#[allow(dead_code)] type Bdcr = crate::pac::rcc::regs::Csr; +#[cfg(any(stm32c0))] +type Bdcr = crate::pac::rcc::regs::Csr1; -#[allow(dead_code)] -pub struct BackupDomain {} +#[cfg(any(stm32c0))] +fn unlock() {} -impl BackupDomain { - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code, unused_variables)] - fn modify(f: impl FnOnce(&mut Bdcr) -> R) -> R { - #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1, rtc_v2l0))] - let cr = crate::pac::PWR.cr(); - #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] - let cr = crate::pac::PWR.cr1(); +#[cfg(not(any(stm32c0)))] +fn unlock() { + #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))] + let cr = crate::pac::PWR.cr(); + #[cfg(not(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba)))] + let cr = crate::pac::PWR.cr1(); + #[cfg(any(stm32u5, stm32h5, stm32wba))] + let cr = crate::pac::PWR.dbpcr(); - // TODO: Missing from PAC for l0 and f0? - #[cfg(not(any(rtc_v2f0, rtc_v3u5)))] - { - cr.modify(|w| w.set_dbp(true)); - while !cr.read().dbp() {} + cr.modify(|w| w.set_dbp(true)); + while !cr.read().dbp() {} +} + +fn bdcr() -> Reg { + #[cfg(any(rtc_v2l0, rtc_v2l1))] + return crate::pac::RCC.csr(); + #[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] + return crate::pac::RCC.bdcr(); + #[cfg(any(stm32c0))] + return crate::pac::RCC.csr1(); +} + +pub struct LsConfig { + pub rtc: RtcClockSource, + pub lsi: bool, + pub lse: Option, +} + +impl LsConfig { + pub const fn default_lse() -> Self { + Self { + rtc: RtcClockSource::LSE, + lse: Some(LseConfig { + frequency: Hertz(32_768), + mode: LseMode::Oscillator(LseDrive::MediumHigh), + }), + lsi: false, } - - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let cr = crate::pac::RCC.csr(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let cr = crate::pac::RCC.bdcr(); - - cr.modify(|w| f(w)) } - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code)] - fn read() -> Bdcr { - #[cfg(any(rtc_v2l0, rtc_v2l1))] - let r = crate::pac::RCC.csr().read(); - - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] - let r = crate::pac::RCC.bdcr().read(); - - r + pub const fn default_lsi() -> Self { + Self { + rtc: RtcClockSource::LSI, + lsi: true, + lse: None, + } } - #[cfg(any( - rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3, - rtc_v3u5 - ))] - #[allow(dead_code, unused_variables)] - pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option) { - use atomic_polyfill::{compiler_fence, Ordering}; + pub const fn off() -> Self { + Self { + rtc: RtcClockSource::NOCLOCK, + lsi: false, + lse: None, + } + } +} - match clock_source { - RtcClockSource::LSI => assert!(lsi), - RtcClockSource::LSE => assert!(lse.is_some()), - _ => {} +impl Default for LsConfig { + fn default() -> Self { + // on L5, just the fact that LSI is enabled makes things crash. + // TODO: investigate. + + #[cfg(not(stm32l5))] + return Self::default_lsi(); + #[cfg(stm32l5)] + return Self::off(); + } +} + +impl LsConfig { + pub(crate) fn init(&self) -> Option { + let rtc_clk = match self.rtc { + RtcClockSource::LSI => { + assert!(self.lsi); + Some(LSI_FREQ) + } + RtcClockSource::LSE => Some(self.lse.as_ref().unwrap().frequency), + RtcClockSource::NOCLOCK => None, + _ => todo!(), }; - let (lse_en, lse_byp, lse_drv) = match lse { - Some(LseCfg::Oscillator(lse_drv)) => (true, false, Some(lse_drv)), - Some(LseCfg::Bypass) => (true, true, None), + + let (lse_en, lse_byp, lse_drv) = match &self.lse { + Some(c) => match c.mode { + LseMode::Oscillator(lse_drv) => (true, false, Some(lse_drv)), + LseMode::Bypass => (true, true, None), + }, None => (false, false, None), }; + _ = lse_drv; // not all chips have it. - if lsi { - #[cfg(rtc_v3u5)] + // Disable backup domain write protection + unlock(); + + if self.lsi { + #[cfg(any(stm32u5, stm32h5, stm32wba))] let csr = crate::pac::RCC.bdcr(); - - #[cfg(not(rtc_v3u5))] + #[cfg(not(any(stm32u5, stm32h5, stm32wba, stm32c0)))] let csr = crate::pac::RCC.csr(); - - // Disable backup domain write protection - Self::modify(|_| {}); + #[cfg(any(stm32c0))] + let csr = crate::pac::RCC.csr2(); #[cfg(not(any(rcc_wb, rcc_wba)))] csr.modify(|w| w.set_lsion(true)); @@ -139,12 +175,12 @@ impl BackupDomain { // first check if the configuration matches what we want. // check if it's already enabled and in the source we want. - let reg = Self::read(); + let reg = bdcr().read(); let mut ok = true; - ok &= reg.rtcsel() == clock_source; + ok &= reg.rtcsel() == self.rtc; #[cfg(not(rcc_wba))] { - ok &= reg.rtcen() == (clock_source != RtcClockSource::NOCLOCK); + ok &= reg.rtcen() == (self.rtc != RtcClockSource::NOCLOCK); } ok &= reg.lseon() == lse_en; ok &= reg.lsebyp() == lse_byp; @@ -155,22 +191,29 @@ impl BackupDomain { // if configuration is OK, we're done. if ok { - // RTC code assumes backup domain is unlocked - Self::modify(|w| {}); - - trace!("BDCR ok: {:08x}", Self::read().0); - return; + trace!("BDCR ok: {:08x}", bdcr().read().0); + return rtc_clk; } // If not OK, reset backup domain and configure it. - #[cfg(not(any(rcc_l0, rcc_l1)))] + #[cfg(not(any(rcc_l0, rcc_l0_v2, rcc_l1, stm32h5, stm32c0)))] { - Self::modify(|w| w.set_bdrst(true)); - Self::modify(|w| w.set_bdrst(false)); + bdcr().modify(|w| w.set_bdrst(true)); + bdcr().modify(|w| w.set_bdrst(false)); + } + #[cfg(any(stm32h5))] + { + bdcr().modify(|w| w.set_vswrst(true)); + bdcr().modify(|w| w.set_vswrst(false)); + } + #[cfg(any(stm32c0))] + { + bdcr().modify(|w| w.set_rtcrst(true)); + bdcr().modify(|w| w.set_rtcrst(false)); } if lse_en { - Self::modify(|w| { + bdcr().modify(|w| { #[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))] if let Some(lse_drv) = lse_drv { w.set_lsedrv(lse_drv.into()); @@ -179,22 +222,24 @@ impl BackupDomain { w.set_lseon(true); }); - while !Self::read().lserdy() {} + while !bdcr().read().lserdy() {} } - if clock_source != RtcClockSource::NOCLOCK { - Self::modify(|w| { + if self.rtc != RtcClockSource::NOCLOCK { + bdcr().modify(|w| { #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); #[cfg(not(rcc_wba))] w.set_rtcen(true); - w.set_rtcsel(clock_source); + w.set_rtcsel(self.rtc); }); } - trace!("BDCR configured: {:08x}", Self::read().0); + trace!("BDCR configured: {:08x}", bdcr().read().0); compiler_fence(Ordering::SeqCst); + + rtc_clk } } diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index efa56de7..eeb6418a 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -1,6 +1,6 @@ use crate::pac::flash::vals::Latency; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; -use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; +use crate::pac::rcc::vals::Sw; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Ppre as APBPrescaler}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -8,9 +8,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(48_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -19,47 +16,22 @@ pub enum ClockSrc { LSI, } -#[derive(Clone, Copy)] -pub enum HSIPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div32, - Div64, - Div128, -} - -impl Into for HSIPrescaler { - fn into(self) -> Hsidiv { - match self { - HSIPrescaler::NotDivided => Hsidiv::DIV1, - HSIPrescaler::Div2 => Hsidiv::DIV2, - HSIPrescaler::Div4 => Hsidiv::DIV4, - HSIPrescaler::Div8 => Hsidiv::DIV8, - HSIPrescaler::Div16 => Hsidiv::DIV16, - HSIPrescaler::Div32 => Hsidiv::DIV32, - HSIPrescaler::Div64 => Hsidiv::DIV64, - HSIPrescaler::Div128 => Hsidiv::DIV128, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::HSI(HSIPrescaler::NotDivided), + mux: ClockSrc::HSI(HSIPrescaler::DIV1), ahb_pre: AHBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -68,33 +40,34 @@ pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw) = match config.mux { ClockSrc::HSI(div) => { // Enable HSI - let div: Hsidiv = div.into(); RCC.cr().write(|w| { w.set_hsidiv(div); w.set_hsion(true) }); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ.0 >> div.to_bits(), Sw::HSI) + (HSI_FREQ / div, Sw::HSI) } ClockSrc::HSE(freq) => { // Enable HSE RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} - (freq.0, Sw::HSE) + (freq, Sw::HSE) } ClockSrc::LSI => { // Enable LSI RCC.csr2().write(|w| w.set_lsion(true)); while !RCC.csr2().read().lsirdy() {} - (LSI_FREQ.0, Sw::LSI) + (super::LSI_FREQ, Sw::LSI) } }; + let rtc = config.ls.init(); + // Determine the flash latency implied by the target clock speed // RM0454 § 3.3.4: - let target_flash_latency = if sys_clk <= 24_000_000 { + let target_flash_latency = if sys_clk <= Hertz(24_000_000) { Latency::WS0 } else { Latency::WS1 @@ -129,7 +102,7 @@ pub(crate) unsafe fn init(config: Config) { } // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once - let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); + let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre); RCC.cfgr().modify(|w| { w.set_sw(sw); w.set_hpre(hpre); @@ -150,34 +123,21 @@ pub(crate) unsafe fn init(config: Config) { FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); } - let ahb_div = match config.ahb_pre { - AHBPrescaler::DIV1 => 1, - AHBPrescaler::DIV2 => 2, - AHBPrescaler::DIV4 => 4, - AHBPrescaler::DIV8 => 8, - AHBPrescaler::DIV16 => 16, - AHBPrescaler::DIV64 => 64, - AHBPrescaler::DIV128 => 128, - AHBPrescaler::DIV256 => 256, - AHBPrescaler::DIV512 => 512, - _ => unreachable!(), - }; - let ahb_freq = sys_clk / ahb_div; + let ahb_freq = sys_clk / config.ahb_pre; let (apb_freq, apb_tim_freq) = match config.apb_pre { APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - apb1: Hertz(apb_freq), - apb1_tim: Hertz(apb_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + apb1: apb_freq, + apb1_tim: apb_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs index ca6eed28..cc712e87 100644 --- a/embassy-stm32/src/rcc/f0.rs +++ b/embassy-stm32/src/rcc/f0.rs @@ -8,9 +8,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - /// Configuration of the clocks /// /// hse takes precedence over hsi48 if both are enabled @@ -27,6 +24,8 @@ pub struct Config { pub sys_ck: Option, pub hclk: Option, pub pclk: Option, + + pub ls: super::LsConfig, } pub(crate) unsafe fn init(config: Config) { @@ -159,6 +158,8 @@ pub(crate) unsafe fn init(config: Config) { }) } + let rtc = config.ls.init(); + set_freqs(Clocks { sys: Hertz(real_sysclk), apb1: Hertz(pclk), @@ -166,5 +167,6 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim: Hertz(pclk * timer_mul), apb2_tim: Hertz(pclk * timer_mul), ahb1: Hertz(hclk), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs index 081c0c76..56c49cd8 100644 --- a/embassy-stm32/src/rcc/f1.rs +++ b/embassy-stm32/src/rcc/f1.rs @@ -9,9 +9,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - /// Configuration of the clocks /// #[non_exhaustive] @@ -25,6 +22,8 @@ pub struct Config { pub pclk2: Option, pub adcclk: Option, pub pllxtpre: bool, + + pub ls: super::LsConfig, } pub(crate) unsafe fn init(config: Config) { @@ -177,6 +176,8 @@ pub(crate) unsafe fn init(config: Config) { }); }); + let rtc = config.ls.init(); + set_freqs(Clocks { sys: Hertz(real_sysclk), apb1: Hertz(pclk1), @@ -185,5 +186,6 @@ pub(crate) unsafe fn init(config: Config) { apb2_tim: Hertz(pclk2 * timer_mul2), ahb1: Hertz(hclk), adc: Some(Hertz(adcclk)), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 07b816bf..ab588233 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -5,17 +5,12 @@ pub use crate::pac::rcc::vals::{ Ppre as APBPrescaler, }; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::BackupDomain; use crate::rcc::{set_freqs, Clocks}; -use crate::rtc::RtcClockSource; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - #[derive(Clone, Copy)] pub struct HSEConfig { pub frequency: Hertz, @@ -180,13 +175,11 @@ pub struct Config { pub pll_mux: PLLSrc, pub pll: PLLConfig, pub mux: ClockSrc, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, pub voltage: VoltageScale, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { @@ -199,12 +192,10 @@ impl Default for Config { pll: PLLConfig::default(), voltage: VoltageScale::Range3, mux: ClockSrc::HSI, - rtc: None, - lsi: false, - lse: None, ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -301,9 +292,9 @@ pub(crate) unsafe fn init(config: Config) { RCC.cfgr().modify(|w| { w.set_sw(sw.into()); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {} @@ -312,11 +303,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_hsion(false)); } - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); + let rtc = config.ls.init(); set_freqs(Clocks { sys: sys_clk, @@ -328,5 +315,6 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb2_tim: apb2_tim_freq, pll48: Some(pll_clocks.pll48_freq), + rtc, }); } diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index 630dbd4f..2aa79cec 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -1,7 +1,8 @@ #[cfg(rcc_f3)] use crate::pac::adccommon::vals::Ckmode; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; +pub use crate::pac::rcc::vals::Adcpres; +use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -9,28 +10,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(8_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(40_000); - -impl From for Adcpres { - fn from(value: AdcClockSource) -> Self { - match value { - AdcClockSource::PllDiv1 => Adcpres::DIV1, - AdcClockSource::PllDiv2 => Adcpres::DIV2, - AdcClockSource::PllDiv4 => Adcpres::DIV4, - AdcClockSource::PllDiv6 => Adcpres::DIV6, - AdcClockSource::PllDiv8 => Adcpres::DIV8, - AdcClockSource::PllDiv12 => Adcpres::DIV12, - AdcClockSource::PllDiv16 => Adcpres::DIV16, - AdcClockSource::PllDiv32 => Adcpres::DIV32, - AdcClockSource::PllDiv64 => Adcpres::DIV64, - AdcClockSource::PllDiv128 => Adcpres::DIV128, - AdcClockSource::PllDiv256 => Adcpres::DIV256, - _ => unreachable!(), - } - } -} - #[cfg(rcc_f3)] impl From for Ckmode { fn from(value: AdcClockSource) -> Self { @@ -45,32 +24,13 @@ impl From for Ckmode { #[derive(Clone, Copy)] pub enum AdcClockSource { - PllDiv1 = 1, - PllDiv2 = 2, - PllDiv4 = 4, - PllDiv6 = 6, - PllDiv8 = 8, - PllDiv12 = 12, - PllDiv16 = 16, - PllDiv32 = 32, - PllDiv64 = 64, - PllDiv128 = 128, - PllDiv256 = 256, + Pll(Adcpres), BusDiv1, BusDiv2, BusDiv4, } impl AdcClockSource { - pub fn is_bus(&self) -> bool { - match self { - Self::BusDiv1 => true, - Self::BusDiv2 => true, - Self::BusDiv4 => true, - _ => false, - } - } - pub fn bus_div(&self) -> u32 { match self { Self::BusDiv1 => 1, @@ -124,6 +84,7 @@ pub struct Config { pub adc34: Option, #[cfg(stm32f334)] pub hrtim: HrtimClockSource, + pub ls: super::LsConfig, } // Information required to setup the PLL clock @@ -137,67 +98,67 @@ struct PllConfig { /// Initialize and Set the clock frequencies pub(crate) unsafe fn init(config: Config) { // Calculate the real System clock, and PLL configuration if applicable - let (Hertz(sysclk), pll_config) = get_sysclk(&config); - assert!(sysclk <= 72_000_000); + let (sysclk, pll_config) = get_sysclk(&config); + assert!(sysclk.0 <= 72_000_000); // Calculate real AHB clock - let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk); - let (hpre_bits, hpre_div) = match sysclk / hclk { + let hclk = config.hclk.map(|h| h).unwrap_or(sysclk); + let hpre = match sysclk.0 / hclk.0 { 0 => unreachable!(), - 1 => (Hpre::DIV1, 1), - 2 => (Hpre::DIV2, 2), - 3..=5 => (Hpre::DIV4, 4), - 6..=11 => (Hpre::DIV8, 8), - 12..=39 => (Hpre::DIV16, 16), - 40..=95 => (Hpre::DIV64, 64), - 96..=191 => (Hpre::DIV128, 128), - 192..=383 => (Hpre::DIV256, 256), - _ => (Hpre::DIV512, 512), + 1 => Hpre::DIV1, + 2 => Hpre::DIV2, + 3..=5 => Hpre::DIV4, + 6..=11 => Hpre::DIV8, + 12..=39 => Hpre::DIV16, + 40..=95 => Hpre::DIV64, + 96..=191 => Hpre::DIV128, + 192..=383 => Hpre::DIV256, + _ => Hpre::DIV512, }; - let hclk = sysclk / hpre_div; - assert!(hclk <= 72_000_000); + let hclk = sysclk / hpre; + assert!(hclk <= Hertz(72_000_000)); // Calculate real APB1 clock - let pclk1 = config.pclk1.map(|p| p.0).unwrap_or(hclk); - let (ppre1_bits, ppre1) = match hclk / pclk1 { + let pclk1 = config.pclk1.unwrap_or(hclk); + let ppre1 = match hclk / pclk1 { 0 => unreachable!(), - 1 => (Ppre::DIV1, 1), - 2 => (Ppre::DIV2, 2), - 3..=5 => (Ppre::DIV4, 4), - 6..=11 => (Ppre::DIV8, 8), - _ => (Ppre::DIV16, 16), + 1 => Ppre::DIV1, + 2 => Ppre::DIV2, + 3..=5 => Ppre::DIV4, + 6..=11 => Ppre::DIV8, + _ => Ppre::DIV16, }; - let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; + let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 }; let pclk1 = hclk / ppre1; - assert!(pclk1 <= 36_000_000); + assert!(pclk1 <= Hertz(36_000_000)); // Calculate real APB2 clock - let pclk2 = config.pclk2.map(|p| p.0).unwrap_or(hclk); - let (ppre2_bits, ppre2) = match hclk / pclk2 { + let pclk2 = config.pclk2.unwrap_or(hclk); + let ppre2 = match hclk / pclk2 { 0 => unreachable!(), - 1 => (Ppre::DIV1, 1), - 2 => (Ppre::DIV2, 2), - 3..=5 => (Ppre::DIV4, 4), - 6..=11 => (Ppre::DIV8, 8), - _ => (Ppre::DIV16, 16), + 1 => Ppre::DIV1, + 2 => Ppre::DIV2, + 3..=5 => Ppre::DIV4, + 6..=11 => Ppre::DIV8, + _ => Ppre::DIV16, }; - let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; + let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 }; let pclk2 = hclk / ppre2; - assert!(pclk2 <= 72_000_000); + assert!(pclk2 <= Hertz(72_000_000)); // Set latency based on HCLK frquency // 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" FLASH.acr().modify(|w| { - w.set_latency(if hclk <= 24_000_000 { + w.set_latency(if hclk <= Hertz(24_000_000) { Latency::WS0 - } else if hclk <= 48_000_000 { + } else if hclk <= Hertz(48_000_000) { Latency::WS1 } else { Latency::WS2 }); - if hpre_div != 1 { + if hpre != Hpre::DIV1 { w.set_hlfcya(false); w.set_prftbe(true); } @@ -240,9 +201,9 @@ 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(ppre2_bits); - w.set_ppre1(ppre1_bits); - w.set_hpre(hpre_bits); + w.set_ppre2(ppre2); + w.set_ppre1(ppre1); + w.set_hpre(hpre); }); // Wait for the new prescalers to kick in @@ -260,45 +221,43 @@ pub(crate) unsafe fn init(config: Config) { }); #[cfg(rcc_f3)] - let adc = config.adc.map(|adc| { - if !adc.is_bus() { + let adc = config.adc.map(|adc| match adc { + AdcClockSource::Pll(adcpres) => { RCC.cfgr2().modify(|w| { // Make sure that we're using the PLL pll_config.unwrap(); - w.set_adc12pres(adc.into()); + w.set_adc12pres(adcpres); - Hertz(sysclk / adc as u32) - }) - } else { - crate::pac::ADC_COMMON.ccr().modify(|w| { - assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); - - w.set_ckmode(adc.into()); - - Hertz(sysclk / adc.bus_div() as u32) + sysclk / adcpres }) } + _ => crate::pac::ADC_COMMON.ccr().modify(|w| { + assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1)); + + w.set_ckmode(adc.into()); + + sysclk / adc.bus_div() + }), }); #[cfg(all(rcc_f3, adc3_common))] - let adc34 = config.adc.map(|adc| { - if !adc.is_bus() { + let adc34 = config.adc34.map(|adc| match adc { + AdcClockSource::Pll(adcpres) => { RCC.cfgr2().modify(|w| { // Make sure that we're using the PLL pll_config.unwrap(); - w.set_adc12pres(adc.into()); + w.set_adc34pres(adcpres); - Hertz(sysclk / adc as u32) - }) - } else { - crate::pac::ADC3_COMMON.ccr().modify(|w| { - assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); - - w.set_ckmode(adc.into()); - - Hertz(sysclk / adc.bus_div() as u32) + sysclk / adcpres }) } + _ => crate::pac::ADC_COMMON.ccr().modify(|w| { + assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1)); + + w.set_ckmode(adc.into()); + + sysclk / adc.bus_div() + }), }); #[cfg(stm32f334)] @@ -310,21 +269,23 @@ pub(crate) unsafe fn init(config: Config) { // Make sure that we're using the PLL pll_config.unwrap(); - assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk)); + assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk)); RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL)); - Some(Hertz(sysclk * 2)) + Some(sysclk * 2u32) } }; + let rtc = config.ls.init(); + set_freqs(Clocks { - sys: Hertz(sysclk), - apb1: Hertz(pclk1), - apb2: Hertz(pclk2), - apb1_tim: Hertz(pclk1 * timer_mul1), - apb2_tim: Hertz(pclk2 * timer_mul2), - ahb1: Hertz(hclk), + sys: sysclk, + apb1: pclk1, + apb2: pclk2, + apb1_tim: pclk1 * timer_mul1, + apb2_tim: pclk2 * timer_mul2, + ahb1: hclk, #[cfg(rcc_f3)] adc: adc, #[cfg(all(rcc_f3, adc3_common))] @@ -333,6 +294,7 @@ pub(crate) unsafe fn init(config: Config) { adc34: None, #[cfg(stm32f334)] hrtim: hrtim, + rtc, }); } @@ -421,16 +383,16 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { #[inline] #[allow(unused_variables)] -fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option) -> Usbpre { +fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option) -> Usbpre { cfg_if::cfg_if! { // Some chips do not have USB if #[cfg(any(stm32f301, stm32f318, stm32f334))] { panic!("USB clock not supported by the chip"); } else { - let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000); + let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000)); match (usb_ok, sysclk) { - (true, 72_000_000) => Usbpre::DIV1_5, - (true, 48_000_000) => Usbpre::DIV1, + (true, Hertz(72_000_000)) => Usbpre::DIV1_5, + (true, Hertz(48_000_000)) => Usbpre::DIV1, _ => panic!( "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz" ), diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 754a0d57..79c2d2f6 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -1,17 +1,11 @@ -use stm32_metapac::rcc::vals::{Pllm, Plln, Pllq, Pllr}; - -use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; +use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllq, Pllr, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// Clocks configuration #[non_exhaustive] #[derive(Default)] @@ -30,9 +24,7 @@ pub struct Config { pub pllsai: Option, pub pll48: bool, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, + pub ls: super::LsConfig, } #[cfg(stm32f410)] @@ -344,17 +336,7 @@ pub(crate) unsafe fn init(config: Config) { }) }); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); - - let rtc = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; + let rtc = config.ls.init(); set_freqs(Clocks { sys: Hertz(sysclk), @@ -377,7 +359,6 @@ pub(crate) unsafe fn init(config: Config) { pllsai: plls.pllsaiclk.map(Hertz), rtc, - rtc_hse: None, }); } diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index 565f6aa9..0a0a1cf2 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -1,16 +1,12 @@ use crate::pac::pwr::vals::Vos; use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllp, Pllq, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// Clocks configuration #[non_exhaustive] #[derive(Default)] @@ -23,9 +19,7 @@ pub struct Config { pub pclk2: Option, pub pll48: bool, - pub rtc: Option, - pub lsi: bool, - pub lse: Option, + pub ls: super::LsConfig, } fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { @@ -261,17 +255,7 @@ pub(crate) unsafe fn init(config: Config) { }) }); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); - - let rtc = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; + let rtc = config.ls.init(); set_freqs(Clocks { sys: Hertz(sysclk), diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 5ac40911..962b1dc0 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -1,6 +1,8 @@ use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{self, Hsidiv, Sw}; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler}; +use crate::pac::rcc::vals::{self, Sw}; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Hsidiv as HSI16Prescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler, +}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -8,9 +10,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -20,33 +19,6 @@ pub enum ClockSrc { LSI, } -#[derive(Clone, Copy)] -pub enum HSI16Prescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div32, - Div64, - Div128, -} - -impl Into for HSI16Prescaler { - fn into(self) -> Hsidiv { - match self { - HSI16Prescaler::NotDivided => Hsidiv::DIV1, - HSI16Prescaler::Div2 => Hsidiv::DIV2, - HSI16Prescaler::Div4 => Hsidiv::DIV4, - HSI16Prescaler::Div8 => Hsidiv::DIV8, - HSI16Prescaler::Div16 => Hsidiv::DIV16, - HSI16Prescaler::Div32 => Hsidiv::DIV32, - HSI16Prescaler::Div64 => Hsidiv::DIV64, - HSI16Prescaler::Div128 => Hsidiv::DIV128, - } - } -} - /// The PLL configuration. /// /// * `VCOCLK = source / m * n` @@ -98,16 +70,18 @@ pub struct Config { pub ahb_pre: AHBPrescaler, pub apb_pre: APBPrescaler, pub low_power_run: bool, + pub ls: super::LsConfig, } impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided), + mux: ClockSrc::HSI16(HSI16Prescaler::DIV1), ahb_pre: AHBPrescaler::DIV1, apb_pre: APBPrescaler::DIV1, low_power_run: false, + ls: Default::default(), } } } @@ -195,7 +169,6 @@ pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw) = match config.mux { ClockSrc::HSI16(div) => { // Enable HSI16 - let div: Hsidiv = div.into(); RCC.cr().write(|w| { w.set_hsidiv(div); w.set_hsion(true) @@ -219,7 +192,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable LSI RCC.csr().write(|w| w.set_lsion(true)); while !RCC.csr().read().lsirdy() {} - (LSI_FREQ, Sw::LSI) + (super::LSI_FREQ, Sw::LSI) } }; @@ -262,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) { } // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once - let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); + let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre); RCC.cfgr().modify(|w| { w.set_sw(sw); w.set_hpre(hpre); @@ -298,10 +271,13 @@ pub(crate) unsafe fn init(config: Config) { PWR.cr1().modify(|w| w.set_lpr(true)); } + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, apb1: apb_freq, apb1_tim: apb_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 08ccc5fe..a4078e38 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -3,7 +3,8 @@ use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; use stm32_metapac::FLASH; pub use crate::pac::rcc::vals::{ - Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler, + Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, + Pllr as PllR, Ppre as APBPrescaler, }; use crate::pac::{PWR, RCC}; use crate::rcc::sealed::RccPeripheral; @@ -13,32 +14,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -#[derive(Clone, Copy)] -pub enum AdcClockSource { - NoClk, - SysClk, - PllP, -} - -impl AdcClockSource { - pub fn adcsel(&self) -> Adcsel { - match self { - AdcClockSource::NoClk => Adcsel::NOCLK, - AdcClockSource::SysClk => Adcsel::SYSCLK, - AdcClockSource::PllP => Adcsel::PLLP, - } - } -} - -impl Default for AdcClockSource { - fn default() -> Self { - Self::NoClk - } -} - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -88,32 +63,6 @@ pub struct Pll { pub div_r: Option, } -fn ahb_div(ahb: AHBPrescaler) -> u32 { - match ahb { - AHBPrescaler::DIV1 => 1, - AHBPrescaler::DIV2 => 2, - AHBPrescaler::DIV4 => 4, - AHBPrescaler::DIV8 => 8, - AHBPrescaler::DIV16 => 16, - AHBPrescaler::DIV64 => 64, - AHBPrescaler::DIV128 => 128, - AHBPrescaler::DIV256 => 256, - AHBPrescaler::DIV512 => 512, - _ => unreachable!(), - } -} - -fn apb_div(apb: APBPrescaler) -> u32 { - match apb { - APBPrescaler::DIV1 => 1, - APBPrescaler::DIV2 => 2, - APBPrescaler::DIV4 => 4, - APBPrescaler::DIV8 => 8, - APBPrescaler::DIV16 => 16, - _ => unreachable!(), - } -} - /// Sets the source for the 48MHz clock to the USB and RNG peripherals. pub enum Clock48MhzSrc { /// Use the High Speed Internal Oscillator. For USB usage, the CRS must be used to calibrate the @@ -149,6 +98,8 @@ pub struct Config { pub clock_48mhz_src: Option, pub adc12_clock_source: AdcClockSource, pub adc345_clock_source: AdcClockSource, + + pub ls: super::LsConfig, } /// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator. @@ -168,8 +119,9 @@ impl Default for Config { low_power_run: false, pll: None, clock_48mhz_src: None, - adc12_clock_source: Default::default(), - adc345_clock_source: Default::default(), + adc12_clock_source: Adcsel::NOCLK, + adc345_clock_source: Adcsel::NOCLK, + ls: Default::default(), } } } @@ -203,8 +155,8 @@ pub(crate) unsafe fn init(config: Config) { let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n; RCC.pllcfgr().write(|w| { - w.set_plln(pll_config.mul_n.into()); - w.set_pllm(pll_config.prediv_m.into()); + w.set_plln(pll_config.mul_n); + w.set_pllm(pll_config.prediv_m); w.set_pllsrc(pll_config.source.into()); }); @@ -249,14 +201,14 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ.0, Sw::HSI16) + (HSI_FREQ, Sw::HSI16) } ClockSrc::HSE(freq) => { // Enable HSE RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} - (freq.0, Sw::HSE) + (freq, Sw::HSE) } ClockSrc::PLL => { assert!(pll_freq.is_some()); @@ -297,35 +249,32 @@ pub(crate) unsafe fn init(config: Config) { } } - (freq, Sw::PLLRCLK) + (Hertz(freq), Sw::PLLRCLK) } }; RCC.cfgr().modify(|w| { w.set_sw(sw); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); - let ahb_freq: u32 = match config.ahb_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => sys_clk / ahb_div(pre), - }; + let ahb_freq = sys_clk / config.ahb_pre; let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let freq = ahb_freq / apb_div(pre); - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let freq = ahb_freq / apb_div(pre); - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; @@ -373,43 +322,40 @@ pub(crate) unsafe fn init(config: Config) { RCC.ccipr().modify(|w| w.set_clk48sel(source)); } - RCC.ccipr() - .modify(|w| w.set_adc12sel(config.adc12_clock_source.adcsel())); - RCC.ccipr() - .modify(|w| w.set_adc345sel(config.adc345_clock_source.adcsel())); + RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source)); + RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source)); let adc12_ck = match config.adc12_clock_source { - AdcClockSource::NoClk => None, - AdcClockSource::PllP => match &pll_freq { - Some(pll) => pll.pll_p, - None => None, - }, - AdcClockSource::SysClk => Some(Hertz(sys_clk)), + AdcClockSource::NOCLK => None, + AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p, + AdcClockSource::SYSCLK => Some(sys_clk), + _ => unreachable!(), }; let adc345_ck = match config.adc345_clock_source { - AdcClockSource::NoClk => None, - AdcClockSource::PllP => match &pll_freq { - Some(pll) => pll.pll_p, - None => None, - }, - AdcClockSource::SysClk => Some(Hertz(sys_clk)), + AdcClockSource::NOCLK => None, + AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p, + AdcClockSource::SYSCLK => Some(sys_clk), + _ => unreachable!(), }; if config.low_power_run { - assert!(sys_clk <= 2_000_000); + assert!(sys_clk <= Hertz(2_000_000)); PWR.cr1().modify(|w| w.set_lpr(true)); } + let rtc = config.ls.init(); + set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - ahb2: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2: Hertz(apb2_freq), - apb2_tim: Hertz(apb2_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + ahb2: ahb_freq, + apb1: apb1_freq, + apb1_tim: apb1_tim_freq, + apb2: apb2_freq, + apb2_tim: apb2_tim_freq, adc: adc12_ck, adc34: adc345_ck, + rtc, }); } diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index b82dc37e..f7a8d68a 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -9,8 +9,6 @@ pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; use crate::pac::{FLASH, PWR, RCC}; -#[cfg(stm32h7)] -use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -23,16 +21,13 @@ pub const CSI_FREQ: Hertz = Hertz(4_000_000); /// HSI48 speed pub const HSI48_FREQ: Hertz = Hertz(48_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -const VCO_RANGE: RangeInclusive = 150_000_000..=420_000_000; +const VCO_RANGE: RangeInclusive = Hertz(150_000_000)..=Hertz(420_000_000); #[cfg(any(stm32h5, pwr_h7rm0455))] -const VCO_WIDE_RANGE: RangeInclusive = 128_000_000..=560_000_000; +const VCO_WIDE_RANGE: RangeInclusive = Hertz(128_000_000)..=Hertz(560_000_000); #[cfg(pwr_h7rm0468)] -const VCO_WIDE_RANGE: RangeInclusive = 192_000_000..=836_000_000; +const VCO_WIDE_RANGE: RangeInclusive = Hertz(192_000_000)..=Hertz(836_000_000); #[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] -const VCO_WIDE_RANGE: RangeInclusive = 192_000_000..=960_000_000; +const VCO_WIDE_RANGE: RangeInclusive = Hertz(192_000_000)..=Hertz(960_000_000); pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; @@ -196,8 +191,7 @@ pub struct Config { pub adc_clock_source: AdcClockSource, pub timer_prescaler: TimerPrescaler, pub voltage_scale: VoltageScale, - #[cfg(stm32h7)] - pub rtc_mux: Option, + pub ls: super::LsConfig, } impl Default for Config { @@ -231,8 +225,7 @@ impl Default for Config { adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5 timer_prescaler: TimerPrescaler::DefaultX2, voltage_scale: VoltageScale::Scale0, - #[cfg(stm32h7)] - rtc_mux: None, + ls: Default::default(), } } } @@ -471,18 +464,7 @@ pub(crate) unsafe fn init(config: Config) { flash_setup(hclk, config.voltage_scale); - #[cfg(stm32h7)] - { - let lsecfg = config.lse.map(|lse| match lse { - Lse::Bypass(freq) => { - assert!(freq <= Hertz(1_000_000)); - LseCfg::Bypass - } - Lse::Oscillator => LseCfg::Oscillator(Default::default()), - }); - - BackupDomain::configure_ls(config.rtc_mux.unwrap_or(RtcClockSource::NOCLOCK), config.lsi, lsecfg); - } + let rtc = config.ls.init(); #[cfg(stm32h7)] { @@ -548,17 +530,6 @@ pub(crate) unsafe fn init(config: Config) { while !pac::SYSCFG.cccsr().read().ready() {} } - #[cfg(stm32h7)] - let rtc_clk = match config.rtc_mux { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(match config.lse { - Some(Lse::Oscillator) => Hertz(32768), - Some(Lse::Bypass(freq)) => freq, - None => panic!("LSE not configured"), - }), - _ => None, - }; - set_freqs(Clocks { sys, ahb1: hclk, @@ -573,10 +544,7 @@ pub(crate) unsafe fn init(config: Config) { apb1_tim, apb2_tim, adc, - #[cfg(stm32h7)] rtc: rtc_clk, - #[cfg(stm32h7)] - rtc_hse: None, #[cfg(stm32h5)] mux_rcc_pclk1: None, @@ -686,9 +654,9 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { let wide_allowed = ref_range != Pllrge::RANGE1; let vco_clk = ref_clk * config.mul; - let vco_range = if VCO_RANGE.contains(&vco_clk.0) { + let vco_range = if VCO_RANGE.contains(&vco_clk) { Pllvcosel::MEDIUMVCO - } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk.0) { + } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk) { Pllvcosel::WIDEVCO } else { panic!("pll vco_clk out of range: {} mhz", vco_clk.0) diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs deleted file mode 100644 index b4236126..00000000 --- a/embassy-stm32/src/rcc/l0.rs +++ /dev/null @@ -1,349 +0,0 @@ -use super::bd::BackupDomain; -use super::RtcClockSource; -pub use crate::pac::pwr::vals::Vos as VoltageScale; -use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; -#[cfg(crs)] -use crate::pac::{crs, CRS, SYSCFG}; -use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::{set_freqs, Clocks}; -use crate::time::Hertz; - -/// HSI speed -pub const HSI_FREQ: Hertz = Hertz(16_000_000); - -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -/// System clock mux source -#[derive(Clone, Copy)] -pub enum ClockSrc { - MSI(MSIRange), - PLL(PLLSource, PLLMul, PLLDiv), - HSE(Hertz), - HSI16, -} - -/// MSI Clock Range -/// -/// These ranges control the frequency of the MSI. Internally, these ranges map -/// to the `MSIRANGE` bits in the `RCC_ICSCR` register. -#[derive(Clone, Copy)] -pub enum MSIRange { - /// Around 65.536 kHz - Range0, - /// Around 131.072 kHz - Range1, - /// Around 262.144 kHz - Range2, - /// Around 524.288 kHz - Range3, - /// Around 1.048 MHz - Range4, - /// Around 2.097 MHz (reset value) - Range5, - /// Around 4.194 MHz - Range6, -} - -impl Default for MSIRange { - fn default() -> MSIRange { - MSIRange::Range5 - } -} - -/// PLL divider -#[derive(Clone, Copy)] -pub enum PLLDiv { - Div2, - Div3, - Div4, -} - -/// PLL multiplier -#[derive(Clone, Copy)] -pub enum PLLMul { - Mul3, - Mul4, - Mul6, - Mul8, - Mul12, - Mul16, - Mul24, - Mul32, - Mul48, -} - -/// PLL clock input source -#[derive(Clone, Copy)] -pub enum PLLSource { - HSI16, - HSE(Hertz), -} - -impl From for Pllmul { - fn from(val: PLLMul) -> Pllmul { - match val { - PLLMul::Mul3 => Pllmul::MUL3, - PLLMul::Mul4 => Pllmul::MUL4, - PLLMul::Mul6 => Pllmul::MUL6, - PLLMul::Mul8 => Pllmul::MUL8, - PLLMul::Mul12 => Pllmul::MUL12, - PLLMul::Mul16 => Pllmul::MUL16, - PLLMul::Mul24 => Pllmul::MUL24, - PLLMul::Mul32 => Pllmul::MUL32, - PLLMul::Mul48 => Pllmul::MUL48, - } - } -} - -impl From for Plldiv { - fn from(val: PLLDiv) -> Plldiv { - match val { - PLLDiv::Div2 => Plldiv::DIV2, - PLLDiv::Div3 => Plldiv::DIV3, - PLLDiv::Div4 => Plldiv::DIV4, - } - } -} - -impl From for Pllsrc { - fn from(val: PLLSource) -> Pllsrc { - match val { - PLLSource::HSI16 => Pllsrc::HSI16, - PLLSource::HSE(_) => Pllsrc::HSE, - } - } -} - -impl From for Msirange { - fn from(val: MSIRange) -> Msirange { - match val { - MSIRange::Range0 => Msirange::RANGE0, - MSIRange::Range1 => Msirange::RANGE1, - MSIRange::Range2 => Msirange::RANGE2, - MSIRange::Range3 => Msirange::RANGE3, - MSIRange::Range4 => Msirange::RANGE4, - MSIRange::Range5 => Msirange::RANGE5, - MSIRange::Range6 => Msirange::RANGE6, - } - } -} - -/// Clocks configutation -pub struct Config { - pub mux: ClockSrc, - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - pub apb2_pre: APBPrescaler, - #[cfg(crs)] - pub enable_hsi48: bool, - pub rtc: Option, - pub lse: Option, - pub lsi: bool, - pub voltage_scale: VoltageScale, -} - -impl Default for Config { - #[inline] - fn default() -> Config { - Config { - mux: ClockSrc::MSI(MSIRange::default()), - ahb_pre: AHBPrescaler::DIV1, - apb1_pre: APBPrescaler::DIV1, - apb2_pre: APBPrescaler::DIV1, - #[cfg(crs)] - enable_hsi48: false, - rtc: None, - lse: None, - lsi: false, - voltage_scale: VoltageScale::RANGE1, - } - } -} - -pub(crate) unsafe fn init(config: Config) { - // Set voltage scale - while PWR.csr().read().vosf() {} - PWR.cr().write(|w| w.set_vos(config.voltage_scale)); - while PWR.csr().read().vosf() {} - - let (sys_clk, sw) = match config.mux { - ClockSrc::MSI(range) => { - // Set MSI range - RCC.icscr().write(|w| w.set_msirange(range.into())); - - // Enable MSI - RCC.cr().write(|w| w.set_msion(true)); - while !RCC.cr().read().msirdy() {} - - let freq = 32_768 * (1 << (range as u8 + 1)); - (freq, Sw::MSI) - } - ClockSrc::HSI16 => { - // Enable HSI16 - RCC.cr().write(|w| w.set_hsi16on(true)); - while !RCC.cr().read().hsi16rdyf() {} - - (HSI_FREQ.0, Sw::HSI16) - } - ClockSrc::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - - (freq.0, Sw::HSE) - } - ClockSrc::PLL(src, mul, div) => { - let freq = match src { - PLLSource::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - freq.0 - } - PLLSource::HSI16 => { - // Enable HSI - RCC.cr().write(|w| w.set_hsi16on(true)); - while !RCC.cr().read().hsi16rdyf() {} - HSI_FREQ.0 - } - }; - - // Disable PLL - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} - - let freq = match mul { - PLLMul::Mul3 => freq * 3, - PLLMul::Mul4 => freq * 4, - PLLMul::Mul6 => freq * 6, - PLLMul::Mul8 => freq * 8, - PLLMul::Mul12 => freq * 12, - PLLMul::Mul16 => freq * 16, - PLLMul::Mul24 => freq * 24, - PLLMul::Mul32 => freq * 32, - PLLMul::Mul48 => freq * 48, - }; - - let freq = match div { - PLLDiv::Div2 => freq / 2, - PLLDiv::Div3 => freq / 3, - PLLDiv::Div4 => freq / 4, - }; - assert!(freq <= 32_000_000); - - RCC.cfgr().write(move |w| { - w.set_pllmul(mul.into()); - w.set_plldiv(div.into()); - w.set_pllsrc(src.into()); - }); - - // Enable PLL - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - (freq, Sw::PLL) - } - }; - - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); - - let wait_states = match config.voltage_scale { - VoltageScale::RANGE1 => match sys_clk { - ..=16_000_000 => 0, - _ => 1, - }, - VoltageScale::RANGE2 => match sys_clk { - ..=8_000_000 => 0, - _ => 1, - }, - VoltageScale::RANGE3 => 0, - _ => unreachable!(), - }; - FLASH.acr().modify(|w| { - w.set_latency(wait_states != 0); - }); - - RCC.cfgr().modify(|w| { - w.set_sw(sw); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); - }); - - let ahb_freq: u32 = match config.ahb_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: Hpre = pre.into(); - let pre = 1 << (pre.to_bits() as u32 - 7); - sys_clk / pre - } - }; - - let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) - } - }; - - let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) - } - }; - - #[cfg(crs)] - if config.enable_hsi48 { - // Reset CRS peripheral - RCC.apb1rstr().modify(|w| w.set_crsrst(true)); - RCC.apb1rstr().modify(|w| w.set_crsrst(false)); - - // Enable CRS peripheral - RCC.apb1enr().modify(|w| w.set_crsen(true)); - - // Initialize CRS - CRS.cfgr().write(|w| - - // Select LSE as synchronization source - w.set_syncsrc(crs::vals::Syncsrc::LSE)); - CRS.cr().modify(|w| { - w.set_autotrimen(true); - w.set_cen(true); - }); - - // Enable VREFINT reference for HSI48 oscillator - SYSCFG.cfgr3().modify(|w| { - w.set_enref_hsi48(true); - w.set_en_vrefint(true); - }); - - // Select HSI48 as USB clock - RCC.ccipr().modify(|w| w.set_hsi48msel(true)); - - // Enable dedicated USB clock - RCC.crrcr().modify(|w| w.set_hsi48on(true)); - while !RCC.crrcr().read().hsi48rdy() {} - } - - set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), - }); -} diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs new file mode 100644 index 00000000..d8a1fc10 --- /dev/null +++ b/embassy-stm32/src/rcc/l0l1.rs @@ -0,0 +1,219 @@ +pub use crate::pac::pwr::vals::Vos as VoltageScale; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler, +}; +use crate::pac::rcc::vals::{Pllsrc, Sw}; +#[cfg(crs)] +use crate::pac::{crs, CRS, SYSCFG}; +use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::{set_freqs, Clocks}; +use crate::time::Hertz; + +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// System clock mux source +#[derive(Clone, Copy)] +pub enum ClockSrc { + MSI(MSIRange), + PLL(PLLSource, PLLMul, PLLDiv), + HSE(Hertz), + HSI16, +} + +/// PLL clock input source +#[derive(Clone, Copy)] +pub enum PLLSource { + HSI16, + HSE(Hertz), +} + +impl From for Pllsrc { + fn from(val: PLLSource) -> Pllsrc { + match val { + PLLSource::HSI16 => Pllsrc::HSI16, + PLLSource::HSE(_) => Pllsrc::HSE, + } + } +} + +/// Clocks configutation +pub struct Config { + pub mux: ClockSrc, + pub ahb_pre: AHBPrescaler, + pub apb1_pre: APBPrescaler, + pub apb2_pre: APBPrescaler, + #[cfg(crs)] + pub enable_hsi48: bool, + pub ls: super::LsConfig, + pub voltage_scale: VoltageScale, +} + +impl Default for Config { + #[inline] + fn default() -> Config { + Config { + mux: ClockSrc::MSI(MSIRange::RANGE5), + ahb_pre: AHBPrescaler::DIV1, + apb1_pre: APBPrescaler::DIV1, + apb2_pre: APBPrescaler::DIV1, + #[cfg(crs)] + enable_hsi48: false, + voltage_scale: VoltageScale::RANGE1, + ls: Default::default(), + } + } +} + +pub(crate) unsafe fn init(config: Config) { + // Set voltage scale + while PWR.csr().read().vosf() {} + PWR.cr().write(|w| w.set_vos(config.voltage_scale)); + while PWR.csr().read().vosf() {} + + let (sys_clk, sw) = match config.mux { + ClockSrc::MSI(range) => { + // Set MSI range + RCC.icscr().write(|w| w.set_msirange(range)); + + // Enable MSI + RCC.cr().write(|w| w.set_msion(true)); + while !RCC.cr().read().msirdy() {} + + let freq = 32_768 * (1 << (range as u8 + 1)); + (Hertz(freq), Sw::MSI) + } + ClockSrc::HSI16 => { + // Enable HSI16 + RCC.cr().write(|w| w.set_hsi16on(true)); + while !RCC.cr().read().hsi16rdy() {} + + (HSI_FREQ, Sw::HSI16) + } + ClockSrc::HSE(freq) => { + // Enable HSE + RCC.cr().write(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + + (freq, Sw::HSE) + } + ClockSrc::PLL(src, mul, div) => { + let freq = match src { + PLLSource::HSE(freq) => { + // Enable HSE + RCC.cr().write(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + freq + } + PLLSource::HSI16 => { + // Enable HSI + RCC.cr().write(|w| w.set_hsi16on(true)); + while !RCC.cr().read().hsi16rdy() {} + HSI_FREQ + } + }; + + // Disable PLL + RCC.cr().modify(|w| w.set_pllon(false)); + while RCC.cr().read().pllrdy() {} + + let freq = freq * mul / div; + + assert!(freq <= Hertz(32_000_000)); + + RCC.cfgr().write(move |w| { + w.set_pllmul(mul); + w.set_plldiv(div); + w.set_pllsrc(src.into()); + }); + + // Enable PLL + RCC.cr().modify(|w| w.set_pllon(true)); + while !RCC.cr().read().pllrdy() {} + + (freq, Sw::PLL) + } + }; + + let rtc = config.ls.init(); + + let wait_states = match (config.voltage_scale, sys_clk.0) { + (VoltageScale::RANGE1, ..=16_000_000) => 0, + (VoltageScale::RANGE2, ..=8_000_000) => 0, + (VoltageScale::RANGE3, ..=4_200_000) => 0, + _ => 1, + }; + + #[cfg(stm32l1)] + FLASH.acr().write(|w| w.set_acc64(true)); + FLASH.acr().modify(|w| w.set_prften(true)); + FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); + + RCC.cfgr().modify(|w| { + w.set_sw(sw); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); + }); + + let ahb_freq = sys_clk / config.ahb_pre; + + let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { + APBPrescaler::DIV1 => (ahb_freq, ahb_freq), + pre => { + let freq = ahb_freq / pre; + (freq, freq * 2u32) + } + }; + + let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { + APBPrescaler::DIV1 => (ahb_freq, ahb_freq), + pre => { + let freq = ahb_freq / pre; + (freq, freq * 2u32) + } + }; + + #[cfg(crs)] + if config.enable_hsi48 { + // Reset CRS peripheral + RCC.apb1rstr().modify(|w| w.set_crsrst(true)); + RCC.apb1rstr().modify(|w| w.set_crsrst(false)); + + // Enable CRS peripheral + RCC.apb1enr().modify(|w| w.set_crsen(true)); + + // Initialize CRS + CRS.cfgr().write(|w| + + // Select LSE as synchronization source + w.set_syncsrc(crs::vals::Syncsrc::LSE)); + CRS.cr().modify(|w| { + w.set_autotrimen(true); + w.set_cen(true); + }); + + // Enable VREFINT reference for HSI48 oscillator + SYSCFG.cfgr3().modify(|w| { + w.set_enref_hsi48(true); + w.set_en_vrefint(true); + }); + + // Select HSI48 as USB clock + RCC.ccipr().modify(|w| w.set_hsi48msel(true)); + + // Enable dedicated USB clock + RCC.crrcr().modify(|w| w.set_hsi48on(true)); + while !RCC.crrcr().read().hsi48rdy() {} + } + + set_freqs(Clocks { + sys: sys_clk, + ahb1: ahb_freq, + apb1: apb1_freq, + apb2: apb2_freq, + apb1_tim: apb1_tim_freq, + apb2_tim: apb2_tim_freq, + rtc, + }); +} diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs deleted file mode 100644 index e445a716..00000000 --- a/embassy-stm32/src/rcc/l1.rs +++ /dev/null @@ -1,279 +0,0 @@ -use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; -use crate::pac::{FLASH, RCC}; -use crate::rcc::{set_freqs, Clocks}; -use crate::time::Hertz; - -/// HSI speed -pub const HSI_FREQ: Hertz = Hertz(16_000_000); - -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -/// System clock mux source -#[derive(Clone, Copy)] -pub enum ClockSrc { - MSI(MSIRange), - PLL(PLLSource, PLLMul, PLLDiv), - HSE(Hertz), - HSI, -} - -/// MSI Clock Range -/// -/// These ranges control the frequency of the MSI. Internally, these ranges map -/// to the `MSIRANGE` bits in the `RCC_ICSCR` register. -#[derive(Clone, Copy)] -pub enum MSIRange { - /// Around 65.536 kHz - Range0, - /// Around 131.072 kHz - Range1, - /// Around 262.144 kHz - Range2, - /// Around 524.288 kHz - Range3, - /// Around 1.048 MHz - Range4, - /// Around 2.097 MHz (reset value) - Range5, - /// Around 4.194 MHz - Range6, -} - -impl Default for MSIRange { - fn default() -> MSIRange { - MSIRange::Range5 - } -} - -/// PLL divider -#[derive(Clone, Copy)] -pub enum PLLDiv { - Div2, - Div3, - Div4, -} - -/// PLL multiplier -#[derive(Clone, Copy)] -pub enum PLLMul { - Mul3, - Mul4, - Mul6, - Mul8, - Mul12, - Mul16, - Mul24, - Mul32, - Mul48, -} - -/// PLL clock input source -#[derive(Clone, Copy)] -pub enum PLLSource { - HSI, - HSE(Hertz), -} - -impl From for Pllmul { - fn from(val: PLLMul) -> Pllmul { - match val { - PLLMul::Mul3 => Pllmul::MUL3, - PLLMul::Mul4 => Pllmul::MUL4, - PLLMul::Mul6 => Pllmul::MUL6, - PLLMul::Mul8 => Pllmul::MUL8, - PLLMul::Mul12 => Pllmul::MUL12, - PLLMul::Mul16 => Pllmul::MUL16, - PLLMul::Mul24 => Pllmul::MUL24, - PLLMul::Mul32 => Pllmul::MUL32, - PLLMul::Mul48 => Pllmul::MUL48, - } - } -} - -impl From for Plldiv { - fn from(val: PLLDiv) -> Plldiv { - match val { - PLLDiv::Div2 => Plldiv::DIV2, - PLLDiv::Div3 => Plldiv::DIV3, - PLLDiv::Div4 => Plldiv::DIV4, - } - } -} - -impl From for Pllsrc { - fn from(val: PLLSource) -> Pllsrc { - match val { - PLLSource::HSI => Pllsrc::HSI, - PLLSource::HSE(_) => Pllsrc::HSE, - } - } -} - -impl From for Msirange { - fn from(val: MSIRange) -> Msirange { - match val { - MSIRange::Range0 => Msirange::RANGE0, - MSIRange::Range1 => Msirange::RANGE1, - MSIRange::Range2 => Msirange::RANGE2, - MSIRange::Range3 => Msirange::RANGE3, - MSIRange::Range4 => Msirange::RANGE4, - MSIRange::Range5 => Msirange::RANGE5, - MSIRange::Range6 => Msirange::RANGE6, - } - } -} - -/// Clocks configutation -pub struct Config { - pub mux: ClockSrc, - pub ahb_pre: AHBPrescaler, - pub apb1_pre: APBPrescaler, - pub apb2_pre: APBPrescaler, -} - -impl Default for Config { - #[inline] - fn default() -> Config { - Config { - mux: ClockSrc::MSI(MSIRange::default()), - ahb_pre: AHBPrescaler::DIV1, - apb1_pre: APBPrescaler::DIV1, - apb2_pre: APBPrescaler::DIV1, - } - } -} - -pub(crate) unsafe fn init(config: Config) { - let (sys_clk, sw) = match config.mux { - ClockSrc::MSI(range) => { - // Set MSI range - RCC.icscr().write(|w| w.set_msirange(range.into())); - - // Enable MSI - RCC.cr().write(|w| w.set_msion(true)); - while !RCC.cr().read().msirdy() {} - - let freq = 32_768 * (1 << (range as u8 + 1)); - (freq, Sw::MSI) - } - ClockSrc::HSI => { - // Enable HSI - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - (HSI_FREQ.0, Sw::HSI) - } - ClockSrc::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - - (freq.0, Sw::HSE) - } - ClockSrc::PLL(src, mul, div) => { - let freq = match src { - PLLSource::HSE(freq) => { - // Enable HSE - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - freq.0 - } - PLLSource::HSI => { - // Enable HSI - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - HSI_FREQ.0 - } - }; - - // Disable PLL - RCC.cr().modify(|w| w.set_pllon(false)); - while RCC.cr().read().pllrdy() {} - - let freq = match mul { - PLLMul::Mul3 => freq * 3, - PLLMul::Mul4 => freq * 4, - PLLMul::Mul6 => freq * 6, - PLLMul::Mul8 => freq * 8, - PLLMul::Mul12 => freq * 12, - PLLMul::Mul16 => freq * 16, - PLLMul::Mul24 => freq * 24, - PLLMul::Mul32 => freq * 32, - PLLMul::Mul48 => freq * 48, - }; - - let freq = match div { - PLLDiv::Div2 => freq / 2, - PLLDiv::Div3 => freq / 3, - PLLDiv::Div4 => freq / 4, - }; - assert!(freq <= 32_000_000); - - RCC.cfgr().write(move |w| { - w.set_pllmul(mul.into()); - w.set_plldiv(div.into()); - w.set_pllsrc(src.into()); - }); - - // Enable PLL - RCC.cr().modify(|w| w.set_pllon(true)); - while !RCC.cr().read().pllrdy() {} - - (freq, Sw::PLL) - } - }; - - // Set flash 64-bit access, prefetch and wait states - if sys_clk >= 16_000_000 { - FLASH.acr().write(|w| w.set_acc64(true)); - FLASH.acr().modify(|w| w.set_prften(true)); - FLASH.acr().modify(|w| w.set_latency(true)); - } - - RCC.cfgr().modify(|w| { - w.set_sw(sw); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); - }); - - let ahb_freq: u32 = match config.ahb_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: Hpre = pre.into(); - let pre = 1 << (pre.to_bits() as u32 - 7); - sys_clk / pre - } - }; - - let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) - } - }; - - let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { - APBPrescaler::DIV1 => (ahb_freq, ahb_freq), - pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) - } - }; - - set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), - }); -} diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 0e35b42e..1e5733d3 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -5,16 +5,12 @@ pub use crate::pac::rcc::vals::{ }; use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -51,9 +47,7 @@ pub struct Config { pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] pub hsi48: bool, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, + pub ls: super::LsConfig, } impl Default for Config { @@ -67,9 +61,7 @@ impl Default for Config { pllsai1: None, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] hsi48: false, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, + ls: Default::default(), } } } @@ -95,23 +87,18 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != Sw::MSI {} } - BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); + let rtc = config.ls.init(); let (sys_clk, sw) = match config.mux { ClockSrc::MSI(range) => { // Enable MSI RCC.cr().write(|w| { - let bits: Msirange = range.into(); - w.set_msirange(bits); + w.set_msirange(range); w.set_msirgsel(true); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} @@ -154,8 +141,7 @@ pub(crate) unsafe fn init(config: Config) { PLLSource::MSI(range) => { // Enable MSI RCC.cr().write(|w| { - let bits: Msirange = range.into(); - w.set_msirange(bits); + w.set_msirange(range); w.set_msipllen(false); // should be turned on if LSE is started w.set_msirgsel(true); w.set_msion(true); @@ -255,9 +241,9 @@ pub(crate) unsafe fn init(config: Config) { RCC.cfgr().modify(|w| { w.set_sw(sw); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); let ahb_freq = sys_clk / config.ahb_pre; @@ -287,6 +273,7 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index d9b3ee28..1f4e0034 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -5,16 +5,12 @@ pub use crate::pac::rcc::vals::{ }; use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; use crate::pac::{FLASH, PWR, RCC}; -use crate::rcc::bd::RtcClockSource; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { @@ -50,9 +46,7 @@ pub struct Config { pub apb2_pre: APBPrescaler, pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, pub hsi48: bool, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, + pub ls: super::LsConfig, } impl Default for Config { @@ -65,9 +59,7 @@ impl Default for Config { apb2_pre: APBPrescaler::DIV1, pllsai1: None, hsi48: false, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, + ls: Default::default(), } } } @@ -93,24 +85,19 @@ pub(crate) unsafe fn init(config: Config) { while RCC.cfgr().read().sws() != Sw::MSI {} } - //BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); + let rtc = config.ls.init(); PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); let (sys_clk, sw) = match config.mux { ClockSrc::MSI(range) => { // Enable MSI RCC.cr().write(|w| { - let bits: Msirange = range.into(); - w.set_msirange(bits); + w.set_msirange(range); w.set_msirgsel(true); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} @@ -153,8 +140,7 @@ pub(crate) unsafe fn init(config: Config) { PLLSource::MSI(range) => { // Enable MSI RCC.cr().write(|w| { - let bits: Msirange = range.into(); - w.set_msirange(bits); + w.set_msirange(range); w.set_msipllen(false); // should be turned on if LSE is started w.set_msirgsel(true); w.set_msion(true); @@ -250,9 +236,9 @@ pub(crate) unsafe fn init(config: Config) { RCC.cfgr().modify(|w| { w.set_sw(sw); - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); let ahb_freq = sys_clk / config.ahb_pre; @@ -282,6 +268,7 @@ pub(crate) unsafe fn init(config: Config) { apb2: apb2_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 85583e0f..a70aa6f1 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -2,11 +2,11 @@ use core::mem::MaybeUninit; -pub use crate::rcc::bd::RtcClockSource; use crate::time::Hertz; -pub(crate) mod bd; +mod bd; mod mco; +pub use bd::*; pub use mco::*; #[cfg_attr(rcc_f0, path = "f0.rs")] @@ -19,8 +19,7 @@ pub use mco::*; #[cfg_attr(rcc_g0, path = "g0.rs")] #[cfg_attr(rcc_g4, path = "g4.rs")] #[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] -#[cfg_attr(rcc_l0, path = "l0.rs")] -#[cfg_attr(rcc_l1, path = "l1.rs")] +#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] #[cfg_attr(rcc_l4, path = "l4.rs")] #[cfg_attr(rcc_l5, path = "l5.rs")] #[cfg_attr(rcc_u5, path = "u5.rs")] @@ -28,9 +27,10 @@ pub use mco::*; #[cfg_attr(rcc_wba, path = "wba.rs")] #[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")] mod _version; -pub use _version::*; #[cfg(feature = "low-power")] -use atomic_polyfill::{AtomicU32, Ordering}; +use core::sync::atomic::{AtomicU32, Ordering}; + +pub use _version::*; // Model Clock Configuration // @@ -133,14 +133,8 @@ pub struct Clocks { #[cfg(stm32f334)] pub hrtim: Option, - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - /// Set only if the lsi or lse is configured, indicates stop is supported pub rtc: Option, - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - /// Set if the hse is configured, indicates stop is not supported - pub rtc_hse: Option, - #[cfg(stm32h5)] pub mux_rcc_pclk1: Option, #[cfg(stm32h5)] @@ -198,14 +192,17 @@ pub fn low_power_ready() -> bool { } #[cfg(feature = "low-power")] -pub(crate) fn clock_refcount_add() { +pub(crate) fn clock_refcount_add(_cs: critical_section::CriticalSection) { // We don't check for overflow because constructing more than u32 peripherals is unlikely - CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); + let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); + CLOCK_REFCOUNT.store(n + 1, Ordering::Relaxed); } #[cfg(feature = "low-power")] -pub(crate) fn clock_refcount_sub() { - assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); +pub(crate) fn clock_refcount_sub(_cs: critical_section::CriticalSection) { + let n = CLOCK_REFCOUNT.load(Ordering::Relaxed); + assert!(n != 0); + CLOCK_REFCOUNT.store(n - 1, Ordering::Relaxed); } /// Frozen clock frequencies @@ -213,14 +210,6 @@ pub(crate) fn clock_refcount_sub() { /// The existence of this value indicates that the clock configuration can no longer be changed static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); -#[cfg(stm32wb)] -/// RCC initialization function -pub(crate) unsafe fn init(config: Config) { - set_freqs(compute_clocks(&config)); - - configure_clocks(&config); -} - /// Sets the clock frequencies /// /// Safety: Sets a mutable global. diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index d8fb1730..68a8d3a3 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -7,9 +7,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - pub use crate::pac::pwr::vals::Vos as VoltageScale; #[derive(Copy, Clone)] @@ -111,7 +108,6 @@ impl Into for ClockSrc { } } -#[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, @@ -125,6 +121,7 @@ pub struct Config { /// /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits. pub voltage_range: VoltageScale, + pub ls: super::LsConfig, } impl Config { @@ -193,6 +190,7 @@ impl Default for Config { apb3_pre: APBPrescaler::DIV1, hsi48: false, voltage_range: VoltageScale::RANGE3, + ls: Default::default(), } } } @@ -434,6 +432,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -444,6 +444,7 @@ pub(crate) unsafe fn init(config: Config) { apb3: apb3_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index ee2a8ae1..181e6bb5 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,118 +1,45 @@ -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; -use crate::rcc::Clocks; -use crate::time::{khz, mhz, Hertz}; - -/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, -/// and with the addition of the init function to configure a system clock. - -/// Only the basic setup using the HSE and HSI clocks are supported as of now. +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource, + Ppre as APBPrescaler, Sw as Sysclk, +}; +use crate::rcc::{set_freqs, Clocks}; +use crate::time::{mhz, Hertz}; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -#[derive(Clone, Copy)] -pub enum HsePrescaler { - NotDivided, - Div2, -} - -impl From for bool { - fn from(value: HsePrescaler) -> Self { - match value { - HsePrescaler::NotDivided => false, - HsePrescaler::Div2 => true, - } - } -} - pub struct Hse { pub prediv: HsePrescaler, pub frequency: Hertz, } -/// System clock mux source -#[derive(Clone, Copy, PartialEq)] -pub enum Sysclk { - /// MSI selected as sysclk - MSI, - /// HSI selected as sysclk - HSI, - /// HSE selected as sysclk - HSE, - /// PLL selected as sysclk - Pll, -} - -impl From for u8 { - fn from(value: Sysclk) -> Self { - match value { - Sysclk::MSI => 0b00, - Sysclk::HSI => 0b01, - Sysclk::HSE => 0b10, - Sysclk::Pll => 0b11, - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum PllSource { - Hsi, - Msi, - Hse, -} - -impl From for u8 { - fn from(value: PllSource) -> Self { - match value { - PllSource::Msi => 0b01, - PllSource::Hsi => 0b10, - PllSource::Hse => 0b11, - } - } -} - -pub enum Pll48Source { - PllSai, - Pll, - Msi, - Hsi48, -} - pub struct PllMux { /// Source clock selection. pub source: PllSource, /// PLL pre-divider (DIVM). Must be between 1 and 63. - pub prediv: u8, + pub prediv: Pllm, } pub struct Pll { /// PLL multiplication factor. Must be between 4 and 512. - pub mul: u16, + pub mul: Plln, /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. /// On PLL1, it must be even (in particular, it cannot be 1.) - pub divp: Option, + pub divp: Option, /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. - pub divq: Option, + pub divq: Option, /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. - pub divr: Option, + pub divr: Option, } /// Clocks configutation pub struct Config { pub hse: Option, - pub lse: Option, - pub lsi: bool, pub sys: Sysclk, pub mux: Option, - pub pll48: Option, - pub rtc: Option, pub pll: Option, pub pllsai: Option, @@ -122,28 +49,28 @@ pub struct Config { pub ahb3_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, + + pub ls: super::LsConfig, } pub const WPAN_DEFAULT: Config = Config { hse: Some(Hse { frequency: mhz(32), - prediv: HsePrescaler::NotDivided, + prediv: HsePrescaler::DIV1, }), - lse: Some(khz(32)), - sys: Sysclk::Pll, + sys: Sysclk::PLL, mux: Some(PllMux { - source: PllSource::Hse, - prediv: 2, + source: PllSource::HSE, + prediv: Pllm::DIV2, }), - pll48: None, - rtc: Some(RtcClockSource::LSE), - lsi: false, + + ls: super::LsConfig::default_lse(), pll: Some(Pll { - mul: 12, - divp: Some(3), - divq: Some(4), - divr: Some(3), + mul: Plln::MUL12, + divp: Some(Pllp::DIV3), + divq: Some(Pllq::DIV4), + divr: Some(Pllr::DIV3), }), pllsai: None, @@ -159,14 +86,12 @@ impl Default for Config { fn default() -> Config { Config { hse: None, - lse: None, - sys: Sysclk::HSI, + sys: Sysclk::HSI16, mux: None, - pll48: None, pll: None, pllsai: None, - rtc: None, - lsi: false, + + ls: Default::default(), ahb1_pre: AHBPrescaler::DIV1, ahb2_pre: AHBPrescaler::DIV1, @@ -177,16 +102,15 @@ impl Default for Config { } } -pub(crate) fn compute_clocks(config: &Config) -> Clocks { - let hse_clk = config.hse.as_ref().map(|hse| match hse.prediv { - HsePrescaler::NotDivided => hse.frequency, - HsePrescaler::Div2 => hse.frequency / 2u32, - }); +#[cfg(stm32wb)] +/// RCC initialization function +pub(crate) unsafe fn init(config: Config) { + let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv); let mux_clk = config.mux.as_ref().map(|pll_mux| { (match pll_mux.source { - PllSource::Hse => hse_clk.unwrap(), - PllSource::Hsi => HSI_FREQ, + PllSource::HSE => hse_clk.unwrap(), + PllSource::HSI16 => HSI_FREQ, _ => unreachable!(), } / pll_mux.prediv) }); @@ -206,44 +130,19 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { let sys_clk = match config.sys { Sysclk::HSE => hse_clk.unwrap(), - Sysclk::HSI => HSI_FREQ, - Sysclk::Pll => pll_r.unwrap(), + Sysclk::HSI16 => HSI_FREQ, + Sysclk::PLL => pll_r.unwrap(), _ => unreachable!(), }; - let ahb1_clk = match config.ahb1_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1u32 << (pre as u32 - 7); - sys_clk / pre - } - }; - - let ahb2_clk = match config.ahb2_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1u32 << (pre as u32 - 7); - sys_clk / pre - } - }; - - let ahb3_clk = match config.ahb3_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1u32 << (pre as u32 - 7); - sys_clk / pre - } - }; + let ahb1_clk = sys_clk / config.ahb1_pre; + let ahb2_clk = sys_clk / config.ahb2_pre; + let ahb3_clk = sys_clk / config.ahb3_pre; let (apb1_clk, apb1_tim_clk) = match config.apb1_pre { APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb1_clk / pre as u32; + let freq = ahb1_clk / pre; (freq, freq * 2u32) } }; @@ -251,43 +150,20 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks { let (apb2_clk, apb2_tim_clk) = match config.apb2_pre { APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb1_clk / pre as u32; + let freq = ahb1_clk / pre; (freq, freq * 2u32) } }; - let rtc_clk = match config.rtc { - Some(RtcClockSource::LSI) => Some(LSI_FREQ), - Some(RtcClockSource::LSE) => Some(config.lse.unwrap()), - _ => None, - }; - - Clocks { - sys: sys_clk, - ahb1: ahb1_clk, - ahb2: ahb2_clk, - ahb3: ahb3_clk, - apb1: apb1_clk, - apb2: apb2_clk, - apb1_tim: apb1_tim_clk, - apb2_tim: apb2_tim_clk, - rtc: rtc_clk, - rtc_hse: None, - } -} - -pub(crate) fn configure_clocks(config: &Config) { let rcc = crate::pac::RCC; let needs_hsi = if let Some(pll_mux) = &config.mux { - pll_mux.source == PllSource::Hsi + pll_mux.source == PllSource::HSI16 } else { false }; - if needs_hsi || config.sys == Sysclk::HSI { + if needs_hsi || config.sys == Sysclk::HSI16 { rcc.cr().modify(|w| { w.set_hsion(true); }); @@ -297,16 +173,12 @@ pub(crate) fn configure_clocks(config: &Config) { rcc.cfgr().modify(|w| w.set_stopwuck(true)); - BackupDomain::configure_ls( - config.rtc.unwrap_or(RtcClockSource::NOCLOCK), - config.lsi, - config.lse.map(|_| Default::default()), - ); + let rtc = config.ls.init(); match &config.hse { Some(hse) => { rcc.cr().modify(|w| { - w.set_hsepre(hse.prediv.into()); + w.set_hsepre(hse.prediv); w.set_hseon(true); }); @@ -328,18 +200,18 @@ pub(crate) fn configure_clocks(config: &Config) { match &config.pll { Some(pll) => { rcc.pllcfgr().modify(|w| { - w.set_plln(pll.mul as u8); + w.set_plln(pll.mul); pll.divp.map(|divp| { w.set_pllpen(true); - w.set_pllp((divp - 1) as u8) + w.set_pllp(divp) }); pll.divq.map(|divq| { w.set_pllqen(true); - w.set_pllq((divq - 1) as u8) + w.set_pllq(divq) }); pll.divr.map(|divr| { - // w.set_pllren(true); - w.set_pllr((divr - 1) as u8); + w.set_pllren(true); + w.set_pllr(divr); }); }); @@ -352,13 +224,25 @@ pub(crate) fn configure_clocks(config: &Config) { rcc.cfgr().modify(|w| { w.set_sw(config.sys.into()); - w.set_hpre(config.ahb1_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb1_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); rcc.extcfgr().modify(|w| { - w.set_c2hpre(config.ahb2_pre.into()); - w.set_shdhpre(config.ahb3_pre.into()); + w.set_c2hpre(config.ahb2_pre); + w.set_shdhpre(config.ahb3_pre); }); + + set_freqs(Clocks { + sys: sys_clk, + ahb1: ahb1_clk, + ahb2: ahb2_clk, + ahb3: ahb3_clk, + apb1: apb1_clk, + apb2: apb2_clk, + apb1_tim: apb1_tim_clk, + apb2_tim: apb2_tim_clk, + rtc, + }) } diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index c5d7ab62..ff5669ec 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs @@ -7,9 +7,6 @@ use crate::time::Hertz; /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; @@ -28,7 +25,7 @@ pub enum PllSrc { impl Into for PllSrc { fn into(self) -> Pllsrc { match self { - PllSrc::HSE(..) => Pllsrc::HSE32, + PllSrc::HSE(..) => Pllsrc::HSE, PllSrc::HSI16 => Pllsrc::HSI16, } } @@ -37,19 +34,19 @@ impl Into for PllSrc { impl Into for ClockSrc { fn into(self) -> Sw { match self { - ClockSrc::HSE(..) => Sw::HSE32, + ClockSrc::HSE(..) => Sw::HSE, ClockSrc::HSI16 => Sw::HSI16, } } } -#[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub apb7_pre: APBPrescaler, + pub ls: super::LsConfig, } impl Default for Config { @@ -60,6 +57,7 @@ impl Default for Config { apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb7_pre: APBPrescaler::DIV1, + ls: Default::default(), } } } @@ -108,13 +106,13 @@ pub(crate) unsafe fn init(config: Config) { }); RCC.cfgr2().modify(|w| { - w.set_hpre(config.ahb_pre.into()); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); RCC.cfgr3().modify(|w| { - w.set_ppre7(config.apb7_pre.into()); + w.set_ppre7(config.apb7_pre); }); let ahb_freq = sys_clk / config.ahb_pre; @@ -140,6 +138,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + let rtc = config.ls.init(); + set_freqs(Clocks { sys: sys_clk, ahb1: ahb_freq, @@ -150,5 +150,6 @@ pub(crate) unsafe fn init(config: Config) { apb7: apb7_freq, apb1_tim: apb1_tim_freq, apb2_tim: apb2_tim_freq, + rtc, }); } diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 7baedfcd..366ca136 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,136 +1,27 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; -use crate::pac::rcc::vals::Adcsel; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; +use crate::pac::rcc::vals::Sw; +pub use crate::pac::rcc::vals::{ + Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr, + Pllsrc as PllSource, Ppre as APBPrescaler, +}; use crate::pac::{FLASH, RCC}; -use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, -/// and with the addition of the init function to configure a system clock. - -/// Only the basic setup using the HSE and HSI clocks are supported as of now. - /// HSI speed pub const HSI_FREQ: Hertz = Hertz(16_000_000); -/// LSI speed -pub const LSI_FREQ: Hertz = Hertz(32_000); - -/// HSE32 speed -pub const HSE32_FREQ: Hertz = Hertz(32_000_000); +/// HSE speed +pub const HSE_FREQ: Hertz = Hertz(32_000_000); /// System clock mux source #[derive(Clone, Copy)] pub enum ClockSrc { MSI(MSIRange), - HSE32, + HSE, HSI16, } -#[derive(Clone, Copy, PartialOrd, PartialEq)] -pub enum MSIRange { - /// Around 100 kHz - Range0, - /// Around 200 kHz - Range1, - /// Around 400 kHz - Range2, - /// Around 800 kHz - Range3, - /// Around 1 MHz - Range4, - /// Around 2 MHz - Range5, - /// Around 4 MHz (reset value) - Range6, - /// Around 8 MHz - Range7, - /// Around 16 MHz - Range8, - /// Around 24 MHz - Range9, - /// Around 32 MHz - Range10, - /// Around 48 MHz - Range11, -} - -impl MSIRange { - fn freq(&self) -> u32 { - match self { - MSIRange::Range0 => 100_000, - MSIRange::Range1 => 200_000, - MSIRange::Range2 => 400_000, - MSIRange::Range3 => 800_000, - MSIRange::Range4 => 1_000_000, - MSIRange::Range5 => 2_000_000, - MSIRange::Range6 => 4_000_000, - MSIRange::Range7 => 8_000_000, - MSIRange::Range8 => 16_000_000, - MSIRange::Range9 => 24_000_000, - MSIRange::Range10 => 32_000_000, - MSIRange::Range11 => 48_000_000, - } - } - - fn vos(&self) -> VoltageScale { - if self > &MSIRange::Range8 { - VoltageScale::RANGE1 - } else { - VoltageScale::RANGE2 - } - } -} - -impl Default for MSIRange { - fn default() -> MSIRange { - MSIRange::Range6 - } -} - -impl Into for MSIRange { - fn into(self) -> u8 { - match self { - MSIRange::Range0 => 0b0000, - MSIRange::Range1 => 0b0001, - MSIRange::Range2 => 0b0010, - MSIRange::Range3 => 0b0011, - MSIRange::Range4 => 0b0100, - MSIRange::Range5 => 0b0101, - MSIRange::Range6 => 0b0110, - MSIRange::Range7 => 0b0111, - MSIRange::Range8 => 0b1000, - MSIRange::Range9 => 0b1001, - MSIRange::Range10 => 0b1010, - MSIRange::Range11 => 0b1011, - } - } -} - -#[derive(Clone, Copy)] -pub enum AdcClockSource { - HSI16, - PLLPCLK, - SYSCLK, -} - -impl AdcClockSource { - pub fn adcsel(&self) -> Adcsel { - match self { - AdcClockSource::HSI16 => Adcsel::HSI16, - AdcClockSource::PLLPCLK => Adcsel::PLLPCLK, - AdcClockSource::SYSCLK => Adcsel::SYSCLK, - } - } -} - -impl Default for AdcClockSource { - fn default() -> Self { - Self::HSI16 - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, @@ -138,91 +29,60 @@ pub struct Config { pub shd_ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, - pub rtc_mux: RtcClockSource, - pub lse: Option, - pub lsi: bool, pub adc_clock_source: AdcClockSource, + pub ls: super::LsConfig, } impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::MSI(MSIRange::default()), + mux: ClockSrc::MSI(MSIRange::RANGE4M), ahb_pre: AHBPrescaler::DIV1, shd_ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, - rtc_mux: RtcClockSource::LSI, - lsi: true, - lse: None, - adc_clock_source: AdcClockSource::default(), + adc_clock_source: AdcClockSource::HSI16, + ls: Default::default(), } } } -#[repr(u8)] -pub enum Lsedrv { - Low = 0, - MediumLow = 1, - MediumHigh = 2, - High = 3, -} - pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw, vos) = match config.mux { - ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::RANGE2), - ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::RANGE1), - ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), + ClockSrc::HSI16 => (HSI_FREQ, Sw::HSI16, VoltageScale::RANGE2), + ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1), + ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)), }; - let ahb_freq: u32 = match config.ahb_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1 << (pre as u32 - 7); - sys_clk / pre - } - }; - - let shd_ahb_freq: u32 = match config.shd_ahb_pre { - AHBPrescaler::DIV1 => sys_clk, - pre => { - let pre: u8 = pre.into(); - let pre = 1 << (pre as u32 - 7); - sys_clk / pre - } - }; + let ahb_freq = sys_clk / config.ahb_pre; + let shd_ahb_freq = sys_clk / config.shd_ahb_pre; let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let pre: u8 = pre.into(); - let pre: u8 = 1 << (pre - 3); - let freq = ahb_freq / pre as u32; - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; // Adjust flash latency - let flash_clk_src_freq: u32 = shd_ahb_freq; + let flash_clk_src_freq = shd_ahb_freq; let ws = match vos { - VoltageScale::RANGE1 => match flash_clk_src_freq { + VoltageScale::RANGE1 => match flash_clk_src_freq.0 { 0..=18_000_000 => 0b000, 18_000_001..=36_000_000 => 0b001, _ => 0b010, }, - VoltageScale::RANGE2 => match flash_clk_src_freq { + VoltageScale::RANGE2 => match flash_clk_src_freq.0 { 0..=6_000_000 => 0b000, 6_000_001..=12_000_000 => 0b001, _ => 0b010, @@ -236,17 +96,14 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} - // Enables the LSI if configured - BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); - match config.mux { ClockSrc::HSI16 => { // Enable HSI16 RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} } - ClockSrc::HSE32 => { - // Enable HSE32 + ClockSrc::HSE => { + // Enable HSE RCC.cr().write(|w| { w.set_hsebyppwr(true); w.set_hseon(true); @@ -258,49 +115,70 @@ pub(crate) unsafe fn init(config: Config) { assert!(!cr.msion() || cr.msirdy()); RCC.cr().write(|w| { w.set_msirgsel(true); - w.set_msirange(range.into()); + w.set_msirange(range); w.set_msion(true); - if config.rtc_mux == RtcClockSource::LSE { - // If LSE is enabled, enable calibration of MSI - w.set_msipllen(true); - } else { - w.set_msipllen(false); - } + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(config.ls.lse.is_some()); }); while !RCC.cr().read().msirdy() {} } } RCC.extcfgr().modify(|w| { - if config.shd_ahb_pre == AHBPrescaler::DIV1 { - w.set_shdhpre(0); - } else { - w.set_shdhpre(config.shd_ahb_pre.into()); - } + w.set_shdhpre(config.shd_ahb_pre); }); RCC.cfgr().modify(|w| { w.set_sw(sw.into()); w.set_hpre(config.ahb_pre); - w.set_ppre1(config.apb1_pre.into()); - w.set_ppre2(config.apb2_pre.into()); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); }); // ADC clock MUX - RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel())); + RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source)); // TODO: switch voltage range + let rtc = config.ls.init(); + set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - ahb2: Hertz(ahb_freq), - ahb3: Hertz(shd_ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb3: Hertz(shd_ahb_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + ahb2: ahb_freq, + ahb3: shd_ahb_freq, + apb1: apb1_freq, + apb2: apb2_freq, + apb3: shd_ahb_freq, + apb1_tim: apb1_tim_freq, + apb2_tim: apb2_tim_freq, + rtc, }); } + +fn msirange_to_hertz(range: MSIRange) -> Hertz { + match range { + MSIRange::RANGE100K => Hertz(100_000), + MSIRange::RANGE200K => Hertz(200_000), + MSIRange::RANGE400K => Hertz(400_000), + MSIRange::RANGE800K => Hertz(800_000), + MSIRange::RANGE1M => Hertz(1_000_000), + MSIRange::RANGE2M => Hertz(2_000_000), + MSIRange::RANGE4M => Hertz(4_000_000), + MSIRange::RANGE8M => Hertz(8_000_000), + MSIRange::RANGE16M => Hertz(16_000_000), + MSIRange::RANGE24M => Hertz(24_000_000), + MSIRange::RANGE32M => Hertz(32_000_000), + MSIRange::RANGE48M => Hertz(48_000_000), + _ => unreachable!(), + } +} + +fn msirange_to_vos(range: MSIRange) -> VoltageScale { + if range.to_bits() > MSIRange::RANGE16M.to_bits() { + VoltageScale::RANGE1 + } else { + VoltageScale::RANGE2 + } +} diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 28dde2eb..cf34d219 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; -pub use crate::rcc::RtcClockSource; use crate::time::Hertz; /// refer to AN4759 to compare features of RTC2 and RTC3 @@ -184,7 +183,7 @@ impl Default for RtcCalibrationCyclePeriod { impl Rtc { pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { - #[cfg(any(rcc_wle, rcc_wl5, rcc_g4, rcc_g0, rtc_v2l4, rtc_v2wb))] + #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] ::enable(); let mut this = Self { @@ -204,19 +203,8 @@ impl Rtc { } fn frequency() -> Hertz { - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab))] let freqs = unsafe { crate::rcc::get_freqs() }; - - // Load the clock frequency from the rcc mod, if supported - #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab))] - match freqs.rtc { - Some(hertz) => hertz, - None => freqs.rtc_hse.unwrap(), - } - - // Assume the default value, if not supported - #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab)))] - Hertz(32_768) + freqs.rtc.unwrap() } /// Acquire a [`RtcTimeProvider`] instance. diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs index 604503e6..a0bc3394 100644 --- a/embassy-stm32/src/time.rs +++ b/embassy-stm32/src/time.rs @@ -77,3 +77,10 @@ impl Div for Hertz { self / (rhs as u32) } } + +impl Div for Hertz { + type Output = u32; + fn div(self, rhs: Hertz) -> Self::Output { + self.0 / rhs.0 + } +} diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 91750241..e88198e6 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -1,9 +1,8 @@ use core::cell::Cell; use core::convert::TryInto; -use core::sync::atomic::{compiler_fence, Ordering}; +use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering}; use core::{mem, ptr}; -use atomic_polyfill::{AtomicU32, AtomicU8}; use critical_section::CriticalSection; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; @@ -229,7 +228,9 @@ impl RtcDriver { fn next_period(&self) { let r = T::regs_gp16(); - let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; + // We only modify the period from the timer interrupt, so we know this can't race. + let period = self.period.load(Ordering::Relaxed) + 1; + self.period.store(period, Ordering::Relaxed); let t = (period as u64) << 15; critical_section::with(move |cs| { @@ -403,18 +404,15 @@ impl Driver for RtcDriver { } unsafe fn allocate_alarm(&self) -> Option { - let id = self.alarm_count.fetch_update(Ordering::AcqRel, Ordering::Acquire, |x| { - if x < ALARM_COUNT as u8 { - Some(x + 1) + critical_section::with(|_| { + let id = self.alarm_count.load(Ordering::Relaxed); + if id < ALARM_COUNT as u8 { + self.alarm_count.store(id + 1, Ordering::Relaxed); + Some(AlarmHandle::new(id)) } else { None } - }); - - match id { - Ok(id) => Some(AlarmHandle::new(id)), - Err(_) => None, - } + }) } fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) { diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 8f034a9d..e4b88d78 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -218,7 +218,6 @@ embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = embedded-hal-async = { version = "=1.0.0-rc.1", optional = true} futures-util = { version = "0.3.17", default-features = false } -atomic-polyfill = "1.0.1" critical-section = "1.1" cfg-if = "1.0.0" heapless = "0.7" diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index ed246a7d..a9286c44 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs @@ -6,7 +6,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::peripherals::ADC1; -use embassy_stm32::rcc::AdcClockSource; +use embassy_stm32::rcc::{AdcClockSource, Adcpres}; use embassy_stm32::time::mhz; use embassy_stm32::{adc, bind_interrupts, Config}; use embassy_time::{Delay, Duration, Timer}; @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) -> ! { config.rcc.hclk = Some(mhz(64)); config.rcc.pclk1 = Some(mhz(32)); config.rcc.pclk2 = Some(mhz(64)); - config.rcc.adc = Some(AdcClockSource::PllDiv1); + config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1)); let mut p = embassy_stm32::init(config); diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index 3fffcfb1..fb5a85bc 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs @@ -7,7 +7,7 @@ use embassy_executor::Spawner; use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::opamp::{OpAmp, OpAmpGain}; use embassy_stm32::peripherals::ADC2; -use embassy_stm32::rcc::AdcClockSource; +use embassy_stm32::rcc::{AdcClockSource, Adcpres}; use embassy_stm32::time::mhz; use embassy_stm32::{adc, bind_interrupts, Config}; use embassy_time::{Delay, Duration, Timer}; @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) -> ! { config.rcc.hclk = Some(mhz(64)); config.rcc.pclk1 = Some(mhz(32)); config.rcc.pclk2 = Some(mhz(64)); - config.rcc.adc = Some(AdcClockSource::PllDiv1); + config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1)); let mut p = embassy_stm32::init(config); diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 16bf5d94..6a1d4b08 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -58,9 +58,8 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/examples/stm32f4/src/bin/rtc.rs b/examples/stm32f4/src/bin/rtc.rs index e3374600..e95ad577 100644 --- a/examples/stm32f4/src/bin/rtc.rs +++ b/examples/stm32f4/src/bin/rtc.rs @@ -5,16 +5,14 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let mut config = Config::default(); - config.rcc.lsi = true; - config.rcc.rtc = Option::Some(RtcClockSource::LSI); + let config = Config::default(); let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index 93c97c8e..7c9ee159 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -59,9 +59,8 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index da9b18a0..30a112b7 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { div_r: Some(PllR::DIV2), }); - config.rcc.adc12_clock_source = AdcClockSource::SysClk; + config.rcc.adc12_clock_source = AdcClockSource::SYSCLK; config.rcc.mux = ClockSrc::PLL; let mut p = embassy_stm32::init(config); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 2f445476..2535c6a6 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -80,9 +80,8 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB15, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index a6603d50..6fbf4344 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -77,9 +77,8 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 596de2f4..09d27cdb 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -78,9 +78,8 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); @@ -106,8 +105,8 @@ async fn main(spawner: Spawner) -> ! { info!("Network task initialized"); - static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new(); - let client = TcpClient::new(&stack, &STATE); + let state: TcpClientState<1, 1024, 1024> = TcpClientState::new(); + let client = TcpClient::new(&stack, &state); loop { let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(10, 42, 0, 1), 8000)); diff --git a/examples/stm32h7/src/bin/rtc.rs b/examples/stm32h7/src/bin/rtc.rs index eeb94073..f2a19af8 100644 --- a/examples/stm32h7/src/bin/rtc.rs +++ b/examples/stm32h7/src/bin/rtc.rs @@ -5,20 +5,18 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::Lse; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; +use embassy_stm32::rcc::LsConfig; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = { - let mut config = Config::default(); - config.rcc.lse = Some(Lse::Oscillator); - config.rcc.rtc_mux = Some(RtcClockSource::LSE); - embassy_stm32::init(config) - }; + let mut config = Config::default(); + config.rcc.ls = LsConfig::default_lse(); + + let p = embassy_stm32::init(config); info!("Hello World!"); let now = NaiveDate::from_ymd_opt(2020, 5, 15) diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index 7e2b8c78..33efc76b 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs @@ -5,7 +5,7 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{self, ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; +use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, PllMul, PllPreDiv, PllRDiv}; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::time::Hertz; use embassy_stm32::Config; @@ -23,8 +23,7 @@ async fn main(_spawner: Spawner) { PllMul::MUL20, None, ); - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc_mux = rcc::RtcClockSource::LSE; + config.rcc.ls = LsConfig::default_lse(); embassy_stm32::init(config) }; info!("Hello World!"); diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 8db89be2..7193d1f1 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -32,7 +32,6 @@ use embedded_io::Write as bWrite; use embedded_io_async::Write; use hal::gpio::{Input, Level, Output, Speed}; use hal::i2c::{self, I2c}; -use hal::rcc::{self}; use hal::rng::{self, Rng}; use hal::{bind_interrupts, exti, pac, peripherals}; use heapless::Vec; @@ -86,7 +85,6 @@ async fn main(spawner: Spawner) { None, ); config.rcc.hsi48 = true; // needed for rng - config.rcc.rtc_mux = rcc::RtcClockSource::LSI; let dp = embassy_stm32::init(config); diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index fb249532..8c789afb 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs @@ -33,8 +33,7 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); - config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; - config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI; + config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; let p = embassy_stm32::init(config); pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)); diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs index 3d8c31ff..19b0d853 100644 --- a/examples/stm32wl/src/bin/lora_p2p_receive.rs +++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs @@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); - config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; + config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; let p = embassy_stm32::init(config); let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs index fbd0b032..85f6a84b 100644 --- a/examples/stm32wl/src/bin/lora_p2p_send.rs +++ b/examples/stm32wl/src/bin/lora_p2p_send.rs @@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); - config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; + config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; let p = embassy_stm32::init(config); let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index 18eeac4f..7c7e8a4e 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -15,8 +15,7 @@ bind_interrupts!(struct Irqs{ #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); - config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; - config.rcc.rtc_mux = embassy_stm32::rcc::RtcClockSource::LSI; + config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; let p = embassy_stm32::init(config); pac::RCC.ccipr().modify(|w| { diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs index 11734e4b..a6bb2801 100644 --- a/examples/stm32wl/src/bin/rtc.rs +++ b/examples/stm32wl/src/bin/rtc.rs @@ -5,9 +5,8 @@ use chrono::{NaiveDate, NaiveDateTime}; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::ClockSrc; -use embassy_stm32::rtc::{Rtc, RtcClockSource, RtcConfig}; -use embassy_stm32::time::Hertz; +use embassy_stm32::rcc::{ClockSrc, LsConfig}; +use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -16,9 +15,8 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let p = { let mut config = Config::default(); - config.rcc.mux = ClockSrc::HSE32; - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc_mux = RtcClockSource::LSE; + config.rcc.mux = ClockSrc::HSE; + config.rcc.ls = LsConfig::default_lse(); embassy_stm32::init(config) }; info!("Hello World!"); diff --git a/examples/stm32wl/src/bin/uart_async.rs b/examples/stm32wl/src/bin/uart_async.rs index 2c9b7c69..44e8f83a 100644 --- a/examples/stm32wl/src/bin/uart_async.rs +++ b/examples/stm32wl/src/bin/uart_async.rs @@ -21,7 +21,7 @@ but can be surely changed for your needs. #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); - config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32; + config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; let p = embassy_stm32::init(config); defmt::info!("Starting system"); diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index ef835eed..a1481c7c 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -10,19 +10,19 @@ stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo -stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo +stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo -stm32h563zi = ["embassy-stm32/stm32h563zi", "eth"] # Nucleo -stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" ] # Nucleo +stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth"] # Nucleo +stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono"] # IoT board stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma"] # Nucleo -stm32l152re = ["embassy-stm32/stm32l152re", "not-gpdma"] # Nucleo -stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "not-gpdma"] # Nucleo -stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "not-gpdma"] # Nucleo +stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"] # Nucleo +stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma"] # Nucleo +stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma"] # Nucleo stm32l552ze = ["embassy-stm32/stm32l552ze", "not-gpdma"] # Nucleo -stm32f767zi = ["embassy-stm32/stm32f767zi", "not-gpdma", "eth"] # Nucleo -stm32f207zg = ["embassy-stm32/stm32f207zg", "not-gpdma", "eth"] # Nucleo -stm32f303ze = ["embassy-stm32/stm32f303ze", "not-gpdma"] # Nucleo +stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth"] # Nucleo +stm32f207zg = ["embassy-stm32/stm32f207zg", "chrono", "not-gpdma", "eth"] # Nucleo +stm32f303ze = ["embassy-stm32/stm32f303ze", "chrono", "not-gpdma"] # Nucleo stm32l496zg = ["embassy-stm32/stm32l496zg", "not-gpdma"] # Nucleo eth = [] diff --git a/tests/stm32/src/bin/eth.rs b/tests/stm32/src/bin/eth.rs index 13919238..6d5e05cd 100644 --- a/tests/stm32/src/bin/eth.rs +++ b/tests/stm32/src/bin/eth.rs @@ -85,9 +85,8 @@ async fn main(spawner: Spawner) { #[cfg(feature = "stm32h563zi")] p.PB15, p.PG11, - GenericSMI::new(), + GenericSMI::new(0), mac_addr, - 0, ); let config = embassy_net::Config::dhcpv4(Default::default()); diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 1f0d630c..46fdbfae 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -10,26 +10,14 @@ use chrono::{NaiveDate, NaiveDateTime}; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_time::{Duration, Timer}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = config(); - - #[cfg(feature = "stm32h755zi")] - { - use embassy_stm32::rcc::Lse; - config.rcc.lse = Some(Lse::Oscillator); - config.rcc.rtc_mux = Some(RtcClockSource::LSE); - } - #[cfg(not(feature = "stm32h755zi"))] - { - use embassy_stm32::time::Hertz; - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc = Some(RtcClockSource::LSE); - } + config.rcc.ls = LsConfig::default_lse(); let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 55c4aa90..929869bc 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs @@ -11,9 +11,8 @@ use common::*; use cortex_m_rt::entry; use embassy_executor::Spawner; use embassy_stm32::low_power::{stop_with_rtc, Executor}; -use embassy_stm32::rcc::RtcClockSource; +use embassy_stm32::rcc::LsConfig; use embassy_stm32::rtc::{Rtc, RtcConfig}; -use embassy_stm32::time::Hertz; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use static_cell::make_static; @@ -49,9 +48,7 @@ async fn async_main(spawner: Spawner) { let _ = config(); let mut config = Config::default(); - - config.rcc.lse = Some(Hertz(32_768)); - config.rcc.rtc = Some(RtcClockSource::LSE); + config.rcc.ls = LsConfig::default_lse(); let p = embassy_stm32::init(config); info!("Hello World!"); diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 79a9b5e8..2bf50079 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -322,8 +322,8 @@ pub fn config() -> Config { config.rcc.mux = ClockSrc::PLL( // 32Mhz clock (16 * 4 / 2) PLLSource::HSI16, - PLLMul::Mul4, - PLLDiv::Div2, + PLLMul::MUL4, + PLLDiv::DIV2, ); } @@ -332,9 +332,9 @@ pub fn config() -> Config { use embassy_stm32::rcc::*; config.rcc.mux = ClockSrc::PLL( // 32Mhz clock (16 * 4 / 2) - PLLSource::HSI, - PLLMul::Mul4, - PLLDiv::Div2, + PLLSource::HSI16, + PLLMul::MUL4, + PLLDiv::DIV2, ); }