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

stm32/rcc: merge wb into l4/l5.
This commit is contained in:
Dario Nieuwenhuis 2023-10-23 16:21:17 +00:00 committed by GitHub
commit d673f8a865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 327 additions and 529 deletions

4
ci.sh
View File

@ -221,8 +221,8 @@ rm out/tests/stm32wb55rg/wpan_ble
# unstable, I think it's running out of RAM?
rm out/tests/stm32f207zg/eth
# doesn't work. Wire in D0-D1 might be bad, or the special IOVDD2 PGx pins.
rm out/tests/stm32u5a5zj/{gpio,usart*}
# doesn't work, gives "noise error", no idea why. usart_dma does pass.
rm out/tests/stm32u5a5zj/usart
if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
echo No teleprobe token found, skipping running HIL tests

View File

@ -58,7 +58,7 @@ rand_core = "0.6.3"
sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
@ -76,7 +76,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-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9", default-features = false, features = ["metadata"]}
[features]

View File

@ -763,6 +763,13 @@ pub(crate) unsafe fn init(_cs: CriticalSection) {
<crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs);
crate::_generated::init_gpio();
// Setting this bit is mandatory to use PG[15:2].
#[cfg(stm32u5)]
crate::pac::PWR.svmcr().modify(|w| {
w.set_io2sv(true);
w.set_io2vmen(true);
});
}
mod eh02 {

View File

@ -166,8 +166,8 @@ pub(crate) unsafe fn init(config: Config) {
};
let hclk = sys / config.ahb_pre;
let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre);
let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre);
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
assert!(max::SYSCLK.contains(&sys));
assert!(max::HCLK.contains(&hclk));
@ -326,15 +326,6 @@ fn flash_setup(clk: Hertz) {
while FLASH.acr().read().latency() != latency {}
}
fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
where
Hertz: core::ops::Div<D, Output = Hertz>,
{
let pclk = hclk / ppre;
let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
(pclk, pclk_tim)
}
#[cfg(stm32f7)]
mod max {
use core::ops::RangeInclusive;

View File

@ -6,8 +6,11 @@ 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;
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};
pub use crate::pac::rcc::vals::{
Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
Pllsrc as PllSource, Sw as Sysclk,
};
use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
use crate::pac::{FLASH, PWR, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
@ -58,41 +61,9 @@ pub struct Hse {
pub mode: HseMode,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Hsi {
/// 64Mhz
Mhz64,
/// 32Mhz (divided by 2)
Mhz32,
/// 16Mhz (divided by 4)
Mhz16,
/// 8Mhz (divided by 8)
Mhz8,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Sysclk {
/// HSI selected as sysclk
HSI,
/// HSE selected as sysclk
HSE,
/// CSI selected as sysclk
CSI,
/// PLL1_P selected as sysclk
Pll1P,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum PllSource {
Hsi,
Csi,
Hse,
}
#[derive(Clone, Copy)]
pub struct Pll {
/// Source clock selection.
#[cfg(stm32h5)]
pub source: PllSource,
/// PLL pre-divider (DIVM).
@ -152,15 +123,12 @@ impl From<TimerPrescaler> for Timpre {
/// Configuration of the core clocks
#[non_exhaustive]
pub struct Config {
pub hsi: Option<Hsi>,
pub hsi: Option<HSIPrescaler>,
pub hse: Option<Hse>,
pub csi: bool,
pub hsi48: bool,
pub sys: Sysclk,
#[cfg(stm32h7)]
pub pll_src: PllSource,
pub pll1: Option<Pll>,
pub pll2: Option<Pll>,
#[cfg(any(rcc_h5, stm32h7))]
@ -184,13 +152,11 @@ pub struct Config {
impl Default for Config {
fn default() -> Self {
Self {
hsi: Some(Hsi::Mhz64),
hsi: Some(HSIPrescaler::DIV1),
hse: None,
csi: false,
hsi48: false,
sys: Sysclk::HSI,
#[cfg(stm32h7)]
pll_src: PllSource::Hsi,
pll1: None,
pll2: None,
#[cfg(any(rcc_h5, stm32h7))]
@ -303,19 +269,13 @@ pub(crate) unsafe fn init(config: Config) {
RCC.cr().modify(|w| w.set_hsion(false));
None
}
Some(hsi) => {
let (freq, hsidiv) = match hsi {
Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
};
Some(hsidiv) => {
RCC.cr().modify(|w| {
w.set_hsidiv(hsidiv);
w.set_hsion(true);
});
while !RCC.cr().read().hsirdy() {}
Some(freq)
Some(HSI_FREQ / hsidiv)
}
};
@ -360,25 +320,29 @@ pub(crate) unsafe fn init(config: Config) {
}
};
// H7 has shared PLLSRC, check it's equal in all PLLs.
#[cfg(stm32h7)]
{
let plls = [&config.pll1, &config.pll2, &config.pll3];
if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
panic!("Source must be equal across all enabled PLLs.")
};
}
// Configure PLLs.
let pll_input = PllInput {
csi,
hse,
hsi,
#[cfg(stm32h7)]
source: config.pll_src,
};
let pll_input = PllInput { csi, hse, hsi };
let pll1 = init_pll(0, config.pll1, &pll_input);
let pll2 = init_pll(1, config.pll2, &pll_input);
#[cfg(any(rcc_h5, stm32h7))]
let pll3 = init_pll(2, config.pll3, &pll_input);
// Configure sysclk
let (sys, sw) = match config.sys {
Sysclk::HSI => (unwrap!(hsi), Sw::HSI),
Sysclk::HSE => (unwrap!(hse), Sw::HSE),
Sysclk::CSI => (unwrap!(csi), Sw::CSI),
Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P),
let sys = match config.sys {
Sysclk::HSI => unwrap!(hsi),
Sysclk::HSE => unwrap!(hse),
Sysclk::CSI => unwrap!(csi),
Sysclk::PLL1_P => unwrap!(pll1.p),
_ => unreachable!(),
};
// Check limits.
@ -502,8 +466,8 @@ pub(crate) unsafe fn init(config: Config) {
RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
RCC.cfgr().modify(|w| w.set_sw(sw));
while RCC.cfgr().read().sws() != sw {}
RCC.cfgr().modify(|w| w.set_sw(config.sys));
while RCC.cfgr().read().sws() != config.sys {}
// IO compensation cell - Requires CSI clock and SYSCFG
#[cfg(stm32h7)] // TODO h5
@ -588,8 +552,6 @@ struct PllInput {
hsi: Option<Hertz>,
hse: Option<Hertz>,
csi: Option<Hertz>,
#[cfg(stm32h7)]
source: PllSource,
}
struct PllOutput {
@ -619,15 +581,11 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
};
};
#[cfg(stm32h5)]
let source = config.source;
#[cfg(stm32h7)]
let source = input.source;
let (in_clk, src) = match source {
PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
let in_clk = match config.source {
PllSource::DISABLE => panic!("must not set PllSource::Disable"),
PllSource::HSI => unwrap!(input.hsi),
PllSource::HSE => unwrap!(input.hse),
PllSource::CSI => unwrap!(input.csi),
};
let ref_clk = in_clk / config.prediv as u32;
@ -667,7 +625,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
#[cfg(stm32h5)]
RCC.pllcfgr(num).write(|w| {
w.set_pllsrc(src);
w.set_pllsrc(config.source);
w.set_divm(config.prediv);
w.set_pllvcosel(vco_range);
w.set_pllrge(ref_range);
@ -681,7 +639,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
{
RCC.pllckselr().modify(|w| {
w.set_divm(num, config.prediv);
w.set_pllsrc(src);
w.set_pllsrc(config.source);
});
RCC.pllcfgr().modify(|w| {
w.set_pllvcosel(num, vco_range);

View File

@ -156,23 +156,9 @@ pub(crate) unsafe fn init(config: Config) {
w.set_ppre2(config.apb2_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 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 freq = ahb_freq / pre;
(freq, freq * 2u32)
}
};
let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(crs)]
if config.enable_hsi48 {
@ -209,11 +195,11 @@ pub(crate) unsafe fn init(config: Config) {
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
pclk1: apb1_freq,
pclk2: apb2_freq,
pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq,
hclk1,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
rtc,
});
}

View File

@ -1,7 +1,8 @@
use crate::pac::rcc::regs::Cfgr;
#[cfg(not(stm32wl))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
use crate::pac::rcc::vals::Msirgsel;
#[cfg(any(stm32wb, stm32wl))]
pub use crate::pac::rcc::vals::Hsepre as HsePrescaler;
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, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
@ -27,6 +28,9 @@ pub struct Hse {
pub freq: Hertz,
/// HSE mode.
pub mode: HseMode,
/// HSE prescaler
#[cfg(any(stm32wb, stm32wl))]
pub prescaler: HsePrescaler,
}
#[derive(Clone, Copy)]
@ -54,12 +58,12 @@ pub struct Config {
pub msi: Option<MSIRange>,
pub hsi: bool,
pub hse: Option<Hse>,
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
pub hsi48: bool,
// pll
pub pll: Option<Pll>,
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pub pllsai1: Option<Pll>,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pub pllsai2: Option<Pll>,
@ -69,11 +73,13 @@ pub struct Config {
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
#[cfg(stm32wl)]
#[cfg(any(stm32wl5x, stm32wb))]
pub core2_ahb_pre: AHBPrescaler,
#[cfg(any(stm32wl, stm32wb))]
pub shared_ahb_pre: AHBPrescaler,
// muxes
#[cfg(not(stm32wl))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC
@ -91,28 +97,63 @@ impl Default for Config {
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
#[cfg(stm32wl)]
#[cfg(any(stm32wl5x, stm32wb))]
core2_ahb_pre: AHBPrescaler::DIV1,
#[cfg(any(stm32wl, stm32wb))]
shared_ahb_pre: AHBPrescaler::DIV1,
pll: None,
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
pllsai1: None,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2: None,
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
hsi48: true,
#[cfg(not(stm32wl))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
clk48_src: Clk48Src::HSI48,
ls: Default::default(),
}
}
}
#[cfg(stm32wb)]
pub const WPAN_DEFAULT: Config = Config {
hse: Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Oscillator,
prescaler: HsePrescaler::DIV1,
}),
mux: ClockSrc::PLL1_R,
hsi48: true,
msi: None,
hsi: false,
clk48_src: Clk48Src::PLL1_Q,
ls: super::LsConfig::default_lse(),
pll: Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL12,
divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
divq: Some(PllQDiv::DIV4), // 32 / 2 * 12 / 4 = 48Mhz
divr: Some(PllRDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
}),
pllsai1: None,
ahb_pre: AHBPrescaler::DIV1,
core2_ahb_pre: AHBPrescaler::DIV2,
shared_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
};
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(Msirgsel::CR);
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(MSIRange::RANGE4M);
w.set_msipllen(false);
w.set_msion(true)
@ -138,8 +179,9 @@ pub(crate) unsafe fn init(config: Config) {
let msi = config.msi.map(|range| {
// Enable MSI
RCC.cr().modify(|w| {
#[cfg(not(stm32wb))]
w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
w.set_msirange(range);
w.set_msirgsel(Msirgsel::CR);
w.set_msion(true);
// If LSE is enabled, enable calibration of MSI
@ -173,7 +215,7 @@ pub(crate) unsafe fn init(config: Config) {
hse.freq
});
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
let hsi48 = config.hsi48.then(|| {
RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {}
@ -185,7 +227,7 @@ pub(crate) unsafe fn init(config: Config) {
let _plls = [
&config.pll,
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
&config.pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
&config.pllsai2,
@ -193,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) {
// L4 has shared PLLSRC, PLLM, check it's equal in all PLLs.
#[cfg(all(stm32l4, not(rcc_l4plus)))]
match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
match super::util::get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
Err(()) => panic!("Source must be equal across all enabled PLLs."),
Ok(None) => {}
Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| {
@ -204,7 +246,7 @@ pub(crate) unsafe fn init(config: Config) {
// L4+, WL has shared PLLSRC, check it's equal in all PLLs.
#[cfg(any(rcc_l4plus, stm32wl))]
match get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
match super::util::get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
Err(()) => panic!("Source must be equal across all enabled PLLs."),
Ok(None) => {}
Ok(Some(source)) => RCC.pllcfgr().write(|w| {
@ -214,7 +256,7 @@ pub(crate) unsafe fn init(config: Config) {
let pll_input = PllInput { hse, hsi, msi };
let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
@ -223,19 +265,19 @@ pub(crate) unsafe fn init(config: Config) {
ClockSrc::HSE => hse.unwrap(),
ClockSrc::HSI => hsi.unwrap(),
ClockSrc::MSI => msi.unwrap(),
ClockSrc::PLL1_R => pll._r.unwrap(),
ClockSrc::PLL1_R => pll.r.unwrap(),
};
#[cfg(stm32l4)]
RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(stm32l5)]
RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
#[cfg(not(stm32wl))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => hsi48,
Clk48Src::MSI => msi,
Clk48Src::PLLSAI1_Q => pllsai1._q,
Clk48Src::PLL1_Q => pll._q,
Clk48Src::PLLSAI1_Q => pllsai1.q,
Clk48Src::PLL1_Q => pll.q,
};
#[cfg(rcc_l4plus)]
@ -243,30 +285,21 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(all(stm32l4, not(rcc_l4plus)))]
assert!(sys_clk.0 <= 80_000_000);
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 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 freq = ahb_freq / pre;
(freq, freq * 2u32)
}
};
#[cfg(stm32wl)]
let ahb3_freq = sys_clk / config.shared_ahb_pre;
let hclk1 = sys_clk / config.ahb_pre;
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
#[cfg(not(any(stm32wl5x, stm32wb)))]
let hclk2 = hclk1;
#[cfg(any(stm32wl5x, stm32wb))]
let hclk2 = sys_clk / config.core2_ahb_pre;
#[cfg(not(any(stm32wl, stm32wb)))]
let hclk3 = hclk1;
#[cfg(any(stm32wl, stm32wb))]
let hclk3 = sys_clk / config.shared_ahb_pre;
// Set flash wait states
#[cfg(stm32l4)]
let latency = match sys_clk.0 {
let latency = match hclk1.0 {
0..=16_000_000 => 0,
0..=32_000_000 => 1,
0..=48_000_000 => 2,
@ -274,7 +307,7 @@ pub(crate) unsafe fn init(config: Config) {
_ => 4,
};
#[cfg(stm32l5)]
let latency = match sys_clk.0 {
let latency = match hclk1.0 {
// VCORE Range 0 (performance), others TODO
0..=20_000_000 => 0,
0..=40_000_000 => 1,
@ -284,12 +317,21 @@ pub(crate) unsafe fn init(config: Config) {
_ => 5,
};
#[cfg(stm32wl)]
let latency = match ahb3_freq.0 {
let latency = match hclk3.0 {
// VOS RANGE1, others TODO.
..=18_000_000 => 0,
..=36_000_000 => 1,
_ => 2,
};
#[cfg(stm32wb)]
let latency = match hclk3.0 {
// VOS RANGE1, others TODO.
..=18_000_000 => 0,
..=36_000_000 => 1,
..=54_000_000 => 2,
..=64_000_000 => 3,
_ => 4,
};
FLASH.acr().modify(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {}
@ -302,28 +344,29 @@ pub(crate) unsafe fn init(config: Config) {
});
while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32wl)]
#[cfg(any(stm32wl, stm32wb))]
{
RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shared_ahb_pre);
#[cfg(any(stm32wl5x, stm32wb))]
w.set_c2hpre(config.core2_ahb_pre);
});
while !RCC.extcfgr().read().shdhpref() {}
#[cfg(any(stm32wl5x, stm32wb))]
while !RCC.extcfgr().read().c2hpref() {}
}
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
#[cfg(not(stm32wl))]
hclk3: ahb_freq,
pclk1: apb1_freq,
pclk2: apb2_freq,
pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq,
hclk1,
hclk2,
hclk3,
pclk1,
pclk2,
pclk1_tim,
pclk2_tim,
#[cfg(stm32wl)]
hclk3: ahb3_freq,
#[cfg(stm32wl)]
pclk3: ahb3_freq,
pclk3: hclk3,
#[cfg(rcc_l4)]
hsi: None,
#[cfg(rcc_l4)]
@ -362,60 +405,56 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
}
}
#[allow(unused)]
fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
let Some(x) = iter.next() else { return Ok(None) };
if !iter.all(|y| y == x) {
return Err(());
}
return Ok(Some(x));
}
struct PllInput {
hsi: Option<Hertz>,
hse: Option<Hertz>,
msi: Option<Hertz>,
}
#[allow(unused)]
#[derive(Default)]
struct PllOutput {
_p: Option<Hertz>,
_q: Option<Hertz>,
_r: Option<Hertz>,
p: Option<Hertz>,
q: Option<Hertz>,
r: Option<Hertz>,
}
#[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance {
Pll,
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
Pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
Pllsai2,
}
fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
fn pll_enable(instance: PllInstance, enabled: bool) {
match instance {
PllInstance::Pll => {
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
RCC.cr().modify(|w| w.set_pllon(enabled));
while RCC.cr().read().pllrdy() != enabled {}
}
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(false));
while RCC.cr().read().pllsai1rdy() {}
RCC.cr().modify(|w| w.set_pllsai1on(enabled));
while RCC.cr().read().pllsai1rdy() != enabled {}
}
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => {
RCC.cr().modify(|w| w.set_pllsai2on(false));
while RCC.cr().read().pllsai2rdy() {}
RCC.cr().modify(|w| w.set_pllsai2on(enabled));
while RCC.cr().read().pllsai2rdy() != enabled {}
}
}
}
fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
// Disable PLL
pll_enable(instance, false);
let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source {
PLLSource::DISABLE => panic!("must not select PLL source as NONE"),
PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"),
PLLSource::HSE => input.hse,
PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi,
@ -459,7 +498,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l4, stm32l5))]
#[cfg(any(stm32l4, stm32l5, stm32wb))]
PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
@ -478,22 +517,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
}
// Enable PLL
match instance {
PllInstance::Pll => {
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
}
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(true));
while !RCC.cr().read().pllsai1rdy() {}
}
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
PllInstance::Pllsai2 => {
RCC.cr().modify(|w| w.set_pllsai2on(true));
while !RCC.cr().read().pllsai2rdy() {}
}
}
pll_enable(instance, true);
PllOutput { _p: p, _q: q, _r: r }
PllOutput { p, q, r }
}

View File

@ -19,9 +19,8 @@ pub use mco::*;
#[cfg_attr(rcc_g4, path = "g4.rs")]
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle), path = "l4l5.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), path = "l4l5.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wb, path = "wb.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")]
mod _version;
#[cfg(feature = "low-power")]
@ -247,3 +246,33 @@ pub(crate) mod sealed {
}
pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
#[allow(unused)]
mod util {
use crate::time::Hertz;
pub fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
where
Hertz: core::ops::Div<D, Output = Hertz>,
{
let pclk = hclk / ppre;
let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
(pclk, pclk_tim)
}
pub fn all_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> bool {
let Some(x) = iter.next() else { return true };
if !iter.all(|y| y == x) {
return false;
}
true
}
pub fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
let Some(x) = iter.next() else { return Ok(None) };
if !iter.all(|y| y == x) {
return Err(());
}
Ok(Some(x))
}
}

View File

@ -1,258 +0,0 @@
pub use crate::pac::rcc::vals::{
Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource,
Ppre as APBPrescaler, Sw as Sysclk,
};
use crate::rcc::{set_freqs, Clocks};
use crate::time::{mhz, Hertz};
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
pub struct Hse {
pub prediv: HsePrescaler,
pub frequency: Hertz,
}
pub struct PllMux {
/// Source clock selection.
pub source: PllSource,
/// PLL pre-divider (DIVM). Must be between 1 and 63.
pub prediv: Pllm,
}
pub struct Pll {
/// PLL multiplication factor. Must be between 4 and 512.
pub mul: Plln,
/// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
/// On PLL1, it must be even (in particular, it cannot be 1.)
pub divp: Option<Pllp>,
/// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
pub divq: Option<Pllq>,
/// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
pub divr: Option<Pllr>,
}
/// Clocks configutation
pub struct Config {
pub hse: Option<Hse>,
pub sys: Sysclk,
pub mux: Option<PllMux>,
pub hsi48: bool,
pub pll: Option<Pll>,
pub pllsai: Option<Pll>,
pub ahb1_pre: AHBPrescaler,
pub ahb2_pre: AHBPrescaler,
pub ahb3_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub ls: super::LsConfig,
}
pub const WPAN_DEFAULT: Config = Config {
hse: Some(Hse {
frequency: mhz(32),
prediv: HsePrescaler::DIV1,
}),
sys: Sysclk::PLL1_R,
mux: Some(PllMux {
source: PllSource::HSE,
prediv: Pllm::DIV2,
}),
hsi48: true,
ls: super::LsConfig::default_lse(),
pll: Some(Pll {
mul: Plln::MUL12,
divp: Some(Pllp::DIV3),
divq: Some(Pllq::DIV4),
divr: Some(Pllr::DIV3),
}),
pllsai: None,
ahb1_pre: AHBPrescaler::DIV1,
ahb2_pre: AHBPrescaler::DIV2,
ahb3_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
};
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
sys: Sysclk::HSI,
hse: None,
mux: None,
pll: None,
pllsai: None,
hsi48: true,
ls: Default::default(),
ahb1_pre: AHBPrescaler::DIV1,
ahb2_pre: AHBPrescaler::DIV1,
ahb3_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
}
}
}
#[cfg(stm32wb)]
/// RCC initialization function
pub(crate) unsafe fn init(config: Config) {
let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv);
let mux_clk = config.mux.as_ref().map(|pll_mux| {
(match pll_mux.source {
PllSource::HSE => hse_clk.unwrap(),
PllSource::HSI => HSI_FREQ,
_ => unreachable!(),
} / pll_mux.prediv)
});
let (pll_r, _pll_q, _pll_p) = match &config.pll {
Some(pll) => {
let pll_vco = mux_clk.unwrap() * pll.mul as u32;
(
pll.divr.map(|divr| pll_vco / divr),
pll.divq.map(|divq| pll_vco / divq),
pll.divp.map(|divp| pll_vco / divp),
)
}
None => (None, None, None),
};
let sys_clk = match config.sys {
Sysclk::HSE => hse_clk.unwrap(),
Sysclk::HSI => HSI_FREQ,
Sysclk::PLL1_R => pll_r.unwrap(),
_ => unreachable!(),
};
let ahb1_clk = sys_clk / config.ahb1_pre;
let ahb2_clk = sys_clk / config.ahb2_pre;
let ahb3_clk = sys_clk / config.ahb3_pre;
let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
pre => {
let freq = ahb1_clk / pre;
(freq, freq * 2u32)
}
};
let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
pre => {
let freq = ahb1_clk / pre;
(freq, freq * 2u32)
}
};
let rcc = crate::pac::RCC;
let needs_hsi = if let Some(pll_mux) = &config.mux {
pll_mux.source == PllSource::HSI
} else {
false
};
if needs_hsi || config.sys == Sysclk::HSI {
rcc.cr().modify(|w| {
w.set_hsion(true);
});
while !rcc.cr().read().hsirdy() {}
}
rcc.cfgr().modify(|w| w.set_stopwuck(true));
let rtc = config.ls.init();
match &config.hse {
Some(hse) => {
rcc.cr().modify(|w| {
w.set_hsepre(hse.prediv);
w.set_hseon(true);
});
while !rcc.cr().read().hserdy() {}
}
_ => {}
}
match &config.mux {
Some(pll_mux) => {
rcc.pllcfgr().modify(|w| {
w.set_pllm(pll_mux.prediv);
w.set_pllsrc(pll_mux.source.into());
});
}
_ => {}
};
match &config.pll {
Some(pll) => {
rcc.pllcfgr().modify(|w| {
w.set_plln(pll.mul);
pll.divp.map(|divp| {
w.set_pllpen(true);
w.set_pllp(divp)
});
pll.divq.map(|divq| {
w.set_pllqen(true);
w.set_pllq(divq)
});
pll.divr.map(|divr| {
w.set_pllren(true);
w.set_pllr(divr);
});
});
rcc.cr().modify(|w| w.set_pllon(true));
while !rcc.cr().read().pllrdy() {}
}
_ => {}
}
let _hsi48 = config.hsi48.then(|| {
rcc.crrcr().modify(|w| w.set_hsi48on(true));
while !rcc.crrcr().read().hsi48rdy() {}
Hertz(48_000_000)
});
rcc.cfgr().modify(|w| {
w.set_sw(config.sys.into());
w.set_hpre(config.ahb1_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
rcc.extcfgr().modify(|w| {
w.set_c2hpre(config.ahb2_pre);
w.set_shdhpre(config.ahb3_pre);
});
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb1_clk,
hclk2: ahb2_clk,
hclk3: ahb3_clk,
pclk1: apb1_clk,
pclk2: apb2_clk,
pclk1_tim: apb1_tim_clk,
pclk2_tim: apb2_tim_clk,
rtc,
})
}

