stm32/rcc: switch to modern api for l0, l1.

This commit is contained in:
Dario Nieuwenhuis 2023-11-05 03:06:13 +01:00
parent 056c409443
commit 8911a4d855
8 changed files with 124 additions and 112 deletions

View File

@ -1,8 +1,8 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale; pub use crate::pac::pwr::vals::Vos as VoltageScale;
pub use crate::pac::rcc::vals::{ pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler, Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Plldiv as PllDiv, Pllmul as PLLMul, Pllmul as PllMul,
Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
}; };
use crate::pac::rcc::vals::{Pllsrc, Sw};
#[cfg(crs)] #[cfg(crs)]
use crate::pac::{crs, CRS, SYSCFG}; use crate::pac::{crs, CRS, SYSCFG};
use crate::pac::{FLASH, PWR, RCC}; use crate::pac::{FLASH, PWR, RCC};
@ -12,39 +12,50 @@ 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, Eq, PartialEq)]
#[derive(Clone, Copy)] pub enum HseMode {
pub enum ClockSrc { /// crystal/ceramic oscillator (HSEBYP=0)
MSI(MSIRange), Oscillator,
PLL(PLLSource, PLLMul, PLLDiv), /// external analog clock (low swing) (HSEBYP=1)
HSE(Hertz), Bypass,
HSI,
} }
/// PLL clock input source #[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy)] pub struct Hse {
pub enum PLLSource { /// HSE frequency.
HSI, pub freq: Hertz,
HSE(Hertz), /// HSE mode.
pub mode: HseMode,
} }
impl From<PLLSource> for Pllsrc { #[derive(Clone, Copy)]
fn from(val: PLLSource) -> Pllsrc { pub struct Pll {
match val { /// PLL source
PLLSource::HSI => Pllsrc::HSI, pub source: PLLSource,
PLLSource::HSE(_) => Pllsrc::HSE,
} /// PLL multiplication factor.
} pub mul: PllMul,
/// PLL main output division factor.
pub div: PllDiv,
} }
/// Clocks configutation /// Clocks configutation
pub struct Config { pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
pub hsi: bool,
pub hse: Option<Hse>,
#[cfg(crs)]
pub hsi48: bool,
pub pll: Option<Pll>,
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,
#[cfg(crs)]
pub enable_hsi48: bool,
pub ls: super::LsConfig, pub ls: super::LsConfig,
pub voltage_scale: VoltageScale, pub voltage_scale: VoltageScale,
} }
@ -53,12 +64,18 @@ impl Default for Config {
#[inline] #[inline]
fn default() -> Config { fn default() -> Config {
Config { Config {
mux: ClockSrc::MSI(MSIRange::RANGE5), msi: Some(MSIRange::RANGE5),
hse: None,
hsi: false,
#[cfg(crs)]
hsi48: false,
pll: None,
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,
#[cfg(crs)]
enable_hsi48: false,
voltage_scale: VoltageScale::RANGE1, voltage_scale: VoltageScale::RANGE1,
ls: Default::default(), ls: Default::default(),
} }
@ -71,71 +88,67 @@ pub(crate) unsafe fn init(config: Config) {
PWR.cr().write(|w| w.set_vos(config.voltage_scale)); PWR.cr().write(|w| w.set_vos(config.voltage_scale));
while PWR.csr().read().vosf() {} while PWR.csr().read().vosf() {}
let (sys_clk, sw) = match config.mux { let rtc = config.ls.init();
ClockSrc::MSI(range) => {
// Set MSI range
RCC.icscr().write(|w| w.set_msirange(range));
// Enable MSI let msi = config.msi.map(|range| {
RCC.cr().write(|w| w.set_msion(true)); RCC.icscr().modify(|w| w.set_msirange(range));
RCC.cr().modify(|w| w.set_msion(true));
while !RCC.cr().read().msirdy() {} while !RCC.cr().read().msirdy() {}
let freq = 32_768 * (1 << (range as u8 + 1)); Hertz(32_768 * (1 << (range as u8 + 1)))
(Hertz(freq), Sw::MSI) });
}
ClockSrc::HSI => { let hsi = config.hsi.then(|| {
// Enable HSI RCC.cr().modify(|w| w.set_hsion(true));
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
(HSI_FREQ, Sw::HSI)
}
ClockSrc::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
(freq, Sw::HSE)
}
ClockSrc::PLL(src, mul, div) => {
let freq = match src {
PLLSource::HSE(freq) => {
// Enable HSE
RCC.cr().write(|w| w.set_hseon(true));
while !RCC.cr().read().hserdy() {}
freq
}
PLLSource::HSI => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ HSI_FREQ
} });
let hse = config.hse.map(|hse| {
RCC.cr().modify(|w| {
w.set_hsebyp(hse.mode == HseMode::Bypass);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
hse.freq
});
let pll = config.pll.map(|pll| {
let freq = match pll.source {
PLLSource::HSE => hse.unwrap(),
PLLSource::HSI => hsi.unwrap(),
}; };
// Disable PLL // Disable PLL
RCC.cr().modify(|w| w.set_pllon(false)); RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {} while RCC.cr().read().pllrdy() {}
let freq = freq * mul / div; let freq = freq * pll.mul / pll.div;
assert!(freq <= Hertz(32_000_000)); assert!(freq <= Hertz(32_000_000));
RCC.cfgr().write(move |w| { RCC.cfgr().write(move |w| {
w.set_pllmul(mul); w.set_pllmul(pll.mul);
w.set_plldiv(div); w.set_plldiv(pll.div);
w.set_pllsrc(src.into()); w.set_pllsrc(pll.source);
}); });
// Enable PLL // Enable PLL
RCC.cr().modify(|w| w.set_pllon(true)); RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {} while !RCC.cr().read().pllrdy() {}
(freq, Sw::PLL1_P) freq
} });
};
let rtc = config.ls.init(); let sys_clk = match config.mux {
ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI => hsi.unwrap(),
ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL1_P => pll.unwrap(),
};
let wait_states = match (config.voltage_scale, sys_clk.0) { let wait_states = match (config.voltage_scale, sys_clk.0) {
(VoltageScale::RANGE1, ..=16_000_000) => 0, (VoltageScale::RANGE1, ..=16_000_000) => 0,
@ -150,7 +163,7 @@ pub(crate) unsafe fn init(config: Config) {
FLASH.acr().modify(|w| w.set_latency(wait_states != 0)); FLASH.acr().modify(|w| w.set_latency(wait_states != 0));
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);
@ -161,7 +174,7 @@ pub(crate) unsafe fn init(config: Config) {
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre); let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(crs)] #[cfg(crs)]
if config.enable_hsi48 { if config.hsi48 {
// Reset CRS peripheral // Reset CRS peripheral
RCC.apb1rstr().modify(|w| w.set_crsrst(true)); RCC.apb1rstr().modify(|w| w.set_crsrst(true));
RCC.apb1rstr().modify(|w| w.set_crsrst(false)); RCC.apb1rstr().modify(|w| w.set_crsrst(false));

View File

@ -193,9 +193,6 @@ pub(crate) unsafe fn init(config: Config) {
}); });
while !RCC.cr().read().msirdy() {} while !RCC.cr().read().msirdy() {}
// Enable as clock source for USB, RNG if running at 48 MHz
if range == MSIRange::RANGE48M {}
msirange_to_hertz(range) msirange_to_hertz(range)
}); });

