Merge pull request #2063 from embassy-rs/rcc-no-spaghetti

stm32/rcc: port L4 to the "flattened" API like h5/h7.
This commit is contained in:
Dario Nieuwenhuis 2023-10-15 01:12:46 +00:00 committed by GitHub
commit c46e758e2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 275 additions and 194 deletions

View File

@ -1,9 +1,8 @@
use crate::pac::rcc::regs::Cfgr; use crate::pac::rcc::regs::Cfgr;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
Pllr as PllRDiv, Ppre as APBPrescaler, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
}; };
use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw};
use crate::pac::{FLASH, RCC}; use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks}; use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz; use crate::time::Hertz;
@ -11,42 +10,47 @@ use crate::time::Hertz;
/// HSI speed /// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000); pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// System clock mux source
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum ClockSrc { pub struct Pll {
MSI(MSIRange), /// PLL pre-divider (DIVM).
PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>), pub prediv: PllPreDiv,
HSE(Hertz),
HSI16,
}
/// PLL clock input source /// PLL multiplication factor.
#[derive(Clone, Copy)] pub mul: PllMul,
pub enum PLLSource {
HSI16,
HSE(Hertz),
MSI(MSIRange),
}
impl From<PLLSource> for Pllsrc { /// PLL P division factor. If None, PLL P output is disabled.
fn from(val: PLLSource) -> Pllsrc { pub divp: Option<PllPDiv>,
match val { /// PLL Q division factor. If None, PLL Q output is disabled.
PLLSource::HSI16 => Pllsrc::HSI16, pub divq: Option<PllQDiv>,
PLLSource::HSE(_) => Pllsrc::HSE, /// PLL R division factor. If None, PLL R output is disabled.
PLLSource::MSI(_) => Pllsrc::MSI, pub divr: Option<PllRDiv>,
}
}
} }
/// Clocks configutation /// Clocks configutation
pub struct Config { pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
pub hsi16: bool,
pub hse: Option<Hertz>,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
pub hsi48: bool,
// pll
pub pll_src: PLLSource,
pub pll: Option<Pll>,
pub pllsai1: Option<Pll>,
#[cfg(any(
stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
))]
pub pllsai2: Option<Pll>,
// sysclk, buses.
pub mux: ClockSrc, pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler, pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler, pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler, pub apb2_pre: APBPrescaler,
pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] // low speed LSI/LSE/RTC
pub hsi48: bool,
pub ls: super::LsConfig, pub ls: super::LsConfig,
} }
@ -54,11 +58,20 @@ impl Default for Config {
#[inline] #[inline]
fn default() -> Config { fn default() -> Config {
Config { Config {
mux: ClockSrc::MSI(MSIRange::RANGE4M), hse: None,
hsi16: false,
msi: Some(MSIRange::RANGE4M),
mux: ClockSrc::MSI,
ahb_pre: AHBPrescaler::DIV1, ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1, apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1, apb2_pre: APBPrescaler::DIV1,
pll_src: PLLSource::NONE,
pll: None,
pllsai1: None, pllsai1: None,
#[cfg(any(
stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
))]
pllsai2: None,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
hsi48: false, hsi48: false,
ls: Default::default(), ls: Default::default(),
@ -80,17 +93,16 @@ pub(crate) unsafe fn init(config: Config) {
// Wait until MSI is running // Wait until MSI is running
while !RCC.cr().read().msirdy() {} while !RCC.cr().read().msirdy() {}
} }
if RCC.cfgr().read().sws() != Sw::MSI { if RCC.cfgr().read().sws() != ClockSrc::MSI {
// Set MSI as a clock source, reset prescalers. // Set MSI as a clock source, reset prescalers.
RCC.cfgr().write_value(Cfgr::default()); RCC.cfgr().write_value(Cfgr::default());
// Wait for clock switch status bits to change. // Wait for clock switch status bits to change.
while RCC.cfgr().read().sws() != Sw::MSI {} while RCC.cfgr().read().sws() != ClockSrc::MSI {}
} }
let rtc = config.ls.init(); let rtc = config.ls.init();
let (sys_clk, sw) = match config.mux { let msi = config.msi.map(|range| {
ClockSrc::MSI(range) => {
// Enable MSI // Enable MSI
RCC.cr().write(|w| { RCC.cr().write(|w| {
w.set_msirange(range); w.set_msirange(range);
@ -104,129 +116,180 @@ pub(crate) unsafe fn init(config: Config) {
// Enable as clock source for USB, RNG if running at 48 MHz // Enable as clock source for USB, RNG if running at 48 MHz
if range == MSIRange::RANGE48M { if range == MSIRange::RANGE48M {
RCC.ccipr().modify(|w| { RCC.ccipr().modify(|w| w.set_clk48sel(0b11));
w.set_clk48sel(0b11);
});
} }
(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, Sw::HSI16)
}
ClockSrc::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
(freq, Sw::HSE)
}
ClockSrc::PLL(src, 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
}
PLLSource::HSI16 => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
}
PLLSource::MSI(range) => {
// Enable MSI
RCC.cr().write(|w| {
w.set_msirange(range);
w.set_msipllen(false); // should be turned on if LSE is started
w.set_msirgsel(true);
w.set_msion(true);
});
while !RCC.cr().read().msirdy() {}
msirange_to_hertz(range) msirange_to_hertz(range)
}
};
// Disable PLL
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
let freq = src_freq / prediv * mul / divr;
#[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
assert!(freq.0 <= 120_000_000);
#[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
assert!(freq.0 <= 80_000_000);
RCC.pllcfgr().write(move |w| {
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 let hsi16 = config.hsi16.then(|| {
if let Some(divq) = divq { RCC.cr().write(|w| w.set_hsion(true));
let freq = src_freq / prediv * mul / divq; while !RCC.cr().read().hsirdy() {}
assert!(freq.0 == 48_000_000);
RCC.ccipr().modify(|w| {
w.set_clk48sel(0b10);
});
}
if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { HSI_FREQ
RCC.pllsai1cfgr().write(move |w| {
w.set_plln(mul);
w.set_pllm(prediv);
if let Some(r_div) = r_div {
w.set_pllr(r_div);
w.set_pllren(true);
}
if let Some(q_div) = q_div {
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_pllp(p_div);
w.set_pllpen(true);
}
}); });
RCC.cr().modify(|w| w.set_pllsai1on(true)); let hse = config.hse.map(|freq| {
} RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
// Enable PLL freq
RCC.cr().modify(|w| w.set_pllon(true)); });
while !RCC.cr().read().pllrdy() {}
RCC.pllcfgr().modify(|w| w.set_pllren(true));
(freq, Sw::PLL)
}
};
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
if config.hsi48 { let _hsi48 = config.hsi48.then(|| {
RCC.crrcr().modify(|w| w.set_hsi48on(true)); RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {} while !RCC.crrcr().read().hsi48rdy() {}
// Enable as clock source for USB, RNG and SDMMC // Enable as clock source for USB, RNG and SDMMC
RCC.ccipr().modify(|w| w.set_clk48sel(0)); RCC.ccipr().modify(|w| w.set_clk48sel(0));
Hertz(48_000_000)
});
let pll_src = match config.pll_src {
PLLSource::NONE => None,
PLLSource::HSE => hse,
PLLSource::HSI16 => hsi16,
PLLSource::MSI => msi,
};
let mut _pllp = None;
let mut _pllq = None;
let mut _pllr = None;
if let Some(pll) = config.pll {
let pll_src = pll_src.unwrap();
// Disable PLL
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
let vco_freq = pll_src / pll.prediv * pll.mul;
_pllp = pll.divp.map(|div| vco_freq / div);
_pllq = pll.divq.map(|div| vco_freq / div);
_pllr = pll.divr.map(|div| vco_freq / div);
RCC.pllcfgr().write(move |w| {
w.set_plln(pll.mul);
w.set_pllm(pll.prediv);
w.set_pllsrc(config.pll_src);
if let Some(divp) = pll.divp {
w.set_pllp(divp);
w.set_pllpen(true);
} }
if let Some(divq) = pll.divq {
w.set_pllq(divq);
w.set_pllqen(true);
}
if let Some(divr) = pll.divr {
w.set_pllr(divr);
w.set_pllren(true);
}
});
if _pllq == Some(Hertz(48_000_000)) {
RCC.ccipr().modify(|w| w.set_clk48sel(0b10));
}
// Enable PLL
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
} else {
// even if we're not using the main pll, set the source for pllsai
RCC.pllcfgr().write(move |w| {
w.set_pllsrc(config.pll_src);
});
}
if let Some(pll) = config.pllsai1 {
let pll_src = pll_src.unwrap();
// Disable PLL
RCC.cr().modify(|w| w.set_pllsai1on(false));
while RCC.cr().read().pllsai1rdy() {}
let vco_freq = pll_src / pll.prediv * pll.mul;
let _pllp = pll.divp.map(|div| vco_freq / div);
let _pllq = pll.divq.map(|div| vco_freq / div);
let _pllr = pll.divr.map(|div| vco_freq / div);
RCC.pllsai1cfgr().write(move |w| {
w.set_plln(pll.mul);
w.set_pllm(pll.prediv);
if let Some(divp) = pll.divp {
w.set_pllp(divp);
w.set_pllpen(true);
}
if let Some(divq) = pll.divq {
w.set_pllq(divq);
w.set_pllqen(true);
}
if let Some(divr) = pll.divr {
w.set_pllr(divr);
w.set_pllren(true);
}
});
if _pllq == Some(Hertz(48_000_000)) {
RCC.ccipr().modify(|w| w.set_clk48sel(0b01));
}
// Enable PLL
RCC.cr().modify(|w| w.set_pllsai1on(true));
while !RCC.cr().read().pllsai1rdy() {}
}
#[cfg(any(
stm32l47x, stm32l48x, stm32l49x, stm32l4ax, stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx
))]
if let Some(pll) = config.pllsai2 {
let pll_src = pll_src.unwrap();
// Disable PLL
RCC.cr().modify(|w| w.set_pllsai2on(false));
while RCC.cr().read().pllsai2rdy() {}
let vco_freq = pll_src / pll.prediv * pll.mul;
let _pllp = pll.divp.map(|div| vco_freq / div);
let _pllq = pll.divq.map(|div| vco_freq / div);
let _pllr = pll.divr.map(|div| vco_freq / div);
RCC.pllsai2cfgr().write(move |w| {
w.set_plln(pll.mul);
w.set_pllm(pll.prediv);
if let Some(divp) = pll.divp {
w.set_pllp(divp);
w.set_pllpen(true);
}
if let Some(divq) = pll.divq {
w.set_pllq(divq);
w.set_pllqen(true);
}
if let Some(divr) = pll.divr {
w.set_pllr(divr);
w.set_pllren(true);
}
});
// Enable PLL
RCC.cr().modify(|w| w.set_pllsai2on(true));
while !RCC.cr().read().pllsai2rdy() {}
}
let sys_clk = match config.mux {
ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI16 => hsi16.unwrap(),
ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL => _pllr.unwrap(),
};
#[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
assert!(sys_clk.0 <= 120_000_000);
#[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
assert!(sys_clk.0 <= 80_000_000);
// Set flash wait states // Set flash wait states
FLASH.acr().modify(|w| { FLASH.acr().modify(|w| {
@ -240,7 +303,7 @@ pub(crate) unsafe fn init(config: Config) {
}); });
RCC.cfgr().modify(|w| { RCC.cfgr().modify(|w| {
w.set_sw(sw); w.set_sw(config.mux);
w.set_hpre(config.ahb_pre); w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre); w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre); w.set_ppre2(config.apb2_pre);
@ -277,7 +340,7 @@ pub(crate) unsafe fn init(config: Config) {
}); });
} }
fn msirange_to_hertz(range: Msirange) -> Hertz { fn msirange_to_hertz(range: MSIRange) -> Hertz {
match range { match range {
MSIRange::RANGE100K => Hertz(100_000), MSIRange::RANGE100K => Hertz(100_000),
MSIRange::RANGE200K => Hertz(200_000), MSIRange::RANGE200K => Hertz(200_000),

View File

@ -4,7 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv}; use embassy_stm32::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv};
use embassy_stm32::rng::Rng; use embassy_stm32::rng::Rng;
use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use embassy_stm32::{bind_interrupts, peripherals, rng, Config};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -16,14 +16,16 @@ bind_interrupts!(struct Irqs {
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
// 72Mhz clock (16 / 1 * 18 / 4) config.rcc.mux = ClockSrc::PLL;
config.rcc.mux = ClockSrc::PLL( config.rcc.hsi16 = true;
PLLSource::HSI16, config.rcc.pll_src = PLLSource::HSI16;
PllRDiv::DIV4, config.rcc.pll = Some(Pll {
PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
PllMul::MUL18, mul: PllMul::MUL18,
Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) divp: None,
); divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
});
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
info!("Hello World!"); info!("Hello World!");

View File

@ -5,7 +5,7 @@
use chrono::{NaiveDate, NaiveDateTime}; use chrono::{NaiveDate, NaiveDateTime};
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, PllMul, PllPreDiv, PllRDiv}; use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use embassy_stm32::rtc::{Rtc, RtcConfig}; use embassy_stm32::rtc::{Rtc, RtcConfig};
use embassy_stm32::time::Hertz; use embassy_stm32::time::Hertz;
use embassy_stm32::Config; use embassy_stm32::Config;
@ -14,18 +14,20 @@ use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = {
let mut config = Config::default(); let mut config = Config::default();
config.rcc.mux = ClockSrc::PLL( config.rcc.mux = ClockSrc::PLL;
PLLSource::HSE(Hertz::mhz(8)), config.rcc.hse = Some(Hertz::mhz(8));
PllRDiv::DIV2, config.rcc.pll_src = PLLSource::HSE;
PllPreDiv::DIV1, config.rcc.pll = Some(Pll {
PllMul::MUL20, prediv: PllPreDiv::DIV1,
None, mul: PllMul::MUL20,
); divp: None,
divq: None,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
});
config.rcc.ls = LsConfig::default_lse(); config.rcc.ls = LsConfig::default_lse();
embassy_stm32::init(config) let p = embassy_stm32::init(config);
};
info!("Hello World!"); info!("Hello World!");
let now = NaiveDate::from_ymd_opt(2020, 5, 15) let now = NaiveDate::from_ymd_opt(2020, 5, 15)

View File

@ -48,7 +48,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
use embedded_hal_bus::spi::ExclusiveDevice; use embedded_hal_bus::spi::ExclusiveDevice;
use hal::gpio::Pull; use hal::gpio::Pull;
use hal::i2c::Config as I2C_Config; use hal::i2c::Config as I2C_Config;
use hal::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use hal::spi::{Config as SPI_Config, Spi}; use hal::spi::{Config as SPI_Config, Spi};
use hal::time::Hertz; use hal::time::Hertz;
@ -77,13 +77,16 @@ async fn main(spawner: Spawner) {
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
// 80MHz highest frequency for flash 0 wait. // 80MHz highest frequency for flash 0 wait.
config.rcc.mux = ClockSrc::PLL( config.rcc.mux = ClockSrc::PLL;
PLLSource::HSE(Hertz(8_000_000)), config.rcc.hse = Some(Hertz::mhz(8));
PllRDiv::DIV2, config.rcc.pll_src = PLLSource::HSE;
PllPreDiv::DIV1, config.rcc.pll = Some(Pll {
PllMul::MUL20, prediv: PllPreDiv::DIV1,
None, mul: PllMul::MUL20,
); divp: None,
divq: None,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
});
config.rcc.hsi48 = true; // needed for rng config.rcc.hsi48 = true; // needed for rng
let dp = embassy_stm32::init(config); let dp = embassy_stm32::init(config);

View File

@ -23,8 +23,17 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let mut config = Config::default(); let mut config = Config::default();
config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None);
config.rcc.hsi48 = true; config.rcc.hsi48 = true;
config.rcc.mux = ClockSrc::PLL;
config.rcc.hsi16 = true;
config.rcc.pll_src = PLLSource::HSI16;
config.rcc.pll = Some(Pll {
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL10,
divp: None,
divq: None,
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
});
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);

View File

@ -284,17 +284,19 @@ pub fn config() -> Config {
config.rcc.adc_clock_source = AdcClockSource::PLL2_P; config.rcc.adc_clock_source = AdcClockSource::PLL2_P;
} }
#[cfg(any(feature = "stm32l4a6zg", feature = "stm32l4r5zi"))] #[cfg(any(feature = "stm32l496zg", feature = "stm32l4a6zg", feature = "stm32l4r5zi"))]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::PLL( config.rcc.mux = ClockSrc::PLL;
// 72Mhz clock (16 / 1 * 18 / 4) config.rcc.hsi16 = true;
PLLSource::HSI16, config.rcc.pll_src = PLLSource::HSI16;
PllRDiv::DIV4, config.rcc.pll = Some(Pll {
PllPreDiv::DIV1, prediv: PllPreDiv::DIV1,
PllMul::MUL18, mul: PllMul::MUL18,
Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) divp: None,
); divq: Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6)
divr: Some(PllRDiv::DIV4), // sysclk 72Mhz clock (16 / 1 * 18 / 4)
});
} }
#[cfg(any(feature = "stm32l552ze"))] #[cfg(any(feature = "stm32l552ze"))]