View File

@ -43,7 +43,7 @@ async fn main(spawner: Spawner) -> ! {
mode: HseMode::BypassDigital,
});
config.rcc.pll1 = Some(Pll {
source: PllSource::Hse,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2),
@ -54,7 +54,7 @@ async fn main(spawner: Spawner) -> ! {
config.rcc.apb1_pre = APBPrescaler::DIV1;
config.rcc.apb2_pre = APBPrescaler::DIV1;
config.rcc.apb3_pre = APBPrescaler::DIV1;
config.rcc.sys = Sysclk::Pll1P;
config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0;
let p = embassy_stm32::init(config);
info!("Hello World!");

View File

@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) {
mode: HseMode::BypassDigital,
});
config.rcc.pll1 = Some(Pll {
source: PllSource::Hse,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2), // 250mhz
@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) {
config.rcc.apb1_pre = APBPrescaler::DIV4;
config.rcc.apb2_pre = APBPrescaler::DIV2;
config.rcc.apb3_pre = APBPrescaler::DIV4;
config.rcc.sys = Sysclk::Pll1P;
config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0;
let p = embassy_stm32::init(config);

View File

@ -14,10 +14,10 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
@ -25,13 +25,14 @@ async fn main(_spawner: Spawner) {
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -28,17 +28,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -16,10 +16,10 @@ fn main() -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
@ -27,13 +27,14 @@ fn main() -> ! {
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -24,10 +24,10 @@ async fn main(spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
@ -35,13 +35,14 @@ async fn main(spawner: Spawner) {
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -34,18 +34,18 @@ async fn main(spawner: Spawner) -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -35,18 +35,18 @@ async fn main(spawner: Spawner) -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -17,18 +17,18 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: Some(PllDiv::DIV8), // 100mhz
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -18,17 +18,17 @@ async fn main(_spawner: Spawner) -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
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
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -40,17 +40,17 @@ fn main() -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
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
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -36,17 +36,17 @@ fn main() -> ! {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
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
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -23,18 +23,18 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for USB
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz

View File

@ -39,6 +39,7 @@ async fn main(_spawner: Spawner) {
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {

View File

@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
use embassy_stm32::bind_interrupts;
use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::spi::Spi;
use embassy_stm32::time::Hertz;
use embassy_time::{Delay, Timer};
use lora_phy::mod_params::*;
use lora_phy::sx1261_2::SX1261_2;
@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
{
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
});
}
let p = embassy_stm32::init(config);
let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);

View File

@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
use embassy_stm32::bind_interrupts;
use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::spi::Spi;
use embassy_stm32::time::Hertz;
use embassy_time::Delay;
use lora_phy::mod_params::*;
use lora_phy::sx1261_2::SX1261_2;
@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE;
{
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
});
}
let p = embassy_stm32::init(config);
let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);

View File

@ -21,6 +21,7 @@ async fn main(_spawner: Spawner) {
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {

View File

@ -5,20 +5,34 @@
use chrono::{NaiveDate, NaiveDateTime};
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, LsConfig};
use embassy_stm32::rtc::{Rtc, RtcConfig};
use embassy_stm32::time::Hertz;
use embassy_stm32::Config;
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = {
let mut config = Config::default();
config.rcc.mux = ClockSrc::HSE;
let mut config = Config::default();
{
use embassy_stm32::rcc::*;
config.rcc.ls = LsConfig::default_lse();
embassy_stm32::init(config)
};
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL6,
divp: None,
divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
});
}
let p = embassy_stm32::init(config);
info!("Hello World!");
let now = NaiveDate::from_ymd_opt(2020, 5, 15)

View File

@ -227,6 +227,11 @@ pub fn config() -> Config {
#[allow(unused_mut)]
let mut config = Config::default();
#[cfg(feature = "stm32wb55rg")]
{
config.rcc = embassy_stm32::rcc::WPAN_DEFAULT;
}
#[cfg(feature = "stm32f207zg")]
{
use embassy_stm32::rcc::*;
@ -307,7 +312,7 @@ pub fn config() -> Config {
mode: HseMode::BypassDigital,
});
config.rcc.pll1 = Some(Pll {
source: PllSource::Hse,
source: PllSource::HSE,
prediv: PllPreDiv::DIV2,
mul: PllMul::MUL125,
divp: Some(PllDiv::DIV2),
@ -318,18 +323,18 @@ pub fn config() -> Config {
config.rcc.apb1_pre = APBPrescaler::DIV1;
config.rcc.apb2_pre = APBPrescaler::DIV1;
config.rcc.apb3_pre = APBPrescaler::DIV1;
config.rcc.sys = Sysclk::Pll1P;
config.rcc.sys = Sysclk::PLL1_P;
config.rcc.voltage_scale = VoltageScale::Scale0;
}
#[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))]
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV2),
@ -337,13 +342,14 @@ pub fn config() -> Config {
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL50,
divp: Some(PllDiv::DIV8), // 100mhz
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 400 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
@ -356,11 +362,11 @@ pub fn config() -> Config {
#[cfg(any(feature = "stm32h7a3zi"))]
{
use embassy_stm32::rcc::*;
config.rcc.hsi = Some(Hsi::Mhz64);
config.rcc.hsi = Some(HSIPrescaler::DIV1);
config.rcc.csi = true;
config.rcc.hsi48 = true; // needed for RNG
config.rcc.pll_src = PllSource::Hsi;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL35,
divp: Some(PllDiv::DIV2), // 280 Mhz
@ -368,13 +374,14 @@ pub fn config() -> Config {
divr: None,
});
config.rcc.pll2 = Some(Pll {
source: PllSource::HSI,
prediv: PllPreDiv::DIV4,
mul: PllMul::MUL35,
divp: Some(PllDiv::DIV8), // 70 Mhz
divq: None,
divr: None,
});
config.rcc.sys = Sysclk::Pll1P; // 280 Mhz
config.rcc.sys = Sysclk::PLL1_P; // 280 Mhz
config.rcc.ahb_pre = AHBPrescaler::DIV1; // 280 Mhz
config.rcc.apb1_pre = APBPrescaler::DIV2; // 140 Mhz
config.rcc.apb2_pre = APBPrescaler::DIV2; // 140 Mhz
@ -405,6 +412,7 @@ pub fn config() -> Config {
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
prescaler: HsePrescaler::DIV1,
});
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.pll = Some(Pll {