From 38e7709a24982231a6a68dca4dddb75eb934c6bf Mon Sep 17 00:00:00 2001 From: Will Glynn Date: Thu, 5 Oct 2023 22:05:05 -0500 Subject: [PATCH 01/13] stm32: u5: implement >55 MHz clock speeds This commit allows STM32U5 devices to operate at 160 MHz. On STM32U5, MSIS can run at 48 MHz and HSE can reach 50 MHz. Faster clocks require using PLL1's R output, though PLL1 can serve other functions besides using the R output for the system clock. This commit extracts a public `PllConfig` struct, primarily to place associated constructors on that type, but also with an eye towards enabling the P and Q outputs in a later commit. STM32U5 PLLs have various frequency requirements on each stage: after the `m` prescaler, after the `n` multiplier, and after the `r` divider. This commit implements the associated checks as assertions. This commit fixes clock calculation and PLL register configuration errors in PLL initialization. STM32U5 has a PWR peripheral which can be configured to push Vcore into different voltage ranges. System clocks exceeding 55 MHz require range 2, and system clocks exceeding 110 MHz require range 1. This commit adds `voltage_range` to `Config` and configures PWR as directed. The voltage range implies different performance limits on various clock signals, including inside a PLL. This commit implements voltage range <-> frequency range checks as assertions, and extracts the otherwise-repeated MSIS, HSI16, and HSE initialization into private methods on `Config`. STM32U5 frequencies above 55 MHz require using the PWR EPOD booster. The EPOD booster requires configuring a second `m` term for PLL1, `mboost`, such that it falls in a particular range. (Recall that >50 MHz cannot be reached without PLL1, so there is no scenario where EPOD is needed but PLL1 is not.) This commit configures and enables the EPOD booster automatically as required. --- embassy-stm32/src/rcc/u5.rs | 360 ++++++++++++++++++------- examples/stm32u5/src/bin/usb_serial.rs | 7 +- 2 files changed, 274 insertions(+), 93 deletions(-) diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index d9a53128..14b8577d 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -1,7 +1,7 @@ -use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; +use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllmboost, Pllrge, Pllsrc, Sw}; pub use super::bus::{AHBPrescaler, APBPrescaler}; -use crate::pac::{FLASH, RCC}; +use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -15,23 +15,86 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; #[derive(Copy, Clone)] pub enum ClockSrc { + /// Use an internal medium speed oscillator (MSIS) as the system clock. MSI(MSIRange), + /// Use the external high speed clock as the system clock. + /// + /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must + /// never exceed 50 MHz. HSE(Hertz), + /// Use the 16 MHz internal high speed oscillator as the system clock. HSI16, - PLL1R(PllSrc, PllM, PllN, PllClkDiv), + /// Use PLL1 as the system clock. + PLL1R(PllConfig), +} + +impl Default for ClockSrc { + fn default() -> Self { + // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9 + ClockSrc::MSI(MSIRange::Range4mhz) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct PllConfig { + /// The clock source for the PLL. + pub source: PllSrc, + /// The PLL prescaler. + /// + /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. + pub m: PllM, + /// The PLL multiplier. + /// + /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 + /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. + pub n: PllN, + /// The divider for the R output. + /// + /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` + /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default + /// `Config { voltage_range }`. + pub r: PllClkDiv, +} + +impl PllConfig { + /// A configuration for HSI16 / 1 * 10 / 1 = 160 MHz + pub const fn hsi16_160mhz() -> Self { + PllConfig { + source: PllSrc::HSI16, + m: PllM::NotDivided, + n: PllN::Mul10, + r: PllClkDiv::NotDivided, + } + } + + /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz + pub const fn msis_160mhz() -> Self { + PllConfig { + source: PllSrc::MSIS(MSIRange::Range48mhz), + m: PllM::Div3, + n: PllN::Mul10, + r: PllClkDiv::NotDivided, + } + } } #[derive(Clone, Copy, Debug)] pub enum PllSrc { - MSI(MSIRange), + /// Use an internal medium speed oscillator as the PLL source. + MSIS(MSIRange), + /// Use the external high speed clock as the system PLL source. + /// + /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must + /// never exceed 50 MHz. HSE(Hertz), + /// Use the 16 MHz internal high speed oscillator as the PLL source. HSI16, } impl Into for PllSrc { fn into(self) -> Pllsrc { match self { - PllSrc::MSI(..) => Pllsrc::MSIS, + PllSrc::MSIS(..) => Pllsrc::MSIS, PllSrc::HSE(..) => Pllsrc::HSE, PllSrc::HSI16 => Pllsrc::HSI16, } @@ -41,57 +104,45 @@ impl Into for PllSrc { seq_macro::seq!(N in 2..=128 { #[derive(Copy, Clone, Debug)] pub enum PllClkDiv { - NotDivided, + NotDivided = 1, #( - Div~N = (N-1), + Div~N = N, )* } impl PllClkDiv { fn to_div(&self) -> u8 { match self { - PllClkDiv::NotDivided => 1, + PllClkDiv::NotDivided => 0, #( - PllClkDiv::Div~N => N + 1, + PllClkDiv::Div~N => N - 1, )* } } } }); -impl Into for PllClkDiv { - fn into(self) -> u8 { - (self as u8) + 1 - } -} - seq_macro::seq!(N in 4..=512 { #[derive(Copy, Clone, Debug)] pub enum PllN { - NotMultiplied, + NotMultiplied = 1, #( - Mul~N = N-1, + Mul~N = N, )* } impl PllN { fn to_mul(&self) -> u16 { match self { - PllN::NotMultiplied => 1, + PllN::NotMultiplied => 0, #( - PllN::Mul~N => N + 1, + PllN::Mul~N => N - 1, )* } } } }); -impl Into for PllN { - fn into(self) -> u16 { - (self as u16) + 1 - } -} - // Pre-division #[derive(Copy, Clone, Debug)] pub enum PllM { @@ -132,6 +183,7 @@ impl Into for ClockSrc { #[derive(Debug, Copy, Clone)] pub enum MSIRange { + /// The 48 MHz MSI speed is unavailable in `VoltageScale::RANGE4`. Range48mhz = 48_000_000, Range24mhz = 24_000_000, Range16mhz = 16_000_000, @@ -179,12 +231,6 @@ impl Into for MSIRange { } } -impl Default for MSIRange { - fn default() -> Self { - MSIRange::Range4mhz - } -} - #[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, @@ -193,103 +239,220 @@ pub struct Config { pub apb2_pre: APBPrescaler, pub apb3_pre: APBPrescaler, pub hsi48: bool, + /// The voltage range influences the maximum clock frequencies for different parts of the + /// device. In particular, system clocks exceeding 110 MHz require `RANGE1`, and system clocks + /// exceeding 55 MHz require at least `RANGE2`. + /// + /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits. + pub voltage_range: VoltageScale, +} + +impl Config { + unsafe fn init_hsi16(&self) -> Hertz { + RCC.cr().write(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + HSI_FREQ + } + + unsafe fn init_hse(&self, frequency: Hertz) -> Hertz { + // Check frequency limits per RM456 § 11.4.10 + match self.voltage_range { + VoltageScale::RANGE1 | VoltageScale::RANGE2 | VoltageScale::RANGE3 => { + assert!(frequency.0 <= 50_000_000); + } + VoltageScale::RANGE4 => { + assert!(frequency.0 <= 25_000_000); + } + } + + // Enable HSE, and wait for it to stabilize + RCC.cr().write(|w| w.set_hseon(true)); + while !RCC.cr().read().hserdy() {} + + frequency + } + + unsafe fn init_msis(&self, range: MSIRange) -> Hertz { + // Check MSI output per RM0456 § 11.4.10 + match self.voltage_range { + VoltageScale::RANGE4 => { + assert!(range as u32 <= 24_000_000); + } + _ => {} + } + + // RM0456 § 11.8.2: spin until MSIS is off or MSIS is ready before setting its range + loop { + let cr = RCC.cr().read(); + if cr.msison() == false || cr.msisrdy() == true { + break; + } + } + + RCC.icscr1().modify(|w| { + let bits: Msirange = range.into(); + w.set_msisrange(bits); + w.set_msirgsel(Msirgsel::RCC_ICSCR1); + }); + RCC.cr().write(|w| { + w.set_msipllen(false); + w.set_msison(true); + }); + while !RCC.cr().read().msisrdy() {} + Hertz(range as u32) + } } impl Default for Config { fn default() -> Self { Self { - mux: ClockSrc::MSI(MSIRange::default()), + mux: ClockSrc::default(), ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, apb3_pre: APBPrescaler::DIV1, hsi48: false, + voltage_range: VoltageScale::RANGE3, } } } pub(crate) unsafe fn init(config: Config) { + // Ensure PWR peripheral clock is enabled + RCC.ahb3enr().modify(|w| { + w.set_pwren(true); + }); + RCC.ahb3enr().read(); // synchronize + + // Set the requested power mode + PWR.vosr().modify(|w| { + w.set_vos(config.voltage_range); + }); + while !PWR.vosr().read().vosrdy() {} + let sys_clk = match config.mux { - ClockSrc::MSI(range) => { - RCC.icscr1().modify(|w| { - let bits: Msirange = range.into(); - w.set_msisrange(bits); - w.set_msirgsel(Msirgsel::RCC_ICSCR1); - }); - RCC.cr().write(|w| { - w.set_msipllen(false); - w.set_msison(true); - }); - while !RCC.cr().read().msisrdy() {} - - range.into() - } - ClockSrc::HSE(freq) => { - RCC.cr().write(|w| w.set_hseon(true)); - while !RCC.cr().read().hserdy() {} - - freq.0 - } - ClockSrc::HSI16 => { - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - HSI_FREQ.0 - } - ClockSrc::PLL1R(src, m, n, div) => { - let freq = match src { - PllSrc::MSI(_) => { - // TODO: enable MSI - MSIRange::default().into() - } - PllSrc::HSE(hertz) => { - // TODO: enable HSE - hertz.0 - } - PllSrc::HSI16 => { - RCC.cr().write(|w| w.set_hsion(true)); - while !RCC.cr().read().hsirdy() {} - - HSI_FREQ.0 - } + ClockSrc::MSI(range) => config.init_msis(range), + ClockSrc::HSE(freq) => config.init_hse(freq), + ClockSrc::HSI16 => config.init_hsi16(), + ClockSrc::PLL1R(pll) => { + // Configure the PLL source + let source_clk = match pll.source { + PllSrc::MSIS(range) => config.init_msis(range), + PllSrc::HSE(hertz) => config.init_hse(hertz), + PllSrc::HSI16 => config.init_hsi16(), }; - // disable + // Calculate the reference clock, which is the source divided by m + let reference_clk = source_clk / (pll.m as u8 as u32 + 1); + + // Check limits per RM0456 § 11.4.6 + assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16)); + + // Calculate the PLL1 VCO clock and PLL1 R output clock + let pll1_clk = reference_clk * (pll.n as u8 as u32); + let pll1r_clk = pll1_clk / (pll.r as u8 as u32); + + // Check system clock per RM0456 § 11.4.9 + assert!(pll1r_clk <= Hertz::mhz(160)); + + // Check PLL clocks per RM0456 § 11.4.10 + match config.voltage_range { + VoltageScale::RANGE1 => { + assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544)); + assert!(pll1r_clk <= Hertz::mhz(208)); + } + VoltageScale::RANGE2 => { + assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544)); + assert!(pll1r_clk <= Hertz::mhz(110)); + } + VoltageScale::RANGE3 => { + assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(330)); + assert!(pll1r_clk <= Hertz::mhz(55)); + } + VoltageScale::RANGE4 => { + panic!("PLL is unavailable in voltage range 4"); + } + } + + // § 10.5.4: if we're targeting >= 55 MHz, we must configure PLL1MBOOST to a prescaler + // value that results in an output between 4 and 16 MHz for the PWR EPOD boost + let mboost = if pll1r_clk >= Hertz::mhz(55) { + // source_clk can be up to 50 MHz, so there's just a few cases: + if source_clk > Hertz::mhz(32) { + // Divide by 4, giving EPOD 8-12.5 MHz + Pllmboost::DIV4 + } else if source_clk > Hertz::mhz(16) { + // Divide by 2, giving EPOD 8-16 MHz + Pllmboost::DIV2 + } else { + // Bypass, giving EPOD 4-16 MHz + Pllmboost::BYPASS + } + } else { + // Nothing to do + Pllmboost::BYPASS + }; + + // Disable the PLL, and wait for it to disable RCC.cr().modify(|w| w.set_pllon(0, false)); while RCC.cr().read().pllrdy(0) {} - let vco = freq * n as u8 as u32; - let pll_ck = vco / (div as u8 as u32 + 1); - + // Configure the PLL RCC.pll1cfgr().write(|w| { - w.set_pllm(m.into()); - w.set_pllsrc(src.into()); + // Configure PLL1 source and prescaler + w.set_pllsrc(pll.source.into()); + w.set_pllm(pll.m.into()); + + // Configure PLL1 input frequncy range + let input_range = if reference_clk <= Hertz::mhz(8) { + Pllrge::FREQ_4TO8MHZ + } else { + Pllrge::FREQ_8TO16MHZ + }; + w.set_pllrge(input_range); + + // Set the prescaler for PWR EPOD + w.set_pllmboost(mboost); + + // Enable PLL1R output w.set_pllren(true); }); + // Configure the PLL divisors RCC.pll1divr().modify(|w| { - w.set_pllr(div.to_div()); - w.set_plln(n.to_mul()); + // Set the VCO multiplier + w.set_plln(pll.n.to_mul()); + // Set the R output divisor + w.set_pllr(pll.r.to_div()); }); - // Enable PLL + // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? + if pll1r_clk >= Hertz::mhz(55) { + // Enable the booster + PWR.vosr().modify(|w| { + w.set_boosten(true); + }); + while !PWR.vosr().read().boostrdy() {} + } + + // Enable the PLL RCC.cr().modify(|w| w.set_pllon(0, true)); while !RCC.cr().read().pllrdy(0) {} - pll_ck + pll1r_clk } - }; + } + .0; if config.hsi48 { RCC.cr().modify(|w| w.set_hsi48on(true)); while !RCC.cr().read().hsi48rdy() {} } - // TODO make configurable - let power_vos = VoltageScale::RANGE3; - - // states and programming delay - let wait_states = match power_vos { + // The clock source is ready + // Calculate and set the flash wait states + let wait_states = match config.voltage_range { // VOS 1 range VCORE 1.26V - 1.40V VoltageScale::RANGE1 => { if sys_clk < 32_000_000 { @@ -335,21 +498,34 @@ pub(crate) unsafe fn init(config: Config) { } } }; - FLASH.acr().modify(|w| { w.set_latency(wait_states); }); + // Switch the system clock source RCC.cfgr1().modify(|w| { w.set_sw(config.mux.into()); }); + // RM0456 § 11.4.9 specifies maximum bus frequencies per voltage range, but the maximum bus + // frequency for each voltage range exactly matches the maximum permitted PLL output frequency. + // Given that: + // + // 1. Any bus frequency can never exceed the system clock frequency; + // 2. We checked the PLL output frequency if we're using it as a system clock; + // 3. The maximum HSE frequencies at each voltage range are lower than the bus limits, and + // we checked the HSE frequency if configured as a system clock; and + // 4. The maximum frequencies from the other clock sources are lower than the lowest bus + // frequency limit + // + // ...then we do not need to perform additional bus-related frequency checks. + + // Configure the bus prescalers 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()); }); - RCC.cfgr3().modify(|w| { w.set_ppre3(config.apb3_pre.into()); }); diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index 9e47fb18..278bd30f 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs @@ -23,7 +23,12 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut config = Config::default(); - config.rcc.mux = ClockSrc::PLL1R(PllSrc::HSI16, PllM::Div2, PllN::Mul10, PllClkDiv::NotDivided); + config.rcc.mux = ClockSrc::PLL1R(PllConfig { + source: PllSrc::HSI16, + m: PllM::Div2, + n: PllN::Mul10, + r: PllClkDiv::NotDivided, + }); //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); config.rcc.hsi48 = true; From 930b8f34953596c550ca47bb35d8ab1d19d8feed Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 6 Oct 2023 17:45:35 +0200 Subject: [PATCH 02/13] Add some uncontroversial derives to Error types --- embassy-embedded-hal/src/flash/partition/mod.rs | 2 +- embassy-rp/src/i2c.rs | 2 +- embassy-rp/src/i2c_slave.rs | 2 +- embassy-stm32/src/dac/mod.rs | 2 +- embassy-stm32/src/i2c/mod.rs | 2 +- embassy-stm32/src/rng.rs | 1 + embassy-stm32/src/sai/mod.rs | 2 +- embassy-stm32/src/spi/mod.rs | 2 +- examples/stm32h7/src/bin/camera.rs | 2 +- examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 2 +- 10 files changed, 10 insertions(+), 9 deletions(-) diff --git a/embassy-embedded-hal/src/flash/partition/mod.rs b/embassy-embedded-hal/src/flash/partition/mod.rs index a12e49ce..42c8a308 100644 --- a/embassy-embedded-hal/src/flash/partition/mod.rs +++ b/embassy-embedded-hal/src/flash/partition/mod.rs @@ -11,7 +11,7 @@ pub use asynch::Partition; pub use blocking::BlockingPartition; /// Partition error -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { /// The requested flash area is outside the partition diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index c358682c..ea077335 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -27,7 +27,7 @@ pub enum AbortReason { } /// I2C error -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { /// I2C abort with error diff --git a/embassy-rp/src/i2c_slave.rs b/embassy-rp/src/i2c_slave.rs index 6136d69c..30e78925 100644 --- a/embassy-rp/src/i2c_slave.rs +++ b/embassy-rp/src/i2c_slave.rs @@ -10,7 +10,7 @@ use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::{pac, Peripheral}; /// I2C error -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Error { diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index a2040b85..7658dce4 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -11,7 +11,7 @@ use crate::{peripherals, Peripheral}; #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Curstom Errors +/// Custom Errors pub enum Error { UnconfiguredChannel, InvalidValue, diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index b35678ed..62d13e90 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -14,7 +14,7 @@ pub use timeout::*; use crate::peripherals; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { Bus, diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 5080cf03..2d7ffc62 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -13,6 +13,7 @@ use crate::{interrupt, pac, peripherals, Peripheral}; static RNG_WAKER: AtomicWaker = AtomicWaker::new(); +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { SeedError, diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 5eecb637..4c3604e5 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -11,7 +11,7 @@ use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { NotATransmitter, diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 14333ba2..bd70342c 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -15,7 +15,7 @@ use crate::rcc::RccPeripheral; use crate::time::Hertz; use crate::{peripherals, Peripheral}; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { Framing, diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index de8ddc29..c22ce4e0 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -184,7 +184,7 @@ mod ov7725 { const CAM_ADDR: u8 = 0x21; - #[derive(Format)] + #[derive(Format, PartialEq, Eq)] pub enum Error { I2c(I2cError), } diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 28752158..ba4a9d23 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -366,7 +366,7 @@ pub struct ADT7422<'d, BUS: I2cBus> { bus: BUS, } -#[derive(Debug, Format)] +#[derive(Debug, Format, PartialEq, Eq)] pub enum Error { I2c(I2cError), Address, From b217d147deab67a988df0d5e58a15eb9260dd6fa Mon Sep 17 00:00:00 2001 From: randi Date: Sat, 7 Oct 2023 11:57:19 +1300 Subject: [PATCH 03/13] Implemented Pwm trait from embedded_hal --- embassy-stm32/src/timer/mod.rs | 28 ++++++++++++++++++++ embassy-stm32/src/timer/simple_pwm.rs | 38 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index d88fbcfd..1e0999ed 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -70,6 +70,16 @@ pub(crate) mod sealed { fn set_autoreload_preload(&mut self, enable: vals::Arpe) { Self::regs().cr1().modify(|r| r.set_arpe(enable)); } + + fn get_frequency(&self) -> Hertz { + let timer_f = Self::frequency(); + + let regs = Self::regs(); + let arr = regs.arr().read().arr(); + let psc = regs.psc().read().psc(); + + timer_f / arr / (psc + 1) + } } pub trait GeneralPurpose16bitInstance: Basic16bitInstance { @@ -103,6 +113,16 @@ pub(crate) mod sealed { regs.egr().write(|r| r.set_ug(true)); regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } + + fn get_frequency(&self) -> Hertz { + let timer_f = Self::frequency(); + + let regs = Self::regs_gp32(); + let arr = regs.arr().read().arr(); + let psc = regs.psc().read().psc(); + + timer_f / arr / (psc + 1) + } } pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { @@ -183,6 +203,10 @@ pub(crate) mod sealed { fn get_max_compare_value(&self) -> u16 { Self::regs_gp16().arr().read().arr() } + + fn get_compare_value(&self, channel: Channel) -> u16 { + Self::regs_gp16().ccr(channel.raw()).read().ccr() + } } pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { @@ -219,6 +243,10 @@ pub(crate) mod sealed { fn get_max_compare_value(&self) -> u32 { Self::regs_gp32().arr().read().arr() } + + fn get_compare_value(&self, channel: Channel) -> u32 { + Self::regs_gp32().ccr(channel.raw()).read().ccr() + } } } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 9e28878b..2b3a069a 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -109,3 +109,41 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { self.inner.set_output_polarity(channel, polarity); } } + +impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { + type Channel = Channel; + type Time = Hertz; + type Duty = u16; + + fn disable(&mut self, channel: Self::Channel) { + self.inner.enable_channel(channel, false); + } + + fn enable(&mut self, channel: Self::Channel) { + self.inner.enable_channel(channel, true); + } + + fn get_period(&self) -> Self::Time { + self.inner.get_frequency().into() + } + + fn get_duty(&self, channel: Self::Channel) -> Self::Duty { + self.inner.get_compare_value(channel) + } + + fn get_max_duty(&self) -> Self::Duty { + self.inner.get_max_compare_value() + 1 + } + + fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { + assert!(duty <= self.get_max_duty()); + self.inner.set_compare_value(channel, duty) + } + + fn set_period

