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:
commit
c46e758e2c
@ -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,154 +93,204 @@ 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);
|
w.set_msirgsel(true);
|
||||||
w.set_msirgsel(true);
|
w.set_msion(true);
|
||||||
w.set_msion(true);
|
|
||||||
|
|
||||||
// If LSE is enabled, enable calibration of MSI
|
// If LSE is enabled, enable calibration of MSI
|
||||||
w.set_msipllen(config.ls.lse.is_some());
|
w.set_msipllen(config.ls.lse.is_some());
|
||||||
});
|
});
|
||||||
while !RCC.cr().read().msirdy() {}
|
while !RCC.cr().read().msirdy() {}
|
||||||
|
|
||||||
// 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)
|
msirange_to_hertz(range)
|
||||||
}
|
});
|
||||||
ClockSrc::HSE(freq) => {
|
|
||||||
// Enable HSE
|
|
||||||
RCC.cr().write(|w| w.set_hseon(true));
|
|
||||||
while !RCC.cr().read().hserdy() {}
|
|
||||||
|
|
||||||
(freq, Sw::HSE)
|
let hsi16 = config.hsi16.then(|| {
|
||||||
}
|
RCC.cr().write(|w| w.set_hsion(true));
|
||||||
ClockSrc::PLL(src, divr, prediv, mul, divq) => {
|
while !RCC.cr().read().hsirdy() {}
|
||||||
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)
|
HSI_FREQ
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
// Disable PLL
|
let hse = config.hse.map(|freq| {
|
||||||
RCC.cr().modify(|w| w.set_pllon(false));
|
RCC.cr().write(|w| w.set_hseon(true));
|
||||||
while RCC.cr().read().pllrdy() {}
|
while !RCC.cr().read().hserdy() {}
|
||||||
|
|
||||||
let freq = src_freq / prediv * mul / divr;
|
freq
|
||||||
|
});
|
||||||
#[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
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable PLL
|
|
||||||
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| {
|
||||||
w.set_latency(match sys_clk.0 {
|
w.set_latency(match sys_clk.0 {
|
||||||
@ -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),
|
||||||
|
@ -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!");
|
||||||
|
@ -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(
|
config.rcc.hse = Some(Hertz::mhz(8));
|
||||||
PLLSource::HSE(Hertz::mhz(8)),
|
config.rcc.pll_src = PLLSource::HSE;
|
||||||
PllRDiv::DIV2,
|
config.rcc.pll = Some(Pll {
|
||||||
PllPreDiv::DIV1,
|
prediv: PllPreDiv::DIV1,
|
||||||
PllMul::MUL20,
|
mul: PllMul::MUL20,
|
||||||
None,
|
divp: None,
|
||||||
);
|
divq: None,
|
||||||
config.rcc.ls = LsConfig::default_lse();
|
divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
|
||||||
embassy_stm32::init(config)
|
});
|
||||||
};
|
config.rcc.ls = LsConfig::default_lse();
|
||||||
|
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)
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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"))]
|
||||||
|
Loading…
Reference in New Issue
Block a user