714: add more clock options for l4 and l5 r=Dirbaio a=ant32

- added an assert so it panics if pll48div is not 48Mhz
- added MSI as a clock source for PLL
- removed hsi48 option for MCUs mentioned in l4 rcc presentation
- copied some code from l4 to l5, but don't have a way of testing it.

Co-authored-by: Philip A Reimer <antreimer@gmail.com>
This commit is contained in:
bors[bot] 2022-04-12 21:42:36 +00:00 committed by GitHub
commit 6d0e6d563d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 5 deletions

View file

@ -96,6 +96,7 @@ pub enum APBPrescaler {
pub enum PLLSource { pub enum PLLSource {
HSI16, HSI16,
HSE(Hertz), HSE(Hertz),
MSI(MSIRange),
} }
seq_macro::seq!(N in 8..=86 { seq_macro::seq!(N in 8..=86 {
@ -192,6 +193,7 @@ impl From<PLLSource> for Pllsrc {
match val { match val {
PLLSource::HSI16 => Pllsrc::HSI16, PLLSource::HSI16 => Pllsrc::HSI16,
PLLSource::HSE(_) => Pllsrc::HSE, PLLSource::HSE(_) => Pllsrc::HSE,
PLLSource::MSI(_) => Pllsrc::MSI,
} }
} }
} }
@ -275,6 +277,7 @@ pub struct Config {
Option<PLLSAI1QDiv>, Option<PLLSAI1QDiv>,
Option<PLLSAI1PDiv>, Option<PLLSAI1PDiv>,
)>, )>,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
pub hsi48: bool, pub hsi48: bool,
} }
@ -287,6 +290,7 @@ impl Default for Config {
apb1_pre: APBPrescaler::NotDivided, apb1_pre: APBPrescaler::NotDivided,
apb2_pre: APBPrescaler::NotDivided, apb2_pre: APBPrescaler::NotDivided,
pllsai1: None, pllsai1: None,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
hsi48: false, hsi48: false,
} }
} }
@ -341,6 +345,18 @@ pub(crate) unsafe fn init(config: Config) {
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
HSI16_FREQ HSI16_FREQ
} }
PLLSource::MSI(range) => {
// Enable MSI
RCC.cr().write(|w| {
let bits: Msirange = range.into();
w.set_msirange(bits);
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() {}
range.into()
}
}; };
// Disable PLL // Disable PLL
@ -366,7 +382,9 @@ pub(crate) unsafe fn init(config: Config) {
}); });
// Enable as clock source for USB, RNG if PLL48 divisor is provided // Enable as clock source for USB, RNG if PLL48 divisor is provided
if pll48div.is_some() { if let Some(pll48div) = pll48div {
let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
assert!(freq == 48_000_000);
RCC.ccipr().modify(|w| { RCC.ccipr().modify(|w| {
w.set_clk48sel(0b10); w.set_clk48sel(0b10);
}); });
@ -408,6 +426,7 @@ pub(crate) unsafe fn init(config: Config) {
} }
}; };
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
if config.hsi48 { if config.hsi48 {
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() {}

View file

@ -96,6 +96,7 @@ pub enum APBPrescaler {
pub enum PLLSource { pub enum PLLSource {
HSI16, HSI16,
HSE(Hertz), HSE(Hertz),
MSI(MSIRange),
} }
seq_macro::seq!(N in 8..=86 { seq_macro::seq!(N in 8..=86 {
@ -192,6 +193,7 @@ impl From<PLLSource> for Pllsrc {
match val { match val {
PLLSource::HSI16 => Pllsrc::HSI16, PLLSource::HSI16 => Pllsrc::HSI16,
PLLSource::HSE(_) => Pllsrc::HSE, PLLSource::HSE(_) => Pllsrc::HSE,
PLLSource::MSI(_) => Pllsrc::MSI,
} }
} }
} }
@ -275,6 +277,7 @@ pub struct Config {
Option<PLLSAI1QDiv>, Option<PLLSAI1QDiv>,
Option<PLLSAI1PDiv>, Option<PLLSAI1PDiv>,
)>, )>,
pub hsi48: bool,
} }
impl Default for Config { impl Default for Config {
@ -286,6 +289,7 @@ impl Default for Config {
apb1_pre: APBPrescaler::NotDivided, apb1_pre: APBPrescaler::NotDivided,
apb2_pre: APBPrescaler::NotDivided, apb2_pre: APBPrescaler::NotDivided,
pllsai1: None, pllsai1: None,
hsi48: false,
} }
} }
} }
@ -339,6 +343,18 @@ pub(crate) unsafe fn init(config: Config) {
while !RCC.cr().read().hsirdy() {} while !RCC.cr().read().hsirdy() {}
HSI16_FREQ HSI16_FREQ
} }
PLLSource::MSI(range) => {
// Enable MSI
RCC.cr().write(|w| {
let bits: Msirange = range.into();
w.set_msirange(bits);
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() {}
range.into()
}
}; };
// Disable PLL // Disable PLL
@ -364,7 +380,9 @@ pub(crate) unsafe fn init(config: Config) {
}); });
// Enable as clock source for USB, RNG if PLL48 divisor is provided // Enable as clock source for USB, RNG if PLL48 divisor is provided
if pll48div.is_some() { if let Some(pll48div) = pll48div {
let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div();
assert!(freq == 48_000_000);
RCC.ccipr1().modify(|w| { RCC.ccipr1().modify(|w| {
w.set_clk48msel(0b10); w.set_clk48msel(0b10);
}); });
@ -406,6 +424,14 @@ pub(crate) unsafe fn init(config: Config) {
} }
}; };
if config.hsi48 {
RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {}
// Enable as clock source for USB, RNG and SDMMC
RCC.ccipr1().modify(|w| w.set_clk48msel(0));
}
// Set flash wait states // Set flash wait states
// VCORE Range 0 (performance), others TODO // VCORE Range 0 (performance), others TODO
FLASH.acr().modify(|w| { FLASH.acr().modify(|w| {

View file

@ -12,12 +12,13 @@ use panic_probe as _;
fn config() -> Config { fn config() -> Config {
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(
PLLSource::HSI16, PLLSource::HSI16,
PLLClkDiv::Div2, PLLClkDiv::Div4,
PLLSrcDiv::Div1, PLLSrcDiv::Div1,
PLLMul::Mul8, PLLMul::Mul18,
Some(PLLClkDiv::Div2), Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6)
); );
config config
} }