(&mut self, period: P) + where + P: Into, + { + self.inner.set_frequency(period.into()); + } +} From 710874021a783768f5d2d3f712e095eba3bc1627 Mon Sep 17 00:00:00 2001 From: randi Date: Sat, 7 Oct 2023 12:22:31 +1300 Subject: [PATCH 04/13] Implemented Pwm trait for complementary pwm from embedded_hal --- embassy-stm32/src/timer/complementary_pwm.rs | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 4f033e3a..0ab72734 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -122,6 +122,46 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } } +impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { + type Channel = Channel; + type Time = Hertz; + type Duty = u16; + + fn disable(&mut self, channel: Self::Channel) { + self.inner.enable_complementary_channel(channel, false); + self.inner.enable_channel(channel, false); + } + + fn enable(&mut self, channel: Self::Channel) { + self.inner.enable_channel(channel, true); + self.inner.enable_complementary_channel(channel, true); + } + + fn get_period(&self) -> Self::Time { + self.inner.get_frequency().into() + } + + fn get_duty(&self, channel: Self::Channel) -> Self::Duty { + self.inner.get_compare_value(channel) + } + + fn get_max_duty(&self) -> Self::Duty { + self.inner.get_max_compare_value() + 1 + } + + fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { + assert!(duty <= self.get_max_duty()); + self.inner.set_compare_value(channel, duty) + } + + fn set_period

(&mut self, period: P) + where + P: Into, + { + self.inner.set_frequency(period.into()); + } +} + fn compute_dead_time_value(value: u16) -> (Ckd, u8) { /* Dead-time = T_clk * T_dts * T_dtg From 534eb960e9f7c9bb28cbd6ffe10b6cc43fd55ff7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 6 Oct 2023 20:47:31 +0200 Subject: [PATCH 05/13] net: add support for dhcp hostname option. --- ci.sh | 2 +- embassy-net/Cargo.toml | 1 + embassy-net/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 46a48f6b..9038a066 100755 --- a/ci.sh +++ b/ci.sh @@ -36,7 +36,7 @@ cargo batch \ --- build --release --manifest-path embassy-time/Cargo.toml --target thumbv6m-none-eabi --features nightly,defmt,defmt-timestamp-uptime,tick-hz-32_768,generic-queue-8 \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv4,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet \ - --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly,dhcpv4-hostname \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 89582dee..c2fffba8 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -33,6 +33,7 @@ udp = ["smoltcp/socket-udp"] tcp = ["smoltcp/socket-tcp"] dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"] +dhcpv4-hostname = ["dhcpv4"] proto-ipv4 = ["smoltcp/proto-ipv4"] proto-ipv6 = ["smoltcp/proto-ipv6"] medium-ethernet = ["smoltcp/medium-ethernet"] diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 297f0467..ef67935e 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -56,12 +56,22 @@ const LOCAL_PORT_MIN: u16 = 1025; const LOCAL_PORT_MAX: u16 = 65535; #[cfg(feature = "dns")] const MAX_QUERIES: usize = 4; +#[cfg(feature = "dhcpv4-hostname")] +const MAX_HOSTNAME_LEN: usize = 32; /// Memory resources needed for a network stack. pub struct StackResources { sockets: [SocketStorage<'static>; SOCK], #[cfg(feature = "dns")] queries: [Option; MAX_QUERIES], + #[cfg(feature = "dhcpv4-hostname")] + hostname: core::cell::UnsafeCell, +} + +#[cfg(feature = "dhcpv4-hostname")] +struct HostnameResources { + option: smoltcp::wire::DhcpOption<'static>, + data: [u8; MAX_HOSTNAME_LEN], } impl StackResources { @@ -73,6 +83,11 @@ impl StackResources { sockets: [SocketStorage::EMPTY; SOCK], #[cfg(feature = "dns")] queries: [INIT; MAX_QUERIES], + #[cfg(feature = "dhcpv4-hostname")] + hostname: core::cell::UnsafeCell::new(HostnameResources { + option: smoltcp::wire::DhcpOption { kind: 0, data: &[] }, + data: [0; MAX_HOSTNAME_LEN], + }), } } } @@ -104,6 +119,7 @@ pub struct StaticConfigV6 { /// DHCP configuration. #[cfg(feature = "dhcpv4")] #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct DhcpConfig { /// Maximum lease duration. /// @@ -120,6 +136,9 @@ pub struct DhcpConfig { pub server_port: u16, /// Client port. This is almost always 68. Do not change unless you know what you're doing. pub client_port: u16, + /// Our hostname. This will be sent to the DHCP server as Option 12. + #[cfg(feature = "dhcpv4-hostname")] + pub hostname: Option>, } #[cfg(feature = "dhcpv4")] @@ -131,6 +150,8 @@ impl Default for DhcpConfig { ignore_naks: Default::default(), server_port: smoltcp::wire::DHCP_SERVER_PORT, client_port: smoltcp::wire::DHCP_CLIENT_PORT, + #[cfg(feature = "dhcpv4-hostname")] + hostname: None, } } } @@ -232,6 +253,8 @@ struct Inner { dns_socket: SocketHandle, #[cfg(feature = "dns")] dns_waker: WakerRegistration, + #[cfg(feature = "dhcpv4-hostname")] + hostname: &'static mut core::cell::UnsafeCell, } pub(crate) struct SocketStack { @@ -307,6 +330,8 @@ impl Stack { )), #[cfg(feature = "dns")] dns_waker: WakerRegistration::new(), + #[cfg(feature = "dhcpv4-hostname")] + hostname: &mut resources.hostname, }; #[cfg(feature = "proto-ipv4")] @@ -673,6 +698,25 @@ impl Inner { socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); socket.set_ports(c.server_port, c.client_port); socket.set_retry_config(c.retry_config); + + socket.set_outgoing_options(&[]); + #[cfg(feature = "dhcpv4-hostname")] + if let Some(h) = c.hostname { + // safety: we just did set_outgoing_options([]) so we know the socket is no longer holding a reference. + let hostname = unsafe { &mut *self.hostname.get() }; + + // create data + // safety: we know the buffer lives forever, new borrows the StackResources for 'static. + // also we won't modify it until next call to this function. + hostname.data[..h.len()].copy_from_slice(h.as_bytes()); + let data: &[u8] = &hostname.data[..h.len()]; + let data: &'static [u8] = unsafe { core::mem::transmute(data) }; + + // set the option. + hostname.option = smoltcp::wire::DhcpOption { data, kind: 12 }; + socket.set_outgoing_options(core::slice::from_ref(&hostname.option)); + } + socket.reset(); } _ => { From 022d870d616575805ace9b37ea87bae1fd90cb84 Mon Sep 17 00:00:00 2001 From: James Munns Date: Sat, 7 Oct 2023 01:33:43 +0200 Subject: [PATCH 06/13] Add missing derive --- embassy-rp/src/i2c.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index ea077335..77777ad3 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -12,7 +12,7 @@ use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::{interrupt, pac, peripherals, Peripheral}; /// I2C error abort reason -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AbortReason { /// A bus operation was not acknowledged, e.g. due to the addressed device From 9090a78df4c3838ee8fdfd6641f5fea7d8e9906e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 7 Oct 2023 01:33:43 +0200 Subject: [PATCH 07/13] ci: set target dir if not specified. --- ci.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ci.sh b/ci.sh index 9038a066..33222298 100755 --- a/ci.sh +++ b/ci.sh @@ -1,9 +1,12 @@ #!/bin/bash -set -euo pipefail +set -eo pipefail export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_hal_internal=debug,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info +if [[ -z "${CARGO_TARGET_DIR}" ]]; then + export CARGO_TARGET_DIR=target_ci +fi TARGET=$(rustc -vV | sed -n 's|host: ||p') From c6d53e7bce9a9f04b2d479a150c4e1aee1bb4ea8 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 23 Sep 2023 17:34:08 +1200 Subject: [PATCH 08/13] rp2040: move in_ram helper outside of Flash's impl Allow it to be called from other modules. --- embassy-rp/src/flash.rs | 78 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 1c1c2449..8fb5542f 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -131,7 +131,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI let len = to - from; - unsafe { self.in_ram(|| ram_helpers::flash_range_erase(from, len))? }; + unsafe { in_ram(|| ram_helpers::flash_range_erase(from, len))? }; Ok(()) } @@ -156,7 +156,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI let unaligned_offset = offset as usize - start; - unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } + unsafe { in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } } let remaining_len = bytes.len() - start_padding; @@ -174,12 +174,12 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI if bytes.as_ptr() as usize >= 0x2000_0000 { let aligned_data = &bytes[start_padding..end_padding]; - unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data))? } + unsafe { in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data))? } } else { for chunk in bytes[start_padding..end_padding].chunks_exact(PAGE_SIZE) { let mut ram_buf = [0xFF_u8; PAGE_SIZE]; ram_buf.copy_from_slice(chunk); - unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf))? } + unsafe { in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, &ram_buf))? } aligned_offset += PAGE_SIZE; } } @@ -194,47 +194,15 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI let unaligned_offset = end_offset - (PAGE_SIZE - rem_offset); - unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } + unsafe { in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf))? } } Ok(()) } - /// Make sure to uphold the contract points with rp2040-flash. - /// - interrupts must be disabled - /// - DMA must not access flash memory - unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> { - // Make sure we're running on CORE0 - let core_id: u32 = pac::SIO.cpuid().read(); - if core_id != 0 { - return Err(Error::InvalidCore); - } - - // Make sure CORE1 is paused during the entire duration of the RAM function - crate::multicore::pause_core1(); - - critical_section::with(|_| { - // Wait for all DMA channels in flash to finish before ram operation - const SRAM_LOWER: u32 = 0x2000_0000; - for n in 0..crate::dma::CHANNEL_COUNT { - let ch = crate::pac::DMA.ch(n); - while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {} - } - // Wait for completion of any background reads - while pac::XIP_CTRL.stream_ctr().read().0 > 0 {} - - // Run our flash operation in RAM - operation(); - }); - - // Resume CORE1 execution - crate::multicore::resume_core1(); - Ok(()) - } - /// Read SPI flash unique ID pub fn blocking_unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> { - unsafe { self.in_ram(|| ram_helpers::flash_unique_id(uid))? }; + unsafe { in_ram(|| ram_helpers::flash_unique_id(uid))? }; Ok(()) } @@ -242,7 +210,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI pub fn blocking_jedec_id(&mut self) -> Result { let mut jedec = None; unsafe { - self.in_ram(|| { + in_ram(|| { jedec.replace(ram_helpers::flash_jedec_id()); })?; }; @@ -871,6 +839,38 @@ mod ram_helpers { } } +/// Make sure to uphold the contract points with rp2040-flash. +/// - interrupts must be disabled +/// - DMA must not access flash memory +pub(crate) unsafe fn in_ram(operation: impl FnOnce()) -> Result<(), Error> { + // Make sure we're running on CORE0 + let core_id: u32 = pac::SIO.cpuid().read(); + if core_id != 0 { + return Err(Error::InvalidCore); + } + + // Make sure CORE1 is paused during the entire duration of the RAM function + crate::multicore::pause_core1(); + + critical_section::with(|_| { + // Wait for all DMA channels in flash to finish before ram operation + const SRAM_LOWER: u32 = 0x2000_0000; + for n in 0..crate::dma::CHANNEL_COUNT { + let ch = crate::pac::DMA.ch(n); + while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {} + } + // Wait for completion of any background reads + while pac::XIP_CTRL.stream_ctr().read().0 > 0 {} + + // Run our flash operation in RAM + operation(); + }); + + // Resume CORE1 execution + crate::multicore::resume_core1(); + Ok(()) +} + mod sealed { pub trait Instance {} pub trait Mode {} From 3e054a6f0d3ba018315f7cb7f0a373221e15737a Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 23 Sep 2023 17:34:47 +1200 Subject: [PATCH 09/13] rp2040: implement BOOTSEL button support --- embassy-rp/src/bootsel.rs | 81 +++++++++++++++++++++++++++++++++++++++ embassy-rp/src/lib.rs | 1 + 2 files changed, 82 insertions(+) create mode 100644 embassy-rp/src/bootsel.rs diff --git a/embassy-rp/src/bootsel.rs b/embassy-rp/src/bootsel.rs new file mode 100644 index 00000000..69d620e8 --- /dev/null +++ b/embassy-rp/src/bootsel.rs @@ -0,0 +1,81 @@ +//! Boot Select button +//! +//! The RP2040 rom supports a BOOTSEL button that is used to enter the USB bootloader +//! if held during reset. To avoid wasting GPIO pins, the button is multiplexed onto +//! the CS pin of the QSPI flash, but that makes it somewhat expensive and complicated +//! to utilize outside of the rom's bootloader. +//! +//! This module provides functionality to poll BOOTSEL from an embassy application. + +use crate::flash::in_ram; + +/// Polls the BOOTSEL button. Returns true if the button is pressed. +/// +/// Polling isn't cheap, as this function waits for core 1 to finish it's current +/// task and for any DMAs from flash to complete +pub fn poll_bootsel() -> bool { + let mut cs_status = Default::default(); + + unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0"); + + // bootsel is active low, so invert + !cs_status.infrompad() +} + +mod ram_helpers { + use rp_pac::io::regs::GpioStatus; + + /// Temporally reconfigures the CS gpio and returns the GpioStatus. + + /// This function runs from RAM so it can disable flash XIP. + /// + /// # Safety + /// + /// The caller must ensure flash is idle and will remain idle. + /// This function must live in ram. It uses inline asm to avoid any + /// potential calls to ABI functions that might be in flash. + #[inline(never)] + #[link_section = ".data.ram_func"] + #[cfg(target_arch = "arm")] + pub unsafe fn read_cs_status() -> GpioStatus { + let result: u32; + + // Magic value, used as both OEOVER::DISABLE and delay loop counter + let magic = 0x2000; + + core::arch::asm!( + ".equiv GPIO_STATUS, 0x0", + ".equiv GPIO_CTRL, 0x4", + + "ldr {orig_ctrl}, [{cs_gpio}, $GPIO_CTRL]", + + // The BOOTSEL pulls the flash's CS line low though a 1K resistor. + // this is weak enough to avoid disrupting normal operation. + // But, if we disable CS's output drive and allow it to float... + "str {val}, [{cs_gpio}, $GPIO_CTRL]", + + // ...then wait for the state to settle... + "1:", // ~4000 cycle delay loop + "subs {val}, #8", + "bne 1b", + + // ...we can read the current state of bootsel + "ldr {val}, [{cs_gpio}, $GPIO_STATUS]", + + // Finally, restore CS to normal operation so XIP can continue + "str {orig_ctrl}, [{cs_gpio}, $GPIO_CTRL]", + + cs_gpio = in(reg) rp_pac::IO_QSPI.gpio(1).as_ptr(), + orig_ctrl = out(reg) _, + val = inout(reg) magic => result, + options(nostack), + ); + + core::mem::transmute(result) + } + + #[cfg(not(target_arch = "arm"))] + pub unsafe fn read_cs_status() -> GpioStatus { + unimplemented!() + } +} diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index e8f818bc..fb918920 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -10,6 +10,7 @@ mod critical_section_impl; mod intrinsics; pub mod adc; +pub mod bootsel; pub mod clocks; pub mod dma; pub mod flash; From d4ed8e5779d5e09ea57728a48fc8654d93b786f8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 7 Oct 2023 01:46:57 +0200 Subject: [PATCH 10/13] rp/bootsel: change it to a method on the peripheral. --- embassy-rp/src/bootsel.rs | 20 +++++++++++--------- embassy-rp/src/lib.rs | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/embassy-rp/src/bootsel.rs b/embassy-rp/src/bootsel.rs index 69d620e8..540255ae 100644 --- a/embassy-rp/src/bootsel.rs +++ b/embassy-rp/src/bootsel.rs @@ -9,17 +9,19 @@ use crate::flash::in_ram; -/// Polls the BOOTSEL button. Returns true if the button is pressed. -/// -/// Polling isn't cheap, as this function waits for core 1 to finish it's current -/// task and for any DMAs from flash to complete -pub fn poll_bootsel() -> bool { - let mut cs_status = Default::default(); +impl crate::peripherals::BOOTSEL { + /// Polls the BOOTSEL button. Returns true if the button is pressed. + /// + /// Polling isn't cheap, as this function waits for core 1 to finish it's current + /// task and for any DMAs from flash to complete + pub fn is_pressed(&mut self) -> bool { + let mut cs_status = Default::default(); - unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0"); + unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0"); - // bootsel is active low, so invert - !cs_status.infrompad() + // bootsel is active low, so invert + !cs_status.infrompad() + } } mod ram_helpers { diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index fb918920..2728395b 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -194,6 +194,7 @@ embassy_hal_internal::peripherals! { PIO1, WATCHDOG, + BOOTSEL, } macro_rules! select_bootloader { From b67b179933806f270465dcf5f246c605eba15dd9 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 7 Oct 2023 01:47:25 +0200 Subject: [PATCH 11/13] rp/bootsel: add test. --- tests/rp/src/bin/bootsel.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/rp/src/bin/bootsel.rs diff --git a/tests/rp/src/bin/bootsel.rs b/tests/rp/src/bin/bootsel.rs new file mode 100644 index 00000000..df1ed8d2 --- /dev/null +++ b/tests/rp/src/bin/bootsel.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +teleprobe_meta::target!(b"rpi-pico"); + +use defmt::{assert_eq, *}; +use embassy_executor::Spawner; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + // add some delay to give an attached debug probe time to parse the + // defmt RTT header. Reading that header might touch flash memory, which + // interferes with flash write operations. + // https://github.com/knurling-rs/defmt/pull/683 + Timer::after(Duration::from_millis(10)).await; + + assert_eq!(p.BOOTSEL.is_pressed(), false); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 2e5ab7981ef5d7681be91b0c29f830872c77eeb0 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 8 Oct 2023 18:27:36 -0500 Subject: [PATCH 12/13] stm32: update metapac --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 20c5155a..18010fb9 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,7 +59,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -78,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-a7bf7f02d1e0bc720c24dbb8881677a298890365", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41", default-features = false, features = ["metadata"]} [features] From 6186fe08070c5f497d72586640db287193b41894 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 9 Oct 2023 02:48:22 +0200 Subject: [PATCH 13/13] stm32/rcc: use PLL enums from PAC. --- embassy-stm32/Cargo.toml | 5 +- embassy-stm32/build.rs | 99 +++++ embassy-stm32/src/rcc/bus.rs | 56 --- embassy-stm32/src/rcc/c0.rs | 2 +- embassy-stm32/src/rcc/f2.rs | 161 +------- embassy-stm32/src/rcc/f4.rs | 10 +- embassy-stm32/src/rcc/f7.rs | 10 +- embassy-stm32/src/rcc/g0.rs | 165 ++------ embassy-stm32/src/rcc/g4.rs | 197 +--------- embassy-stm32/src/rcc/h.rs | 53 ++- embassy-stm32/src/rcc/l0.rs | 2 +- embassy-stm32/src/rcc/l1.rs | 2 +- embassy-stm32/src/rcc/l4.rs | 334 ++++------------- embassy-stm32/src/rcc/l5.rs | 351 ++++++------------ embassy-stm32/src/rcc/mod.rs | 1 - embassy-stm32/src/rcc/u5.rs | 276 ++++---------- embassy-stm32/src/rcc/wb.rs | 2 +- embassy-stm32/src/rcc/wl.rs | 2 +- examples/stm32f2/src/bin/pll.rs | 6 +- examples/stm32g4/src/bin/adc.rs | 6 +- examples/stm32g4/src/bin/pll.rs | 6 +- examples/stm32g4/src/bin/usb_serial.rs | 8 +- examples/stm32h5/src/bin/eth.rs | 12 +- examples/stm32h5/src/bin/usb_serial.rs | 10 +- examples/stm32h7/src/bin/adc.rs | 14 +- examples/stm32h7/src/bin/camera.rs | 8 +- examples/stm32h7/src/bin/dac.rs | 14 +- examples/stm32h7/src/bin/dac_dma.rs | 14 +- examples/stm32h7/src/bin/eth.rs | 6 +- examples/stm32h7/src/bin/eth_client.rs | 6 +- examples/stm32h7/src/bin/fmc.rs | 8 +- .../stm32h7/src/bin/low_level_timer_api.rs | 8 +- examples/stm32h7/src/bin/pwm.rs | 6 +- examples/stm32h7/src/bin/sdmmc.rs | 8 +- examples/stm32h7/src/bin/spi.rs | 8 +- examples/stm32h7/src/bin/spi_dma.rs | 8 +- examples/stm32h7/src/bin/usb_serial.rs | 6 +- examples/stm32l4/src/bin/rng.rs | 10 +- examples/stm32l4/src/bin/rtc.rs | 8 +- .../src/bin/spe_adin1110_http_server.rs | 8 +- examples/stm32l4/src/bin/usb_serial.rs | 2 +- examples/stm32l5/src/bin/rng.rs | 10 +- examples/stm32l5/src/bin/usb_ethernet.rs | 2 +- examples/stm32l5/src/bin/usb_hid_mouse.rs | 2 +- examples/stm32l5/src/bin/usb_serial.rs | 2 +- examples/stm32u5/src/bin/usb_serial.rs | 6 +- tests/stm32/src/common.rs | 42 +-- 47 files changed, 599 insertions(+), 1383 deletions(-) delete mode 100644 embassy-stm32/src/rcc/bus.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 18010fb9..70e8f2e2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,12 +59,11 @@ 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-eecd80c34d4a3035be31404857e6c6e115376f41" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" stm32-fmc = "0.3.0" -seq-macro = "0.3.0" cfg-if = "1.0.0" embedded-io = { version = "0.6.0" } embedded-io-async = { version = "0.6.0", optional = true } @@ -78,7 +77,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-eecd80c34d4a3035be31404857e6c6e115376f41", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 3f85d9e6..643f1b6e 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -893,6 +893,105 @@ fn main() { } } + // ======== + // Generate Div/Mul impls for RCC prescalers/dividers/multipliers. + let rcc_registers = METADATA + .peripherals + .iter() + .filter_map(|p| p.registers.as_ref()) + .find(|r| r.kind == "rcc") + .unwrap() + .ir; + + for e in rcc_registers.enums { + fn is_rcc_name(e: &str) -> bool { + 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, + _ => false, + } + } + + #[derive(Copy, Clone, Debug)] + struct Frac { + num: u32, + denom: u32, + } + + impl Frac { + fn simplify(self) -> Self { + let d = gcd(self.num, self.denom); + Self { + num: self.num / d, + denom: self.denom / d, + } + } + } + + fn gcd(a: u32, b: u32) -> u32 { + if b == 0 { + return a; + } + gcd(b, a % b) + } + + fn parse_num(n: &str) -> Result { + for prefix in ["DIV", "MUL"] { + if let Some(n) = n.strip_prefix(prefix) { + let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32; + let mantissa = n.replace('_', "").parse().map_err(|_| ())?; + let f = Frac { + num: mantissa, + denom: 10u32.pow(exponent), + }; + return Ok(f.simplify()); + } + } + Err(()) + } + + if is_rcc_name(e.name) { + let enum_name = format_ident!("{}", e.name); + let mut muls = Vec::new(); + let mut divs = Vec::new(); + for v in e.variants { + let Ok(val) = parse_num(v.name) else { + panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) + }; + let variant_name = format_ident!("{}", v.name); + let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name); + let num = val.num; + let denom = val.denom; + muls.push(quote!(#variant => self * #num / #denom,)); + divs.push(quote!(#variant => self * #denom / #num,)); + } + + g.extend(quote! { + impl core::ops::Div for crate::time::Hertz { + type Output = crate::time::Hertz; + fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { + match rhs { + #(#divs)* + #[allow(unreachable_patterns)] + _ => unreachable!(), + } + } + } + impl core::ops::Mul for crate::time::Hertz { + type Output = crate::time::Hertz; + fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { + match rhs { + #(#muls)* + #[allow(unreachable_patterns)] + _ => unreachable!(), + } + } + } + }); + } + } + // ======== // Write foreach_foo! macrotables diff --git a/embassy-stm32/src/rcc/bus.rs b/embassy-stm32/src/rcc/bus.rs deleted file mode 100644 index 495cf7fe..00000000 --- a/embassy-stm32/src/rcc/bus.rs +++ /dev/null @@ -1,56 +0,0 @@ -use core::ops::Div; - -#[allow(unused_imports)] -use crate::pac::rcc; -pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; -use crate::time::Hertz; - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: AHBPrescaler) -> Self::Output { - let divisor = match rhs { - AHBPrescaler::DIV1 => 1, - AHBPrescaler::DIV2 => 2, - #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] - AHBPrescaler::DIV3 => 3, - AHBPrescaler::DIV4 => 4, - #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] - AHBPrescaler::DIV5 => 5, - #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] - AHBPrescaler::DIV6 => 6, - AHBPrescaler::DIV8 => 8, - #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] - AHBPrescaler::DIV10 => 10, - AHBPrescaler::DIV16 => 16, - #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] - AHBPrescaler::DIV32 => 32, - #[cfg(not(rcc_wba))] - AHBPrescaler::DIV64 => 64, - #[cfg(not(rcc_wba))] - AHBPrescaler::DIV128 => 128, - #[cfg(not(rcc_wba))] - AHBPrescaler::DIV256 => 256, - #[cfg(not(rcc_wba))] - AHBPrescaler::DIV512 => 512, - _ => unreachable!(), - }; - Hertz(self.0 / divisor) - } -} - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: APBPrescaler) -> Self::Output { - let divisor = match rhs { - APBPrescaler::DIV1 => 1, - APBPrescaler::DIV2 => 2, - APBPrescaler::DIV4 => 4, - APBPrescaler::DIV8 => 8, - APBPrescaler::DIV16 => 16, - _ => unreachable!(), - }; - Hertz(self.0 / divisor) - } -} diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 8f45e7c0..efa56de7 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -1,5 +1,5 @@ -pub use super::bus::{AHBPrescaler, APBPrescaler}; 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::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 44de5bf1..07b816bf 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -1,9 +1,9 @@ -use core::convert::TryFrom; -use core::ops::{Div, Mul}; - -pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; +use crate::pac::rcc::vals::Sw; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc, + Ppre as APBPrescaler, +}; use crate::pac::{FLASH, RCC}; use crate::rcc::bd::BackupDomain; use crate::rcc::{set_freqs, Clocks}; @@ -43,17 +43,17 @@ pub enum HSESrc { pub struct PLLConfig { pub pre_div: PLLPreDiv, pub mul: PLLMul, - pub main_div: PLLMainDiv, - pub pll48_div: PLL48Div, + pub p_div: PLLPDiv, + pub q_div: PLLQDiv, } impl Default for PLLConfig { fn default() -> Self { PLLConfig { - pre_div: PLLPreDiv(16), - mul: PLLMul(192), - main_div: PLLMainDiv::Div2, - pll48_div: PLL48Div(4), + pre_div: PLLPreDiv::DIV16, + mul: PLLMul::MUL192, + p_div: PLLPDiv::DIV2, + q_div: PLLQDiv::DIV4, } } } @@ -61,9 +61,9 @@ impl Default for PLLConfig { impl PLLConfig { pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { let in_freq = src_freq / self.pre_div; - let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32); - let main_freq = vco_freq / self.main_div; - let pll48_freq = vco_freq / self.pll48_div; + let vco_freq = src_freq / self.pre_div * self.mul; + let main_freq = vco_freq / self.p_div; + let pll48_freq = vco_freq / self.q_div; PLLClocks { in_freq, vco_freq, @@ -72,129 +72,6 @@ impl PLLConfig { } } } - -/// Clock source for both main PLL and PLLI2S -#[derive(Clone, Copy, PartialEq)] -pub enum PLLSrc { - HSE, - HSI, -} - -impl Into for PLLSrc { - fn into(self) -> Pllsrc { - match self { - PLLSrc::HSE => Pllsrc::HSE, - PLLSrc::HSI => Pllsrc::HSI, - } - } -} - -/// Division factor for both main PLL and PLLI2S -#[derive(Clone, Copy, PartialEq)] -#[repr(transparent)] -pub struct PLLPreDiv(u8); - -impl TryFrom for PLLPreDiv { - type Error = &'static str; - - fn try_from(value: u8) -> Result { - match value { - 2..=63 => Ok(PLLPreDiv(value)), - _ => Err("PLLPreDiv must be within range 2..=63"), - } - } -} - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: PLLPreDiv) -> Self::Output { - Hertz(self.0 / u32::from(rhs.0)) - } -} - -/// Multiplication factor for main PLL -#[derive(Clone, Copy, PartialEq)] -#[repr(transparent)] -pub struct PLLMul(u16); - -impl Mul for Hertz { - type Output = Hertz; - - fn mul(self, rhs: PLLMul) -> Self::Output { - Hertz(self.0 * u32::from(rhs.0)) - } -} - -impl TryFrom for PLLMul { - type Error = &'static str; - - fn try_from(value: u16) -> Result { - match value { - 192..=432 => Ok(PLLMul(value)), - _ => Err("PLLMul must be within range 192..=432"), - } - } -} - -/// PLL division factor for the main system clock -#[derive(Clone, Copy, PartialEq)] -pub enum PLLMainDiv { - Div2, - Div4, - Div6, - Div8, -} - -impl Into for PLLMainDiv { - fn into(self) -> Pllp { - match self { - PLLMainDiv::Div2 => Pllp::DIV2, - PLLMainDiv::Div4 => Pllp::DIV4, - PLLMainDiv::Div6 => Pllp::DIV6, - PLLMainDiv::Div8 => Pllp::DIV8, - } - } -} - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: PLLMainDiv) -> Self::Output { - let divisor = match rhs { - PLLMainDiv::Div2 => 2, - PLLMainDiv::Div4 => 4, - PLLMainDiv::Div6 => 6, - PLLMainDiv::Div8 => 8, - }; - Hertz(self.0 / divisor) - } -} - -/// PLL division factor for USB OTG FS / SDIO / RNG -#[derive(Clone, Copy, PartialEq)] -#[repr(transparent)] -pub struct PLL48Div(u8); - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: PLL48Div) -> Self::Output { - Hertz(self.0 / u32::from(rhs.0)) - } -} - -impl TryFrom for PLL48Div { - type Error = &'static str; - - fn try_from(value: u8) -> Result { - match value { - 2..=15 => Ok(PLL48Div(value)), - _ => Err("PLL48Div must be within range 2..=15"), - } - } -} - #[derive(Clone, Copy, PartialEq)] pub struct PLLClocks { pub in_freq: Hertz, @@ -367,11 +244,11 @@ pub(crate) unsafe fn init(config: Config) { assert!(pll_clocks.pll48_freq <= Hertz(48_000_000)); RCC.pllcfgr().write(|w| { - w.set_pllsrc(config.pll_mux.into()); - w.set_pllm(config.pll.pre_div.0); - w.set_plln(config.pll.mul.0); - w.set_pllp(config.pll.main_div.into()); - w.set_pllq(config.pll.pll48_div.0); + w.set_pllsrc(config.pll_mux); + w.set_pllm(config.pll.pre_div); + w.set_plln(config.pll.mul); + w.set_pllp(config.pll.p_div); + w.set_pllq(config.pll.q_div); }); let (sys_clk, sw) = match config.mux { diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ad106ce3..754a0d57 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -1,3 +1,5 @@ +use stm32_metapac::rcc::vals::{Pllm, Plln, Pllq, Pllr}; + use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::bd::{BackupDomain, RtcClockSource}; @@ -170,12 +172,12 @@ fn setup_pll( let real_pll48clk = vco_in * plln / pllq; RCC.pllcfgr().modify(|w| { - w.set_pllm(pllm as u8); - w.set_plln(plln as u16); + w.set_pllm(Pllm::from_bits(pllm as u8)); + w.set_plln(Plln::from_bits(plln as u16)); w.set_pllp(Pllp::from_bits(pllp as u8)); - w.set_pllq(pllq as u8); + w.set_pllq(Pllq::from_bits(pllq as u8)); w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); - w.set_pllr(0); + w.set_pllr(Pllr::from_bits(0)); }); let real_pllsysclk = vco_in * plln / sysclk_div; diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index f32559e2..565f6aa9 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -1,5 +1,5 @@ use crate::pac::pwr::vals::Vos; -use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; +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}; @@ -29,8 +29,6 @@ pub struct Config { } fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bool) -> PllResults { - use crate::pac::rcc::vals::{Pllp, Pllsrc}; - let sysclk = pllsysclk.unwrap_or(pllsrcclk); if pllsysclk.is_none() && !pll48clk { RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8))); @@ -84,10 +82,10 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, pll48clk: bo let real_pll48clk = vco_in * plln / pllq; RCC.pllcfgr().modify(|w| { - w.set_pllm(pllm as u8); - w.set_plln(plln as u16); + w.set_pllm(Pllm::from_bits(pllm as u8)); + w.set_plln(Plln::from_bits(plln as u16)); w.set_pllp(Pllp::from_bits(pllp as u8)); - w.set_pllq(pllq as u8); + w.set_pllq(Pllq::from_bits(pllq as u8)); w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); }); diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 7f0a2c7f..5ac40911 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -1,6 +1,6 @@ -pub use super::bus::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; +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::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -60,15 +60,15 @@ pub struct PllConfig { /// The initial divisor of that clock signal pub m: Pllm, /// The PLL VCO multiplier, which must be in the range `8..=86`. - pub n: u8, + pub n: Plln, /// The final divisor for `PLLRCLK` output which drives the system clock pub r: Pllr, /// The divisor for the `PLLQCLK` output, if desired - pub q: Option, + pub q: Option, /// The divisor for the `PLLPCLK` output, if desired - pub p: Option, + pub p: Option, } impl Default for PllConfig { @@ -77,9 +77,9 @@ impl Default for PllConfig { // HSI16 / 1 * 8 / 2 = 64 MHz PllConfig { source: PllSrc::HSI16, - m: Pllm::Div1, - n: 8, - r: Pllr::Div2, + m: Pllm::DIV1, + n: Plln::MUL8, + r: Pllr::DIV2, q: None, p: None, } @@ -92,87 +92,6 @@ pub enum PllSrc { HSE(Hertz), } -#[derive(Clone, Copy)] -pub enum Pllm { - Div1, - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, -} - -impl From for u8 { - fn from(v: Pllm) -> Self { - match v { - Pllm::Div1 => 0b000, - Pllm::Div2 => 0b001, - Pllm::Div3 => 0b010, - Pllm::Div4 => 0b011, - Pllm::Div5 => 0b100, - Pllm::Div6 => 0b101, - Pllm::Div7 => 0b110, - Pllm::Div8 => 0b111, - } - } -} - -impl From for u32 { - fn from(v: Pllm) -> Self { - match v { - Pllm::Div1 => 1, - Pllm::Div2 => 2, - Pllm::Div3 => 3, - Pllm::Div4 => 4, - Pllm::Div5 => 5, - Pllm::Div6 => 6, - Pllm::Div7 => 7, - Pllm::Div8 => 8, - } - } -} - -#[derive(Clone, Copy)] -pub enum Pllr { - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, -} - -impl From for u8 { - fn from(v: Pllr) -> Self { - match v { - Pllr::Div2 => 0b000, - Pllr::Div3 => 0b001, - Pllr::Div4 => 0b010, - Pllr::Div5 => 0b011, - Pllr::Div6 => 0b101, - Pllr::Div7 => 0b110, - Pllr::Div8 => 0b111, - } - } -} - -impl From for u32 { - fn from(v: Pllr) -> Self { - match v { - Pllr::Div2 => 2, - Pllr::Div3 => 3, - Pllr::Div4 => 4, - Pllr::Div5 => 5, - Pllr::Div6 => 6, - Pllr::Div7 => 7, - Pllr::Div8 => 8, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, @@ -194,29 +113,28 @@ impl Default for Config { } impl PllConfig { - pub(crate) fn init(self) -> u32 { - assert!(self.n >= 8 && self.n <= 86); + pub(crate) fn init(self) -> Hertz { let (src, input_freq) = match self.source { - PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), - PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq.0), + PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ), + PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq), }; - let m_freq = input_freq / u32::from(self.m); + let m_freq = input_freq / self.m; // RM0454 § 5.4.4: // > Caution: The software must set these bits so that the PLL input frequency after the // > /M divider is between 2.66 and 16 MHz. - debug_assert!(m_freq >= 2_660_000 && m_freq <= 16_000_000); + debug_assert!(m_freq.0 >= 2_660_000 && m_freq.0 <= 16_000_000); let n_freq = m_freq * self.n as u32; // RM0454 § 5.4.4: // > Caution: The software must set these bits so that the VCO output frequency is between // > 64 and 344 MHz. - debug_assert!(n_freq >= 64_000_000 && n_freq <= 344_000_000); + debug_assert!(n_freq.0 >= 64_000_000 && n_freq.0 <= 344_000_000); - let r_freq = n_freq / u32::from(self.r); + let r_freq = n_freq / self.r; // RM0454 § 5.4.4: // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock. - debug_assert!(r_freq <= 64_000_000); + debug_assert!(r_freq.0 <= 64_000_000); // RM0454 § 5.2.3: // > To modify the PLL configuration, proceed as follows: @@ -239,25 +157,16 @@ impl PllConfig { } } - // Configure PLLSYSCFGR - RCC.pllsyscfgr().modify(|w| { - w.set_pllr(u8::from(self.r)); + // Configure PLLCFGR + RCC.pllcfgr().modify(|w| { + w.set_pllr(self.r); w.set_pllren(false); - - if let Some(q) = self.q { - w.set_pllq(u8::from(q)); - } + w.set_pllq(self.q.unwrap_or(Pllq::DIV2)); w.set_pllqen(false); - - if let Some(p) = self.p { - w.set_pllp(u8::from(p)); - } + w.set_pllp(self.p.unwrap_or(Pllp::DIV2)); w.set_pllpen(false); - w.set_plln(self.n); - - w.set_pllm(self.m as u8); - + w.set_pllm(self.m); w.set_pllsrc(src) }); @@ -269,7 +178,7 @@ impl PllConfig { // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL // > configuration register (RCC_PLLCFGR). - RCC.pllsyscfgr().modify(|w| { + RCC.pllcfgr().modify(|w| { // We'll use R for system clock, so enable that unconditionally w.set_pllren(true); @@ -293,14 +202,14 @@ pub(crate) unsafe fn init(config: Config) { }); 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::PLL(pll) => { let freq = pll.init(); @@ -310,15 +219,15 @@ pub(crate) unsafe fn init(config: Config) { // Enable LSI RCC.csr().write(|w| w.set_lsion(true)); while !RCC.csr().read().lsirdy() {} - (LSI_FREQ.0, Sw::LSI) + (LSI_FREQ, Sw::LSI) } }; // 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.0 <= 24_000_000 { Latency::WS0 - } else if sys_clk <= 48_000_000 { + } else if sys_clk.0 <= 48_000_000 { Latency::WS1 } else { Latency::WS2 @@ -374,27 +283,25 @@ pub(crate) unsafe fn init(config: Config) { FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); } - let ahb_freq = Hertz(sys_clk) / config.ahb_pre; + let ahb_freq = sys_clk / config.ahb_pre; let (apb_freq, apb_tim_freq) = match config.apb_pre { - APBPrescaler::DIV1 => (ahb_freq.0, ahb_freq.0), + APBPrescaler::DIV1 => (ahb_freq, ahb_freq), pre => { - let pre: Ppre = pre.into(); - let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq.0 / pre as u32; - (freq, freq * 2) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; if config.low_power_run { - assert!(sys_clk <= 2_000_000); + assert!(sys_clk.0 <= 2_000_000); PWR.cr1().modify(|w| w.set_lpr(true)); } set_freqs(Clocks { - sys: Hertz(sys_clk), + sys: sys_clk, ahb1: ahb_freq, - apb1: Hertz(apb_freq), - apb1_tim: Hertz(apb_tim_freq), + apb1: apb_freq, + apb1_tim: apb_tim_freq, }); } diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 41bebc91..08ccc5fe 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -2,7 +2,9 @@ use stm32_metapac::flash::vals::Latency; use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; use stm32_metapac::FLASH; -pub use super::bus::{AHBPrescaler, APBPrescaler}; +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, +}; use crate::pac::{PWR, RCC}; use crate::rcc::sealed::RccPeripheral; use crate::rcc::{set_freqs, Clocks}; @@ -61,181 +63,6 @@ impl Into for PllSrc { } } -seq_macro::seq!(P in 2..=31 { - /// Output divider for the PLL P output. - #[derive(Clone, Copy)] - pub enum PllP { - // Note: If PLL P is set to 0 the PLLP bit controls the output division. There does not seem to - // a good reason to do this so the API does not support it. - // Div1 is invalid - #( - Div~P, - )* - } - - impl From for u8 { - /// Returns the register value for the P output divider. - fn from(val: PllP) -> u8 { - match val { - #( - PllP::Div~P => P, - )* - } - } - } -}); - -impl PllP { - /// Returns the numeric value of the P output divider. - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - val as u32 - } -} - -/// Output divider for the PLL Q output. -#[derive(Clone, Copy)] -pub enum PllQ { - Div2, - Div4, - Div6, - Div8, -} - -impl PllQ { - /// Returns the numeric value of the Q output divider. - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - (val as u32 + 1) * 2 - } -} - -impl From for u8 { - /// Returns the register value for the Q output divider. - fn from(val: PllQ) -> u8 { - match val { - PllQ::Div2 => 0b00, - PllQ::Div4 => 0b01, - PllQ::Div6 => 0b10, - PllQ::Div8 => 0b11, - } - } -} - -/// Output divider for the PLL R output. -#[derive(Clone, Copy)] -pub enum PllR { - Div2, - Div4, - Div6, - Div8, -} - -impl PllR { - /// Returns the numeric value of the R output divider. - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - (val as u32 + 1) * 2 - } -} - -impl From for u8 { - /// Returns the register value for the R output divider. - fn from(val: PllR) -> u8 { - match val { - PllR::Div2 => 0b00, - PllR::Div4 => 0b01, - PllR::Div6 => 0b10, - PllR::Div8 => 0b11, - } - } -} - -seq_macro::seq!(N in 8..=127 { - /// Multiplication factor for the PLL VCO input clock. - #[derive(Clone, Copy)] - pub enum PllN { - #( - Mul~N, - )* - } - - impl From for u8 { - /// Returns the register value for the N multiplication factor. - fn from(val: PllN) -> u8 { - match val { - #( - PllN::Mul~N => N, - )* - } - } - } - - impl PllN { - /// Returns the numeric value of the N multiplication factor. - pub fn to_mul(self) -> u32 { - match self { - #( - PllN::Mul~N => N, - )* - } - } - } -}); - -/// PLL Pre-division. This must be set such that the PLL input is between 2.66 MHz and 16 MHz. -#[derive(Copy, Clone)] -pub enum PllM { - Div1, - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, - Div9, - Div10, - Div11, - Div12, - Div13, - Div14, - Div15, - Div16, -} - -impl PllM { - /// Returns the numeric value of the M pre-division. - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - val as u32 + 1 - } -} - -impl From for u8 { - /// Returns the register value for the M pre-division. - fn from(val: PllM) -> u8 { - match val { - PllM::Div1 => 0b0000, - PllM::Div2 => 0b0001, - PllM::Div3 => 0b0010, - PllM::Div4 => 0b0011, - PllM::Div5 => 0b0100, - PllM::Div6 => 0b0101, - PllM::Div7 => 0b0110, - PllM::Div8 => 0b0111, - PllM::Div9 => 0b1000, - PllM::Div10 => 0b1001, - PllM::Div11 => 0b1010, - PllM::Div12 => 0b1011, - PllM::Div13 => 0b1100, - PllM::Div14 => 0b1101, - PllM::Div15 => 0b1110, - PllM::Div16 => 0b1111, - } - } -} - /// PLL Configuration /// /// Use this struct to configure the PLL source, input frequency, multiplication factor, and output @@ -360,12 +187,12 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI_FREQ.0 + HSI_FREQ } PllSrc::HSE(freq) => { RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} - freq.0 + freq } }; @@ -373,7 +200,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_pllon(false)); while RCC.cr().read().pllrdy() {} - let internal_freq = src_freq / pll_config.prediv_m.to_div() * pll_config.mul_n.to_mul(); + 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()); @@ -383,26 +210,26 @@ pub(crate) unsafe fn init(config: Config) { let pll_p_freq = pll_config.div_p.map(|div_p| { RCC.pllcfgr().modify(|w| { - w.set_pllpdiv(div_p.into()); + w.set_pllp(div_p); w.set_pllpen(true); }); - Hertz(internal_freq / div_p.to_div()) + internal_freq / div_p }); let pll_q_freq = pll_config.div_q.map(|div_q| { RCC.pllcfgr().modify(|w| { - w.set_pllq(div_q.into()); + w.set_pllq(div_q); w.set_pllqen(true); }); - Hertz(internal_freq / div_q.to_div()) + internal_freq / div_q }); let pll_r_freq = pll_config.div_r.map(|div_r| { RCC.pllcfgr().modify(|w| { - w.set_pllr(div_r.into()); + w.set_pllr(div_r); w.set_pllren(true); }); - Hertz(internal_freq / div_r.to_div()) + internal_freq / div_r }); // Enable the PLL diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 5f9cc1c8..a11fd473 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -6,8 +6,8 @@ use crate::pac::pwr::vals::Vos; pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; #[cfg(stm32h7)] pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; -pub use crate::pac::rcc::vals::Ckpersel as PerClockSource; 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}; @@ -34,7 +34,7 @@ const VCO_WIDE_RANGE: RangeInclusive = 192_000_000..=836_000_000; #[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] const VCO_WIDE_RANGE: RangeInclusive = 192_000_000..=960_000_000; -pub use super::bus::{AHBPrescaler, APBPrescaler}; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; #[derive(Clone, Copy, Eq, PartialEq)] pub enum VoltageScale { @@ -109,19 +109,19 @@ pub struct Pll { #[cfg(stm32h5)] pub source: PllSource, - /// PLL pre-divider (DIVM). Must be between 1 and 63. - pub prediv: u8, + /// PLL pre-divider (DIVM). + pub prediv: PllPreDiv, - /// PLL multiplication factor. Must be between 4 and 512. - pub mul: u16, + /// PLL multiplication factor. + pub mul: PllMul, - /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. + /// PLL P division factor. If None, PLL P output is disabled. /// On PLL1, it must be even (in particular, it cannot be 1.) - pub divp: Option, - /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. - pub divq: Option, - /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. - pub divr: Option, + pub divp: Option, + /// PLL Q division factor. If None, PLL Q output is disabled. + pub divq: Option, + /// PLL R division factor. If None, PLL R output is disabled. + pub divr: Option, } fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { @@ -604,9 +604,9 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { // "To save power when PLL1 is not used, the value of PLL1M must be set to 0."" #[cfg(stm32h7)] - RCC.pllckselr().write(|w| w.set_divm(num, 0)); + RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0))); #[cfg(stm32h5)] - RCC.pllcfgr(num).write(|w| w.set_divm(0)); + RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0))); return PllOutput { p: None, @@ -615,9 +615,6 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { }; }; - assert!(1 <= config.prediv && config.prediv <= 63); - assert!(4 <= config.mul && config.mul <= 512); - #[cfg(stm32h5)] let source = config.source; #[cfg(stm32h7)] @@ -653,22 +650,16 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { }; let p = config.divp.map(|div| { - assert!(1 <= div && div <= 128); if num == 0 { // on PLL1, DIVP must be even. - assert!(div % 2 == 0); + // The enum value is 1 less than the divider, so check it's odd. + assert!(div.to_bits() % 2 == 1); } vco_clk / div }); - let q = config.divq.map(|div| { - assert!(1 <= div && div <= 128); - vco_clk / div - }); - let r = config.divr.map(|div| { - assert!(1 <= div && div <= 128); - vco_clk / div - }); + let q = config.divq.map(|div| vco_clk / div); + let r = config.divr.map(|div| vco_clk / div); #[cfg(stm32h5)] RCC.pllcfgr(num).write(|w| { @@ -699,10 +690,10 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { } RCC.plldivr(num).write(|w| { - w.set_plln(config.mul - 1); - w.set_pllp((config.divp.unwrap_or(1) - 1) as u8); - w.set_pllq((config.divq.unwrap_or(1) - 1) as u8); - w.set_pllr((config.divr.unwrap_or(1) - 1) as u8); + w.set_plln(config.mul); + w.set_pllp(config.divp.unwrap_or(PllDiv::DIV2)); + w.set_pllq(config.divq.unwrap_or(PllDiv::DIV2)); + w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2)); }); RCC.cr().modify(|w| w.set_pllon(num, true)); diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 7358be31..b4236126 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs @@ -1,8 +1,8 @@ use super::bd::BackupDomain; -pub use super::bus::{AHBPrescaler, APBPrescaler}; 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}; diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index 90524fb3..e445a716 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs @@ -1,5 +1,5 @@ -pub use super::bus::{AHBPrescaler, APBPrescaler}; 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; diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 2fbb9920..0e35b42e 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -1,7 +1,9 @@ -use stm32_metapac::rcc::regs::Cfgr; - -pub use super::bus::{AHBPrescaler, APBPrescaler}; -use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; +use crate::pac::rcc::regs::Cfgr; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, + Pllr as PllRDiv, Ppre as APBPrescaler, +}; +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}; @@ -17,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); #[derive(Clone, Copy)] pub enum ClockSrc { MSI(MSIRange), - PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option), + PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option), 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 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 Default for MSIRange { - fn default() -> MSIRange { - MSIRange::Range6 - } -} - -pub type PLL48Div = PLLClkDiv; -pub type PLLSAI1RDiv = PLLClkDiv; -pub type PLLSAI1QDiv = PLLClkDiv; -pub type PLLSAI1PDiv = PLLClkDiv; - -/// PLL divider -#[derive(Clone, Copy)] -pub enum PLLDiv { - Div2, - Div3, - Div4, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -81,95 +32,6 @@ pub enum PLLSource { MSI(MSIRange), } -seq_macro::seq!(N in 8..=86 { - #[derive(Clone, Copy)] - pub enum PLLMul { - #( - Mul~N, - )* - } - - impl From for u8 { - fn from(val: PLLMul) -> u8 { - match val { - #( - PLLMul::Mul~N => N, - )* - } - } - } - - impl PLLMul { - pub fn to_mul(self) -> u32 { - match self { - #( - PLLMul::Mul~N => N, - )* - } - } - } -}); - -#[derive(Clone, Copy)] -pub enum PLLClkDiv { - Div2, - Div4, - Div6, - Div8, -} - -impl PLLClkDiv { - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - (val as u32 + 1) * 2 - } -} - -impl From for u8 { - fn from(val: PLLClkDiv) -> u8 { - match val { - PLLClkDiv::Div2 => 0b00, - PLLClkDiv::Div4 => 0b01, - PLLClkDiv::Div6 => 0b10, - PLLClkDiv::Div8 => 0b11, - } - } -} - -#[derive(Clone, Copy)] -pub enum PLLSrcDiv { - Div1, - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, -} - -impl PLLSrcDiv { - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - val as u32 + 1 - } -} - -impl From for u8 { - fn from(val: PLLSrcDiv) -> u8 { - match val { - PLLSrcDiv::Div1 => 0b000, - PLLSrcDiv::Div2 => 0b001, - PLLSrcDiv::Div3 => 0b010, - PLLSrcDiv::Div4 => 0b011, - PLLSrcDiv::Div5 => 0b100, - PLLSrcDiv::Div6 => 0b101, - PLLSrcDiv::Div7 => 0b110, - PLLSrcDiv::Div8 => 0b111, - } - } -} - impl From for Pllsrc { fn from(val: PLLSource) -> Pllsrc { match val { @@ -180,57 +42,13 @@ impl From for Pllsrc { } } -impl From for Msirange { - fn from(val: MSIRange) -> Msirange { - match val { - MSIRange::Range0 => Msirange::RANGE100K, - MSIRange::Range1 => Msirange::RANGE200K, - MSIRange::Range2 => Msirange::RANGE400K, - MSIRange::Range3 => Msirange::RANGE800K, - MSIRange::Range4 => Msirange::RANGE1M, - MSIRange::Range5 => Msirange::RANGE2M, - MSIRange::Range6 => Msirange::RANGE4M, - MSIRange::Range7 => Msirange::RANGE8M, - MSIRange::Range8 => Msirange::RANGE16M, - MSIRange::Range9 => Msirange::RANGE24M, - MSIRange::Range10 => Msirange::RANGE32M, - MSIRange::Range11 => Msirange::RANGE48M, - } - } -} - -impl From for u32 { - fn from(val: MSIRange) -> u32 { - match val { - 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, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, - pub pllsai1: Option<( - PLLMul, - PLLSrcDiv, - Option, - Option, - Option, - )>, + pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] pub hsi48: bool, pub rtc_mux: RtcClockSource, @@ -242,7 +60,7 @@ impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::MSI(MSIRange::Range6), + mux: ClockSrc::MSI(MSIRange::RANGE4M), ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, @@ -262,7 +80,7 @@ pub(crate) unsafe fn init(config: Config) { // Turn on MSI and configure it to 4MHz. RCC.cr().modify(|w| { w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. - w.set_msirange(MSIRange::default().into()); + w.set_msirange(MSIRange::RANGE4M); w.set_msipllen(false); w.set_msion(true) }); @@ -298,40 +116,40 @@ pub(crate) unsafe fn init(config: Config) { while !RCC.cr().read().msirdy() {} // Enable as clock source for USB, RNG if running at 48 MHz - if let MSIRange::Range11 = range { + if range == MSIRange::RANGE48M { RCC.ccipr().modify(|w| { w.set_clk48sel(0b11); }); } - (range.into(), Sw::MSI) + (msirange_to_hertz(range), Sw::MSI) } ClockSrc::HSI16 => { // Enable HSI16 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(src, div, prediv, mul, pll48div) => { + ClockSrc::PLL(src, divr, prediv, mul, divq) => { let src_freq = match src { PLLSource::HSE(freq) => { // Enable HSE RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} - freq.0 + freq } PLLSource::HSI16 => { // Enable HSI RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI_FREQ.0 + HSI_FREQ } PLLSource::MSI(range) => { // Enable MSI @@ -343,7 +161,8 @@ pub(crate) unsafe fn init(config: Config) { w.set_msion(true); }); while !RCC.cr().read().msirdy() {} - range.into() + + msirange_to_hertz(range) } }; @@ -351,28 +170,28 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_pllon(false)); while RCC.cr().read().pllrdy() {} - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div(); + let freq = src_freq / prediv * mul / divr; #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))] - assert!(freq <= 120_000_000); + assert!(freq.0 <= 120_000_000); #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))] - assert!(freq <= 80_000_000); + assert!(freq.0 <= 80_000_000); RCC.pllcfgr().write(move |w| { - w.set_plln(mul.into()); - w.set_pllm(prediv.into()); - w.set_pllr(div.into()); - if let Some(pll48div) = pll48div { - w.set_pllq(pll48div.into()); + w.set_plln(mul); + w.set_pllm(prediv); + w.set_pllr(divr); + if let Some(divq) = divq { + w.set_pllq(divq); w.set_pllqen(true); } w.set_pllsrc(src.into()); }); // Enable as clock source for USB, RNG if PLL48 divisor is provided - if let Some(pll48div) = pll48div { - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div(); - assert!(freq == 48_000_000); + if let Some(divq) = divq { + let freq = src_freq / prediv * mul / divq; + assert!(freq.0 == 48_000_000); RCC.ccipr().modify(|w| { w.set_clk48sel(0b10); }); @@ -380,25 +199,25 @@ pub(crate) unsafe fn init(config: Config) { if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { RCC.pllsai1cfgr().write(move |w| { - w.set_pllsai1n(mul.into()); - w.set_pllsai1m(prediv.into()); + w.set_plln(mul); + w.set_pllm(prediv); if let Some(r_div) = r_div { - w.set_pllsai1r(r_div.into()); - w.set_pllsai1ren(true); + w.set_pllr(r_div); + w.set_pllren(true); } if let Some(q_div) = q_div { - w.set_pllsai1q(q_div.into()); - w.set_pllsai1qen(true); - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div(); - if freq == 48_000_000 { + w.set_pllq(q_div); + w.set_pllqen(true); + let freq = src_freq / prediv * mul / q_div; + if freq.0 == 48_000_000 { RCC.ccipr().modify(|w| { w.set_clk48sel(0b1); }); } } if let Some(p_div) = p_div { - w.set_pllsai1pdiv(p_div.into()); - w.set_pllsai1pen(true); + w.set_pllp(p_div); + w.set_pllpen(true); } }); @@ -425,17 +244,13 @@ pub(crate) unsafe fn init(config: Config) { // Set flash wait states FLASH.acr().modify(|w| { - w.set_latency(if sys_clk <= 16_000_000 { - 0b000 - } else if sys_clk <= 32_000_000 { - 0b001 - } else if sys_clk <= 48_000_000 { - 0b010 - } else if sys_clk <= 64_000_000 { - 0b011 - } else { - 0b100 - }); + w.set_latency(match sys_clk.0 { + 0..=16_000_000 => 0, + 0..=32_000_000 => 1, + 0..=48_000_000 => 2, + 0..=64_000_000 => 3, + _ => 4, + }) }); RCC.cfgr().modify(|w| { @@ -445,43 +260,50 @@ pub(crate) unsafe fn init(config: Config) { 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 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 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) } }; 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) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - ahb2: Hertz(ahb_freq), - ahb3: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + ahb2: ahb_freq, + ahb3: ahb_freq, + apb1: apb1_freq, + apb2: apb2_freq, + apb1_tim: apb1_tim_freq, + apb2_tim: apb2_tim_freq, }); } + +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!(), + } +} diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index 652bdcb7..d9b3ee28 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -1,8 +1,11 @@ -use stm32_metapac::PWR; - -pub use super::bus::{AHBPrescaler, APBPrescaler}; -use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; -use crate::pac::{FLASH, RCC}; +use crate::pac::rcc::regs::Cfgr; +pub use crate::pac::rcc::vals::{ + Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, + Pllr as PllRDiv, Ppre as APBPrescaler, +}; +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; @@ -16,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); #[derive(Clone, Copy)] pub enum ClockSrc { MSI(MSIRange), - PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option), + PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option), 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 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 Default for MSIRange { - fn default() -> MSIRange { - MSIRange::Range6 - } -} - -pub type PLL48Div = PLLClkDiv; -pub type PLLSAI1RDiv = PLLClkDiv; -pub type PLLSAI1QDiv = PLLClkDiv; -pub type PLLSAI1PDiv = PLLClkDiv; - -/// PLL divider -#[derive(Clone, Copy)] -pub enum PLLDiv { - Div2, - Div3, - Div4, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -80,95 +32,6 @@ pub enum PLLSource { MSI(MSIRange), } -seq_macro::seq!(N in 8..=86 { - #[derive(Clone, Copy)] - pub enum PLLMul { - #( - Mul~N, - )* - } - - impl From for u8 { - fn from(val: PLLMul) -> u8 { - match val { - #( - PLLMul::Mul~N => N, - )* - } - } - } - - impl PLLMul { - pub fn to_mul(self) -> u32 { - match self { - #( - PLLMul::Mul~N => N, - )* - } - } - } -}); - -#[derive(Clone, Copy)] -pub enum PLLClkDiv { - Div2, - Div4, - Div6, - Div8, -} - -impl PLLClkDiv { - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - (val as u32 + 1) * 2 - } -} - -impl From for u8 { - fn from(val: PLLClkDiv) -> u8 { - match val { - PLLClkDiv::Div2 => 0b00, - PLLClkDiv::Div4 => 0b01, - PLLClkDiv::Div6 => 0b10, - PLLClkDiv::Div8 => 0b11, - } - } -} - -#[derive(Clone, Copy)] -pub enum PLLSrcDiv { - Div1, - Div2, - Div3, - Div4, - Div5, - Div6, - Div7, - Div8, -} - -impl PLLSrcDiv { - pub fn to_div(self) -> u32 { - let val: u8 = self.into(); - val as u32 + 1 - } -} - -impl From for u8 { - fn from(val: PLLSrcDiv) -> u8 { - match val { - PLLSrcDiv::Div1 => 0b000, - PLLSrcDiv::Div2 => 0b001, - PLLSrcDiv::Div3 => 0b010, - PLLSrcDiv::Div4 => 0b011, - PLLSrcDiv::Div5 => 0b100, - PLLSrcDiv::Div6 => 0b101, - PLLSrcDiv::Div7 => 0b110, - PLLSrcDiv::Div8 => 0b111, - } - } -} - impl From for Pllsrc { fn from(val: PLLSource) -> Pllsrc { match val { @@ -179,75 +42,59 @@ impl From for Pllsrc { } } -impl From for Msirange { - fn from(val: MSIRange) -> Msirange { - match val { - MSIRange::Range0 => Msirange::RANGE100K, - MSIRange::Range1 => Msirange::RANGE200K, - MSIRange::Range2 => Msirange::RANGE400K, - MSIRange::Range3 => Msirange::RANGE800K, - MSIRange::Range4 => Msirange::RANGE1M, - MSIRange::Range5 => Msirange::RANGE2M, - MSIRange::Range6 => Msirange::RANGE4M, - MSIRange::Range7 => Msirange::RANGE8M, - MSIRange::Range8 => Msirange::RANGE16M, - MSIRange::Range9 => Msirange::RANGE24M, - MSIRange::Range10 => Msirange::RANGE32M, - MSIRange::Range11 => Msirange::RANGE48M, - } - } -} - -impl From for u32 { - fn from(val: MSIRange) -> u32 { - match val { - 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, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, - pub pllsai1: Option<( - PLLMul, - PLLSrcDiv, - Option, - Option, - Option, - )>, + pub pllsai1: Option<(PllMul, PllPreDiv, Option, Option, Option)>, pub hsi48: bool, + pub rtc_mux: RtcClockSource, + pub lse: Option, + pub lsi: bool, } impl Default for Config { #[inline] fn default() -> Config { Config { - mux: ClockSrc::MSI(MSIRange::Range6), + mux: ClockSrc::MSI(MSIRange::RANGE4M), ahb_pre: AHBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1, pllsai1: None, hsi48: false, + rtc_mux: RtcClockSource::LSI, + lsi: true, + lse: None, } } } pub(crate) unsafe fn init(config: Config) { + // Switch to MSI to prevent problems with PLL configuration. + if !RCC.cr().read().msion() { + // Turn on MSI and configure it to 4MHz. + RCC.cr().modify(|w| { + w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. + w.set_msirange(MSIRange::RANGE4M); + w.set_msipllen(false); + w.set_msion(true) + }); + + // Wait until MSI is running + while !RCC.cr().read().msirdy() {} + } + if RCC.cfgr().read().sws() != Sw::MSI { + // Set MSI as a clock source, reset prescalers. + RCC.cfgr().write_value(Cfgr::default()); + // Wait for clock switch status bits to change. + while RCC.cfgr().read().sws() != Sw::MSI {} + } + + //BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); + PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); let (sys_clk, sw) = match config.mux { ClockSrc::MSI(range) => { @@ -255,47 +102,53 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| { let bits: Msirange = range.into(); w.set_msirange(bits); - w.set_msipllen(false); 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); + } }); while !RCC.cr().read().msirdy() {} // Enable as clock source for USB, RNG if running at 48 MHz - if let MSIRange::Range11 = range { + if range == MSIRange::RANGE48M { RCC.ccipr1().modify(|w| { w.set_clk48msel(0b11); }); } - (range.into(), Sw::MSI) + (msirange_to_hertz(range), Sw::MSI) } ClockSrc::HSI16 => { // Enable HSI16 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(src, div, prediv, mul, pll48div) => { + ClockSrc::PLL(src, divr, prediv, mul, divq) => { let src_freq = match src { PLLSource::HSE(freq) => { // Enable HSE RCC.cr().write(|w| w.set_hseon(true)); while !RCC.cr().read().hserdy() {} - freq.0 + freq } PLLSource::HSI16 => { // Enable HSI RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI_FREQ.0 + HSI_FREQ } PLLSource::MSI(range) => { // Enable MSI @@ -307,7 +160,8 @@ pub(crate) unsafe fn init(config: Config) { w.set_msion(true); }); while !RCC.cr().read().msirdy() {} - range.into() + + msirange_to_hertz(range) } }; @@ -315,23 +169,23 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().modify(|w| w.set_pllon(false)); while RCC.cr().read().pllrdy() {} - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div(); + let freq = src_freq / prediv * mul / divr; RCC.pllcfgr().write(move |w| { - w.set_plln(mul.into()); - w.set_pllm(prediv.into()); - w.set_pllr(div.into()); - if let Some(pll48div) = pll48div { - w.set_pllq(pll48div.into()); + w.set_plln(mul); + w.set_pllm(prediv); + w.set_pllr(divr); + if let Some(divq) = divq { + w.set_pllq(divq); w.set_pllqen(true); } w.set_pllsrc(src.into()); }); // Enable as clock source for USB, RNG if PLL48 divisor is provided - if let Some(pll48div) = pll48div { - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div(); - assert!(freq == 48_000_000); + if let Some(divq) = divq { + let freq = src_freq / prediv * mul / divq; + assert!(freq.0 == 48_000_000); RCC.ccipr1().modify(|w| { w.set_clk48msel(0b10); }); @@ -339,25 +193,25 @@ pub(crate) unsafe fn init(config: Config) { if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { RCC.pllsai1cfgr().write(move |w| { - w.set_pllsai1n(mul.into()); - w.set_pllsai1m(prediv.into()); + w.set_plln(mul); + w.set_pllm(prediv); if let Some(r_div) = r_div { - w.set_pllsai1r(r_div.into()); - w.set_pllsai1ren(true); + w.set_pllr(r_div); + w.set_pllren(true); } if let Some(q_div) = q_div { - w.set_pllsai1q(q_div.into()); - w.set_pllsai1qen(true); - let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div(); - if freq == 48_000_000 { + w.set_pllq(q_div); + w.set_pllqen(true); + let freq = src_freq / prediv * mul / q_div; + if freq.0 == 48_000_000 { RCC.ccipr1().modify(|w| { w.set_clk48msel(0b1); }); } } if let Some(p_div) = p_div { - w.set_pllsai1pdiv(p_div.into()); - w.set_pllsai1pen(true); + w.set_pllp(p_div); + w.set_pllpen(true); } }); @@ -384,7 +238,7 @@ pub(crate) unsafe fn init(config: Config) { // Set flash wait states // VCORE Range 0 (performance), others TODO FLASH.acr().modify(|w| { - w.set_latency(match sys_clk { + w.set_latency(match sys_clk.0 { 0..=20_000_000 => 0, 0..=40_000_000 => 1, 0..=60_000_000 => 2, @@ -401,43 +255,50 @@ pub(crate) unsafe fn init(config: Config) { 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 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 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) } }; 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) + let freq = ahb_freq / pre; + (freq, freq * 2u32) } }; set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - ahb2: Hertz(ahb_freq), - ahb3: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + ahb2: ahb_freq, + ahb3: ahb_freq, + apb1: apb1_freq, + apb2: apb2_freq, + apb1_tim: apb1_tim_freq, + apb2_tim: apb2_tim_freq, }); } + +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!(), + } +} diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index a3299089..52dc386b 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -6,7 +6,6 @@ pub use crate::rcc::bd::RtcClockSource; use crate::time::Hertz; pub(crate) mod bd; -mod bus; mod mco; pub use mco::*; diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 14b8577d..d8fb1730 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -1,6 +1,5 @@ -use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllmboost, Pllrge, Pllsrc, Sw}; - -pub use super::bus::{AHBPrescaler, APBPrescaler}; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler}; +use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -16,7 +15,7 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; #[derive(Copy, Clone)] pub enum ClockSrc { /// Use an internal medium speed oscillator (MSIS) as the system clock. - MSI(MSIRange), + MSI(Msirange), /// Use the external high speed clock as the system clock. /// /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must @@ -31,29 +30,29 @@ pub enum ClockSrc { impl Default for ClockSrc { fn default() -> Self { // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9 - ClockSrc::MSI(MSIRange::Range4mhz) + ClockSrc::MSI(Msirange::RANGE_4MHZ) } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] pub struct PllConfig { /// The clock source for the PLL. pub source: PllSrc, /// The PLL prescaler. /// /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. - pub m: PllM, + pub m: Pllm, /// The PLL multiplier. /// /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. - pub n: PllN, + pub n: Plln, /// The divider for the R output. /// /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default /// `Config { voltage_range }`. - pub r: PllClkDiv, + pub r: Plldiv, } impl PllConfig { @@ -61,27 +60,27 @@ impl PllConfig { pub const fn hsi16_160mhz() -> Self { PllConfig { source: PllSrc::HSI16, - m: PllM::NotDivided, - n: PllN::Mul10, - r: PllClkDiv::NotDivided, + m: Pllm::DIV1, + n: Plln::MUL10, + r: Plldiv::DIV1, } } /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz pub const fn msis_160mhz() -> Self { PllConfig { - source: PllSrc::MSIS(MSIRange::Range48mhz), - m: PllM::Div3, - n: PllN::Mul10, - r: PllClkDiv::NotDivided, + source: PllSrc::MSIS(Msirange::RANGE_48MHZ), + m: Pllm::DIV3, + n: Plln::MUL10, + r: Plldiv::DIV1, } } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] pub enum PllSrc { /// Use an internal medium speed oscillator as the PLL source. - MSIS(MSIRange), + MSIS(Msirange), /// Use the external high speed clock as the system PLL source. /// /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must @@ -101,75 +100,6 @@ impl Into for PllSrc { } } -seq_macro::seq!(N in 2..=128 { - #[derive(Copy, Clone, Debug)] - pub enum PllClkDiv { - NotDivided = 1, - #( - Div~N = N, - )* - } - - impl PllClkDiv { - fn to_div(&self) -> u8 { - match self { - PllClkDiv::NotDivided => 0, - #( - PllClkDiv::Div~N => N - 1, - )* - } - } - } -}); - -seq_macro::seq!(N in 4..=512 { - #[derive(Copy, Clone, Debug)] - pub enum PllN { - NotMultiplied = 1, - #( - Mul~N = N, - )* - } - - impl PllN { - fn to_mul(&self) -> u16 { - match self { - PllN::NotMultiplied => 0, - #( - PllN::Mul~N => N - 1, - )* - } - } - } -}); - -// Pre-division -#[derive(Copy, Clone, Debug)] -pub enum PllM { - NotDivided = 0b0000, - Div2 = 0b0001, - Div3 = 0b0010, - Div4 = 0b0011, - Div5 = 0b0100, - Div6 = 0b0101, - Div7 = 0b0110, - Div8 = 0b0111, - Div9 = 0b1000, - Div10 = 0b1001, - Div11 = 0b1010, - Div12 = 0b1011, - Div13 = 0b1100, - Div14 = 0b1101, - Div15 = 0b1110, - Div16 = 0b1111, -} - -impl Into for PllM { - fn into(self) -> Pllm { - Pllm::from_bits(self as u8) - } -} - impl Into for ClockSrc { fn into(self) -> Sw { match self { @@ -181,56 +111,6 @@ impl Into for ClockSrc { } } -#[derive(Debug, Copy, Clone)] -pub enum MSIRange { - /// The 48 MHz MSI speed is unavailable in `VoltageScale::RANGE4`. - Range48mhz = 48_000_000, - Range24mhz = 24_000_000, - Range16mhz = 16_000_000, - Range12mhz = 12_000_000, - Range4mhz = 4_000_000, - Range2mhz = 2_000_000, - Range1_33mhz = 1_330_000, - Range1mhz = 1_000_000, - Range3_072mhz = 3_072_000, - Range1_536mhz = 1_536_000, - Range1_024mhz = 1_024_000, - Range768khz = 768_000, - Range400khz = 400_000, - Range200khz = 200_000, - Range133khz = 133_000, - Range100khz = 100_000, -} - -impl Into for MSIRange { - fn into(self) -> u32 { - self as u32 - } -} - -impl Into for MSIRange { - fn into(self) -> Msirange { - match self { - MSIRange::Range48mhz => Msirange::RANGE_48MHZ, - MSIRange::Range24mhz => Msirange::RANGE_24MHZ, - MSIRange::Range16mhz => Msirange::RANGE_16MHZ, - MSIRange::Range12mhz => Msirange::RANGE_12MHZ, - MSIRange::Range4mhz => Msirange::RANGE_4MHZ, - MSIRange::Range2mhz => Msirange::RANGE_2MHZ, - MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ, - MSIRange::Range1mhz => Msirange::RANGE_1MHZ, - MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ, - MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ, - MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ, - MSIRange::Range768khz => Msirange::RANGE_768KHZ, - MSIRange::Range400khz => Msirange::RANGE_400KHZ, - MSIRange::Range200khz => Msirange::RANGE_200KHZ, - MSIRange::Range133khz => Msirange::RANGE_133KHZ, - MSIRange::Range100khz => Msirange::RANGE_100KHZ, - } - } -} - #[derive(Copy, Clone)] pub struct Config { pub mux: ClockSrc, @@ -273,11 +153,11 @@ impl Config { frequency } - unsafe fn init_msis(&self, range: MSIRange) -> Hertz { + unsafe fn init_msis(&self, range: Msirange) -> Hertz { // Check MSI output per RM0456 § 11.4.10 match self.voltage_range { VoltageScale::RANGE4 => { - assert!(range as u32 <= 24_000_000); + assert!(msirange_to_hertz(range).0 <= 24_000_000); } _ => {} } @@ -291,8 +171,7 @@ impl Config { } RCC.icscr1().modify(|w| { - let bits: Msirange = range.into(); - w.set_msisrange(bits); + w.set_msisrange(range); w.set_msirgsel(Msirgsel::RCC_ICSCR1); }); RCC.cr().write(|w| { @@ -300,7 +179,7 @@ impl Config { w.set_msison(true); }); while !RCC.cr().read().msisrdy() {} - Hertz(range as u32) + msirange_to_hertz(range) } } @@ -344,14 +223,14 @@ pub(crate) unsafe fn init(config: Config) { }; // Calculate the reference clock, which is the source divided by m - let reference_clk = source_clk / (pll.m as u8 as u32 + 1); + let reference_clk = source_clk / pll.m; // Check limits per RM0456 § 11.4.6 assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16)); // Calculate the PLL1 VCO clock and PLL1 R output clock - let pll1_clk = reference_clk * (pll.n as u8 as u32); - let pll1r_clk = pll1_clk / (pll.r as u8 as u32); + let pll1_clk = reference_clk * pll.n; + let pll1r_clk = pll1_clk / pll.r; // Check system clock per RM0456 § 11.4.9 assert!(pll1r_clk <= Hertz::mhz(160)); @@ -387,11 +266,11 @@ pub(crate) unsafe fn init(config: Config) { Pllmboost::DIV2 } else { // Bypass, giving EPOD 4-16 MHz - Pllmboost::BYPASS + Pllmboost::DIV1 } } else { // Nothing to do - Pllmboost::BYPASS + Pllmboost::DIV1 }; // Disable the PLL, and wait for it to disable @@ -402,7 +281,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.pll1cfgr().write(|w| { // Configure PLL1 source and prescaler w.set_pllsrc(pll.source.into()); - w.set_pllm(pll.m.into()); + w.set_pllm(pll.m); // Configure PLL1 input frequncy range let input_range = if reference_clk <= Hertz::mhz(8) { @@ -422,9 +301,9 @@ pub(crate) unsafe fn init(config: Config) { // Configure the PLL divisors RCC.pll1divr().modify(|w| { // Set the VCO multiplier - w.set_plln(pll.n.to_mul()); + w.set_plln(pll.n); // Set the R output divisor - w.set_pllr(pll.r.to_div()); + w.set_pllr(pll.r); }); // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? @@ -442,8 +321,7 @@ pub(crate) unsafe fn init(config: Config) { pll1r_clk } - } - .0; + }; if config.hsi48 { RCC.cr().modify(|w| w.set_hsi48on(true)); @@ -455,13 +333,13 @@ pub(crate) unsafe fn init(config: Config) { let wait_states = match config.voltage_range { // VOS 1 range VCORE 1.26V - 1.40V VoltageScale::RANGE1 => { - if sys_clk < 32_000_000 { + if sys_clk.0 < 32_000_000 { 0 - } else if sys_clk < 64_000_000 { + } else if sys_clk.0 < 64_000_000 { 1 - } else if sys_clk < 96_000_000 { + } else if sys_clk.0 < 96_000_000 { 2 - } else if sys_clk < 128_000_000 { + } else if sys_clk.0 < 128_000_000 { 3 } else { 4 @@ -469,11 +347,11 @@ pub(crate) unsafe fn init(config: Config) { } // VOS 2 range VCORE 1.15V - 1.26V VoltageScale::RANGE2 => { - if sys_clk < 30_000_000 { + if sys_clk.0 < 30_000_000 { 0 - } else if sys_clk < 60_000_000 { + } else if sys_clk.0 < 60_000_000 { 1 - } else if sys_clk < 90_000_000 { + } else if sys_clk.0 < 90_000_000 { 2 } else { 3 @@ -481,9 +359,9 @@ pub(crate) unsafe fn init(config: Config) { } // VOS 3 range VCORE 1.05V - 1.15V VoltageScale::RANGE3 => { - if sys_clk < 24_000_000 { + if sys_clk.0 < 24_000_000 { 0 - } else if sys_clk < 48_000_000 { + } else if sys_clk.0 < 48_000_000 { 1 } else { 2 @@ -491,7 +369,7 @@ pub(crate) unsafe fn init(config: Config) { } // VOS 4 range VCORE 0.95V - 1.05V VoltageScale::RANGE4 => { - if sys_clk < 12_000_000 { + if sys_clk.0 < 12_000_000 { 0 } else { 1 @@ -522,62 +400,70 @@ pub(crate) unsafe fn init(config: Config) { // Configure the bus prescalers 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_ppre3(config.apb3_pre.into()); + w.set_ppre3(config.apb3_pre); }); - 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 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 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) } }; let (apb3_freq, _apb3_tim_freq) = match config.apb3_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) } }; set_freqs(Clocks { - sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), - ahb2: Hertz(ahb_freq), - ahb3: Hertz(ahb_freq), - apb1: Hertz(apb1_freq), - apb2: Hertz(apb2_freq), - apb3: Hertz(apb3_freq), - apb1_tim: Hertz(apb1_tim_freq), - apb2_tim: Hertz(apb2_tim_freq), + sys: sys_clk, + ahb1: ahb_freq, + ahb2: ahb_freq, + ahb3: ahb_freq, + apb1: apb1_freq, + apb2: apb2_freq, + apb3: apb3_freq, + apb1_tim: apb1_tim_freq, + apb2_tim: apb2_tim_freq, }); } + +fn msirange_to_hertz(range: Msirange) -> Hertz { + match range { + Msirange::RANGE_48MHZ => Hertz(48_000_000), + Msirange::RANGE_24MHZ => Hertz(24_000_000), + Msirange::RANGE_16MHZ => Hertz(16_000_000), + Msirange::RANGE_12MHZ => Hertz(12_000_000), + Msirange::RANGE_4MHZ => Hertz(4_000_000), + Msirange::RANGE_2MHZ => Hertz(2_000_000), + Msirange::RANGE_1_33MHZ => Hertz(1_330_000), + Msirange::RANGE_1MHZ => Hertz(1_000_000), + Msirange::RANGE_3_072MHZ => Hertz(3_072_000), + Msirange::RANGE_1_536MHZ => Hertz(1_536_000), + Msirange::RANGE_1_024MHZ => Hertz(1_024_000), + Msirange::RANGE_768KHZ => Hertz(768_000), + Msirange::RANGE_400KHZ => Hertz(400_000), + Msirange::RANGE_200KHZ => Hertz(200_000), + Msirange::RANGE_133KHZ => Hertz(133_000), + Msirange::RANGE_100KHZ => Hertz(100_000), + } +} diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index ee45a342..ee2a8ae1 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,4 +1,4 @@ -pub use super::bus::{AHBPrescaler, APBPrescaler}; +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}; diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 937f5550..7baedfcd 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,6 +1,6 @@ -pub use super::bus::{AHBPrescaler, APBPrescaler}; 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::{FLASH, RCC}; use crate::rcc::bd::{BackupDomain, RtcClockSource}; use crate::rcc::{set_freqs, Clocks}; diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs index 89493761..62aaa980 100644 --- a/examples/stm32f2/src/bin/pll.rs +++ b/examples/stm32f2/src/bin/pll.rs @@ -7,7 +7,7 @@ use core::convert::TryFrom; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rcc::{ - APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLL48Div, PLLConfig, PLLMainDiv, PLLMul, PLLPreDiv, PLLSrc, + APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc, }; use embassy_stm32::time::Hertz; use embassy_stm32::Config; @@ -32,9 +32,9 @@ async fn main(_spawner: Spawner) { // 1 MHz PLL input * 240 = 240 MHz PLL VCO mul: unwrap!(PLLMul::try_from(240)), // 240 MHz PLL VCO / 2 = 120 MHz main PLL output - main_div: PLLMainDiv::Div2, + p_div: PLLPDiv::DIV2, // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output - pll48_div: unwrap!(PLL48Div::try_from(5)), + q_div: PLLQDiv::DIV5, }; // System clock comes from PLL (= the 120 MHz main PLL output) config.rcc.mux = ClockSrc::PLL; diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index a792748b..da9b18a0 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs @@ -16,12 +16,12 @@ async fn main(_spawner: Spawner) { config.rcc.pll = Some(Pll { source: PllSrc::HSI16, - prediv_m: PllM::Div4, - mul_n: PllN::Mul85, + prediv_m: PllM::DIV4, + mul_n: PllN::MUL85, div_p: None, div_q: None, // Main system clock at 170 MHz - div_r: Some(PllR::Div2), + div_r: Some(PllR::DIV2), }); config.rcc.adc12_clock_source = AdcClockSource::SysClk; diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index ef7d4800..f8159cb5 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs @@ -15,12 +15,12 @@ async fn main(_spawner: Spawner) { config.rcc.pll = Some(Pll { source: PllSrc::HSI16, - prediv_m: PllM::Div4, - mul_n: PllN::Mul85, + prediv_m: PllM::DIV4, + mul_n: PllN::MUL85, div_p: None, div_q: None, // Main system clock at 170 MHz - div_r: Some(PllR::Div2), + div_r: Some(PllR::DIV2), }); config.rcc.mux = ClockSrc::PLL; diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index 77cfa67d..9099b609 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs @@ -25,16 +25,16 @@ async fn main(_spawner: Spawner) { // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. const USE_HSI48: bool = true; - let pllq_div = if USE_HSI48 { None } else { Some(PllQ::Div6) }; + let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) }; config.rcc.pll = Some(Pll { source: PllSrc::HSE(Hertz(8_000_000)), - prediv_m: PllM::Div2, - mul_n: PllN::Mul72, + prediv_m: PllM::DIV2, + mul_n: PllN::MUL72, div_p: None, div_q: pllq_div, // Main system clock at 144 MHz - div_r: Some(PllR::Div2), + div_r: Some(PllR::DIV2), }); config.rcc.mux = ClockSrc::PLL; diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 4e92d064..2f445476 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -9,7 +9,9 @@ use embassy_net::{Ipv4Address, Stack, StackResources}; use embassy_stm32::eth::generic_smi::GenericSMI; use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; -use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, +}; use embassy_stm32::rng::Rng; use embassy_stm32::time::Hertz; use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; @@ -42,10 +44,10 @@ async fn main(spawner: Spawner) -> ! { }); config.rcc.pll1 = Some(Pll { source: PllSource::Hse, - prediv: 2, - mul: 125, - divp: Some(2), - divq: Some(2), + prediv: PllPreDiv::DIV2, + mul: PllMul::MUL125, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV2), divr: None, }); config.rcc.ahb_pre = AHBPrescaler::DIV1; diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index cbe540a0..3b3c38e1 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs @@ -4,7 +4,9 @@ use defmt::{panic, *}; use embassy_executor::Spawner; -use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; +use embassy_stm32::rcc::{ + AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, +}; use embassy_stm32::time::Hertz; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; @@ -29,9 +31,9 @@ async fn main(_spawner: Spawner) { }); config.rcc.pll1 = Some(Pll { source: PllSource::Hse, - prediv: 2, - mul: 125, - divp: Some(2), // 250mhz + prediv: PllPreDiv::DIV2, + mul: PllMul::MUL125, + divp: Some(PllDiv::DIV2), // 250mhz divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index 77922d4b..7859b86d 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs @@ -18,16 +18,16 @@ async fn main(_spawner: Spawner) { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // SPI1 cksel defaults to pll1_q + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q divr: None, }); config.rcc.pll2 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV8), // 100mhz divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 64ca65a0..40ef16cf 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -32,10 +32,10 @@ async fn main(_spawner: Spawner) { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // 100mhz divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs index 93df7a31..82122189 100644 --- a/examples/stm32h7/src/bin/dac.rs +++ b/examples/stm32h7/src/bin/dac.rs @@ -20,16 +20,16 @@ fn main() -> ! { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // SPI1 cksel defaults to pll1_q + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // 100mhz divr: None, }); config.rcc.pll2 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV8), // 100mhz divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 8c921abc..933641ae 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -28,16 +28,16 @@ async fn main(spawner: Spawner) { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // SPI1 cksel defaults to pll1_q + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // 100mhz divr: None, }); config.rcc.pll2 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV8), // 100mhz divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 1b5d71ed..a6603d50 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -39,9 +39,9 @@ async fn main(spawner: Spawner) -> ! { config.rcc.hsi48 = true; // needed for RNG config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 3abd31c7..596de2f4 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -40,9 +40,9 @@ async fn main(spawner: Spawner) -> ! { config.rcc.hsi48 = true; // needed for RNG config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs index de0b351d..7ae87b02 100644 --- a/examples/stm32h7/src/bin/fmc.rs +++ b/examples/stm32h7/src/bin/fmc.rs @@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // 100mhz divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index a1e955c3..f4fa0690 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) { config.rcc.hsi48 = true; // needed for RNG config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // 100 Mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // 100mhz divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index 5c8e57aa..37e4c92c 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs @@ -21,9 +21,9 @@ async fn main(_spawner: Spawner) { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), divq: None, divr: None, }); diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs index 752aefdf..ecb8d654 100644 --- a/examples/stm32h7/src/bin/sdmmc.rs +++ b/examples/stm32h7/src/bin/sdmmc.rs @@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) -> ! { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(4), // default clock chosen by SDMMCSEL. 200 Mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index 9fe46f03..f128d4a5 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs @@ -44,10 +44,10 @@ fn main() -> ! { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(4), // used by SPI3. 100Mhz. + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 88d65d5b..d4c0bcdb 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs @@ -40,10 +40,10 @@ fn main() -> ! { config.rcc.csi = true; config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(4), // used by SPI3. 100Mhz. + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. divr: None, }); config.rcc.sys = Sysclk::Pll1P; // 400 Mhz diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs index 14de4356..c1e5144b 100644 --- a/examples/stm32h7/src/bin/usb_serial.rs +++ b/examples/stm32h7/src/bin/usb_serial.rs @@ -28,9 +28,9 @@ async fn main(_spawner: Spawner) { config.rcc.hsi48 = true; // needed for USB config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), divq: None, divr: None, }); diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs index 806e49f5..d0208d8a 100644 --- a/examples/stm32l4/src/bin/rng.rs +++ b/examples/stm32l4/src/bin/rng.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv}; use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use {defmt_rtt as _, panic_probe as _}; @@ -19,10 +19,10 @@ async fn main(_spawner: Spawner) { // 72Mhz clock (16 / 1 * 18 / 4) config.rcc.mux = ClockSrc::PLL( PLLSource::HSI16, - PLLClkDiv::Div4, - PLLSrcDiv::Div1, - PLLMul::Mul18, - Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) + PllRDiv::DIV4, + PllPreDiv::DIV1, + PllMul::MUL18, + Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) ); let p = embassy_stm32::init(config); diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index eb1eed01..7e2b8c78 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, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use embassy_stm32::rcc::{self, ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::time::Hertz; use embassy_stm32::Config; @@ -18,9 +18,9 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); config.rcc.mux = ClockSrc::PLL( PLLSource::HSE(Hertz::mhz(8)), - PLLClkDiv::Div2, - PLLSrcDiv::Div1, - PLLMul::Mul20, + PllRDiv::DIV2, + PllPreDiv::DIV1, + PllMul::MUL20, None, ); config.rcc.lse = Some(Hertz(32_768)); diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index ba4a9d23..8db89be2 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -49,7 +49,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; use embedded_hal_bus::spi::ExclusiveDevice; use hal::gpio::Pull; use hal::i2c::Config as I2C_Config; -use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use hal::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; use hal::spi::{Config as SPI_Config, Spi}; use hal::time::Hertz; @@ -80,9 +80,9 @@ async fn main(spawner: Spawner) { // 80MHz highest frequency for flash 0 wait. config.rcc.mux = ClockSrc::PLL( PLLSource::HSE(Hertz(8_000_000)), - PLLClkDiv::Div2, - PLLSrcDiv::Div1, - PLLMul::Mul20, + PllRDiv::DIV2, + PllPreDiv::DIV1, + PllMul::MUL20, None, ); config.rcc.hsi48 = true; // needed for rng diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs index 410d6891..dc0d98ad 100644 --- a/examples/stm32l4/src/bin/usb_serial.rs +++ b/examples/stm32l4/src/bin/usb_serial.rs @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut config = Config::default(); - config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); + config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); config.rcc.hsi48 = true; let p = embassy_stm32::init(config); diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs index 9549d64d..cc3c99b5 100644 --- a/examples/stm32l5/src/bin/rng.rs +++ b/examples/stm32l5/src/bin/rng.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv}; use embassy_stm32::rng::Rng; use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use {defmt_rtt as _, panic_probe as _}; @@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); config.rcc.mux = ClockSrc::PLL( PLLSource::HSI16, - PLLClkDiv::Div2, - PLLSrcDiv::Div1, - PLLMul::Mul8, - Some(PLLClkDiv::Div2), + PllRDiv::DIV2, + PllPreDiv::DIV1, + PllMul::MUL8, + Some(PllQDiv::DIV2), ); let p = embassy_stm32::init(config); diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 15b84761..498147f9 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -45,7 +45,7 @@ async fn net_task(stack: &'static Stack>) -> ! { #[embassy_executor::main] async fn main(spawner: Spawner) { let mut config = Config::default(); - config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); + config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); config.rcc.hsi48 = true; let p = embassy_stm32::init(config); diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index 7e894e40..db6a9c76 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs @@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); + config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); config.rcc.hsi48 = true; let p = embassy_stm32::init(config); diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs index 0c719560..e19ecbf0 100644 --- a/examples/stm32l5/src/bin/usb_serial.rs +++ b/examples/stm32l5/src/bin/usb_serial.rs @@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); + config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); config.rcc.hsi48 = true; let p = embassy_stm32::init(config); diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index 278bd30f..9b2adb0a 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs @@ -25,9 +25,9 @@ async fn main(_spawner: Spawner) { let mut config = Config::default(); config.rcc.mux = ClockSrc::PLL1R(PllConfig { source: PllSrc::HSI16, - m: PllM::Div2, - n: PllN::Mul10, - r: PllClkDiv::NotDivided, + m: Pllm::DIV2, + n: Plln::MUL10, + r: Plldiv::DIV1, }); //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); config.rcc.hsi48 = true; diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 32ba03e4..79a9b5e8 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -202,9 +202,9 @@ pub fn config() -> Config { // 1 MHz PLL input * 240 = 240 MHz PLL VCO mul: unwrap!(PLLMul::try_from(240)), // 240 MHz PLL VCO / 2 = 120 MHz main PLL output - main_div: PLLMainDiv::Div2, + p_div: PLLPDiv::DIV2, // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output - pll48_div: unwrap!(PLL48Div::try_from(5)), + q_div: PLLQDiv::DIV5, }; // System clock comes from PLL (= the 120 MHz main PLL output) config.rcc.mux = ClockSrc::PLL; @@ -239,10 +239,10 @@ pub fn config() -> Config { }); config.rcc.pll1 = Some(Pll { source: PllSource::Hse, - prediv: 2, - mul: 125, - divp: Some(2), - divq: Some(2), + prediv: PllPreDiv::DIV2, + mul: PllMul::MUL125, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV2), divr: None, }); config.rcc.ahb_pre = AHBPrescaler::DIV1; @@ -261,16 +261,16 @@ pub fn config() -> Config { config.rcc.hsi48 = true; // needed for RNG config.rcc.pll_src = PllSource::Hsi; config.rcc.pll1 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(2), - divq: Some(8), // SPI1 cksel defaults to pll1_q + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV2), + divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q divr: None, }); config.rcc.pll2 = Some(Pll { - prediv: 4, - mul: 50, - divp: Some(8), // 100mhz + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL50, + divp: Some(PllDiv::DIV8), // 100mhz divq: None, divr: None, }); @@ -290,10 +290,10 @@ pub fn config() -> Config { config.rcc.mux = ClockSrc::PLL( // 72Mhz clock (16 / 1 * 18 / 4) PLLSource::HSI16, - PLLClkDiv::Div4, - PLLSrcDiv::Div1, - PLLMul::Mul18, - Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) + PllRDiv::DIV4, + PllPreDiv::DIV1, + PllMul::MUL18, + Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) ); } @@ -303,9 +303,9 @@ pub fn config() -> Config { config.rcc.mux = ClockSrc::PLL( // 110Mhz clock (16 / 4 * 55 / 2) PLLSource::HSI16, - PLLClkDiv::Div2, - PLLSrcDiv::Div4, - PLLMul::Mul55, + PllRDiv::DIV2, + PllPreDiv::DIV4, + PllMul::MUL55, None, ); } @@ -313,7 +313,7 @@ pub fn config() -> Config { #[cfg(feature = "stm32u585ai")] { use embassy_stm32::rcc::*; - config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); + config.rcc.mux = ClockSrc::MSI(Msirange::RANGE_48MHZ); } #[cfg(feature = "stm32l073rz")]