View File

@ -12,7 +12,7 @@ use {defmt_rtt as _, panic_probe as _};
#[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();
config.rcc.enable_hsi48 = true; config.rcc.hsi48 = true;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
let button = Input::new(p.PB2, Pull::Up); let button = Input::new(p.PB2, Pull::Up);

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true; config.rcc.hsi48 = true;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default(); let mut spi_config = spi::Config::default();

View File

@ -34,7 +34,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true; config.rcc.hsi48 = true;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default(); let mut spi_config = spi::Config::default();

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true; config.rcc.hsi48 = true;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default(); let mut spi_config = spi::Config::default();

View File

@ -24,7 +24,7 @@ const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriatel
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default(); let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI; config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI;
config.rcc.enable_hsi48 = true; config.rcc.hsi48 = true;
let p = embassy_stm32::init(config); let p = embassy_stm32::init(config);
let mut spi_config = spi::Config::default(); let mut spi_config = spi::Config::default();

View File

@ -460,23 +460,25 @@ pub fn config() -> Config {
#[cfg(feature = "stm32l073rz")] #[cfg(feature = "stm32l073rz")]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::PLL( config.rcc.hsi = true;
// 32Mhz clock (16 * 4 / 2) config.rcc.pll = Some(Pll {
PLLSource::HSI, source: PLLSource::HSI,
PLLMul::MUL4, mul: PLLMul::MUL4,
PLLDiv::DIV2, div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
); });
config.rcc.mux = ClockSrc::PLL1_P;
} }
#[cfg(any(feature = "stm32l152re"))] #[cfg(any(feature = "stm32l152re"))]
{ {
use embassy_stm32::rcc::*; use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::PLL( config.rcc.hsi = true;
// 32Mhz clock (16 * 4 / 2) config.rcc.pll = Some(Pll {
PLLSource::HSI, source: PLLSource::HSI,
PLLMul::MUL4, mul: PLLMul::MUL4,
PLLDiv::DIV2, div: PLLDiv::DIV2, // 32Mhz clock (16 * 4 / 2)
); });
config.rcc.mux = ClockSrc::PLL1_P;
} }
config config