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

stm32/rcc: merge wl into l4/l5.
This commit is contained in:
Dario Nieuwenhuis 2023-10-22 22:48:57 +00:00 committed by GitHub
commit e895ea2d8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 198 additions and 276 deletions

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-ee64389697d9234af374a89788aa52bb93d59284" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc" }
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-ee64389697d9234af374a89788aa52bb93d59284", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]}
[features]

View File

@ -5,6 +5,7 @@ use core::task::Poll;
use self::sealed::Instance;
use crate::interrupt;
use crate::interrupt::typelevel::Interrupt;
use crate::pac::rcc::vals::{Lptim1sel, Lptim2sel};
use crate::peripherals::IPCC;
use crate::rcc::sealed::RccPeripheral;
@ -273,7 +274,7 @@ fn _configure_pwr() {
// set LPTIM1 & LPTIM2 clock source
rcc.ccipr().modify(|w| {
w.set_lptim1sel(0b00); // PCLK
w.set_lptim2sel(0b00); // PCLK
w.set_lptim1sel(Lptim1sel::PCLK1);
w.set_lptim2sel(Lptim2sel::PCLK1);
});
}

View File

@ -1,8 +1,10 @@
use crate::pac::rcc::regs::Cfgr;
#[cfg(not(stm32wl))]
pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
use crate::pac::rcc::vals::Msirgsel;
pub use crate::pac::rcc::vals::{
Clk48sel as Clk48Src, 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,
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,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
@ -11,6 +13,22 @@ use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1)
Bypass,
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Hse {
/// HSE frequency.
pub freq: Hertz,
/// HSE mode.
pub mode: HseMode,
}
#[derive(Clone, Copy)]
pub struct Pll {
/// PLL source
@ -35,12 +53,13 @@ pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,
pub hsi: bool,
pub hse: Option<Hertz>,
#[cfg(not(any(stm32l47x, stm32l48x)))]
pub hse: Option<Hse>,
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
pub hsi48: bool,
// pll
pub pll: Option<Pll>,
#[cfg(any(stm32l4, stm32l5))]
pub pllsai1: Option<Pll>,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pub pllsai2: Option<Pll>,
@ -50,8 +69,11 @@ pub struct Config {
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
#[cfg(stm32wl)]
pub shared_ahb_pre: AHBPrescaler,
// muxes
#[cfg(not(stm32wl))]
pub clk48_src: Clk48Src,
// low speed LSI/LSE/RTC
@ -69,12 +91,16 @@ impl Default for Config {
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
#[cfg(stm32wl)]
shared_ahb_pre: AHBPrescaler::DIV1,
pll: None,
#[cfg(any(stm32l4, stm32l5))]
pllsai1: None,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
pllsai2: None,
#[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
hsi48: true,
#[cfg(not(stm32wl))]
clk48_src: Clk48Src::HSI48,
ls: Default::default(),
}
@ -111,7 +137,7 @@ pub(crate) unsafe fn init(config: Config) {
let msi = config.msi.map(|range| {
// Enable MSI
RCC.cr().write(|w| {
RCC.cr().modify(|w| {
w.set_msirange(range);
w.set_msirgsel(Msirgsel::CR);
w.set_msion(true);
@ -128,20 +154,26 @@ pub(crate) unsafe fn init(config: Config) {
});
let hsi = config.hsi.then(|| {
RCC.cr().write(|w| w.set_hsion(true));
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
HSI_FREQ
});
let hse = config.hse.map(|freq| {
RCC.cr().write(|w| w.set_hseon(true));
let hse = config.hse.map(|hse| {
RCC.cr().modify(|w| {
#[cfg(stm32wl)]
w.set_hsebyppwr(hse.mode == HseMode::Bypass);
#[cfg(not(stm32wl))]
w.set_hsebyp(hse.mode == HseMode::Bypass);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
freq
hse.freq
});
#[cfg(not(any(stm32l47x, stm32l48x)))]
#[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
let hsi48 = config.hsi48.then(|| {
RCC.crrcr().modify(|w| w.set_hsi48on(true));
while !RCC.crrcr().read().hsi48rdy() {}
@ -153,6 +185,7 @@ pub(crate) unsafe fn init(config: Config) {
let _plls = [
&config.pll,
#[cfg(any(stm32l4, stm32l5))]
&config.pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
&config.pllsai2,
@ -169,8 +202,8 @@ pub(crate) unsafe fn init(config: Config) {
}),
};
// L4+ has shared PLLSRC, check it's equal in all PLLs.
#[cfg(any(rcc_l4plus))]
// 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)) {
Err(()) => panic!("Source must be equal across all enabled PLLs."),
Ok(None) => {}
@ -181,6 +214,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))]
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);
@ -196,6 +230,7 @@ pub(crate) unsafe fn init(config: Config) {
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))]
let _clk48 = match config.clk48_src {
Clk48Src::HSI48 => hsi48,
Clk48Src::MSI => msi,
@ -208,38 +243,6 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(all(stm32l4, not(rcc_l4plus)))]
assert!(sys_clk.0 <= 80_000_000);
// Set flash wait states
#[cfg(stm32l4)]
FLASH.acr().modify(|w| {
w.set_latency(match sys_clk.0 {
0..=16_000_000 => 0,
0..=32_000_000 => 1,
0..=48_000_000 => 2,
0..=64_000_000 => 3,
_ => 4,
})
});
// VCORE Range 0 (performance), others TODO
#[cfg(stm32l5)]
FLASH.acr().modify(|w| {
w.set_latency(match sys_clk.0 {
0..=20_000_000 => 0,
0..=40_000_000 => 1,
0..=60_000_000 => 2,
0..=80_000_000 => 3,
0..=100_000_000 => 4,
_ => 5,
})
});
RCC.cfgr().modify(|w| {
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
while RCC.cfgr().read().sws() != config.mux {}
let ahb_freq = sys_clk / config.ahb_pre;
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
@ -258,15 +261,69 @@ pub(crate) unsafe fn init(config: Config) {
}
};
#[cfg(stm32wl)]
let ahb3_freq = sys_clk / config.shared_ahb_pre;
// Set flash wait states
#[cfg(stm32l4)]
let latency = match sys_clk.0 {
0..=16_000_000 => 0,
0..=32_000_000 => 1,
0..=48_000_000 => 2,
0..=64_000_000 => 3,
_ => 4,
};
#[cfg(stm32l5)]
let latency = match sys_clk.0 {
// VCORE Range 0 (performance), others TODO
0..=20_000_000 => 0,
0..=40_000_000 => 1,
0..=60_000_000 => 2,
0..=80_000_000 => 3,
0..=100_000_000 => 4,
_ => 5,
};
#[cfg(stm32wl)]
let latency = match ahb3_freq.0 {
// VOS RANGE1, others TODO.
..=18_000_000 => 0,
..=36_000_000 => 1,
_ => 2,
};
FLASH.acr().modify(|w| w.set_latency(latency));
while FLASH.acr().read().latency() != latency {}
RCC.cfgr().modify(|w| {
w.set_sw(config.mux);
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
while RCC.cfgr().read().sws() != config.mux {}
#[cfg(stm32wl)]
{
RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shared_ahb_pre);
});
while !RCC.extcfgr().read().shdhpref() {}
}
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,
#[cfg(stm32wl)]
hclk3: ahb3_freq,
#[cfg(stm32wl)]
pclk3: ahb3_freq,
#[cfg(rcc_l4)]
hsi: None,
#[cfg(rcc_l4)]
@ -330,6 +387,7 @@ struct PllOutput {
#[derive(PartialEq, Eq, Clone, Copy)]
enum PllInstance {
Pll,
#[cfg(any(stm32l4, stm32l5))]
Pllsai1,
#[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
Pllsai2,
@ -342,6 +400,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
RCC.cr().modify(|w| w.set_pllon(false));
while RCC.cr().read().pllrdy() {}
}
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => {
RCC.cr().modify(|w| w.set_pllsai1on(false));
while RCC.cr().read().pllsai1rdy() {}
@ -356,7 +415,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
let Some(pll) = config else { return PllOutput::default() };
let pll_src = match pll.source {
PLLSource::NONE => panic!("must not select PLL source as NONE"),
PLLSource::DISABLE => panic!("must not select PLL source as NONE"),
PLLSource::HSE => input.hse,
PLLSource::HSI => input.hsi,
PLLSource::MSI => input.msi,
@ -400,6 +459,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
w.set_pllsrc(pll.source);
write_fields!(w);
}),
#[cfg(any(stm32l4, stm32l5))]
PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
#[cfg(any(rcc_l4plus, stm32l5))]
w.set_pllm(pll.prediv);
@ -423,6 +483,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> 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() {}

View File

@ -19,11 +19,10 @@ 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), path = "l4l5.rs")]
#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle), path = "l4l5.rs")]
#[cfg_attr(rcc_u5, path = "u5.rs")]
#[cfg_attr(rcc_wb, path = "wb.rs")]
#[cfg_attr(rcc_wba, path = "wba.rs")]
#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
mod _version;
#[cfg(feature = "low-power")]
use core::sync::atomic::{AtomicU32, Ordering};

View File

@ -170,7 +170,7 @@ impl Config {
RCC.icscr1().modify(|w| {
w.set_msisrange(range);
w.set_msirgsel(Msirgsel::RCC_ICSCR1);
w.set_msirgsel(Msirgsel::ICSCR1);
});
RCC.cr().write(|w| {
w.set_msipllen(false);

View File

@ -1,184 +0,0 @@
pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::vals::Sw;
pub use crate::pac::rcc::vals::{
Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
Pllsrc as PllSource, Ppre as APBPrescaler,
};
use crate::pac::{FLASH, RCC};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
/// HSE speed
pub const HSE_FREQ: Hertz = Hertz(32_000_000);
/// System clock mux source
#[derive(Clone, Copy)]
pub enum ClockSrc {
MSI(MSIRange),
HSE,
HSI,
}
/// Clocks configutation
pub struct Config {
pub mux: ClockSrc,
pub ahb_pre: AHBPrescaler,
pub shd_ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub adc_clock_source: AdcClockSource,
pub ls: super::LsConfig,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
mux: ClockSrc::MSI(MSIRange::RANGE4M),
ahb_pre: AHBPrescaler::DIV1,
shd_ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
adc_clock_source: AdcClockSource::HSI,
ls: Default::default(),
}
}
}
pub(crate) unsafe fn init(config: Config) {
let (sys_clk, sw, vos) = match config.mux {
ClockSrc::HSI => (HSI_FREQ, Sw::HSI, VoltageScale::RANGE2),
ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1),
ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
};
let ahb_freq = sys_clk / config.ahb_pre;
let shd_ahb_freq = sys_clk / config.shd_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)
}
};
// Adjust flash latency
let flash_clk_src_freq = shd_ahb_freq;
let ws = match vos {
VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
0..=18_000_000 => 0b000,
18_000_001..=36_000_000 => 0b001,
_ => 0b010,
},
VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
0..=6_000_000 => 0b000,
6_000_001..=12_000_000 => 0b001,
_ => 0b010,
},
_ => unreachable!(),
};
FLASH.acr().modify(|w| {
w.set_latency(ws);
});
while FLASH.acr().read().latency() != ws {}
match config.mux {
ClockSrc::HSI => {
// Enable HSI
RCC.cr().write(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
ClockSrc::HSE => {
// Enable HSE
RCC.cr().write(|w| {
w.set_hsebyppwr(true);
w.set_hseon(true);
});
while !RCC.cr().read().hserdy() {}
}
ClockSrc::MSI(range) => {
let cr = RCC.cr().read();
assert!(!cr.msion() || cr.msirdy());
RCC.cr().write(|w| {
w.set_msirgsel(true);
w.set_msirange(range);
w.set_msion(true);
// If LSE is enabled, enable calibration of MSI
w.set_msipllen(config.ls.lse.is_some());
});
while !RCC.cr().read().msirdy() {}
}
}
RCC.extcfgr().modify(|w| {
w.set_shdhpre(config.shd_ahb_pre);
});
RCC.cfgr().modify(|w| {
w.set_sw(sw.into());
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
// ADC clock MUX
RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
// TODO: switch voltage range
let rtc = config.ls.init();
set_freqs(Clocks {
sys: sys_clk,
hclk1: ahb_freq,
hclk2: ahb_freq,
hclk3: shd_ahb_freq,
pclk1: apb1_freq,
pclk2: apb2_freq,
pclk3: shd_ahb_freq,
pclk1_tim: apb1_tim_freq,
pclk2_tim: apb2_tim_freq,
rtc,
});
}
fn msirange_to_hertz(range: MSIRange) -> Hertz {
match range {
MSIRange::RANGE100K => Hertz(100_000),
MSIRange::RANGE200K => Hertz(200_000),
MSIRange::RANGE400K => Hertz(400_000),
MSIRange::RANGE800K => Hertz(800_000),
MSIRange::RANGE1M => Hertz(1_000_000),
MSIRange::RANGE2M => Hertz(2_000_000),
MSIRange::RANGE4M => Hertz(4_000_000),
MSIRange::RANGE8M => Hertz(8_000_000),
MSIRange::RANGE16M => Hertz(16_000_000),
MSIRange::RANGE24M => Hertz(24_000_000),
MSIRange::RANGE32M => Hertz(32_000_000),
MSIRange::RANGE48M => Hertz(48_000_000),
_ => unreachable!(),
}
}
fn msirange_to_vos(range: MSIRange) -> VoltageScale {
if range.to_bits() > MSIRange::RANGE16M.to_bits() {
VoltageScale::RANGE1
} else {
VoltageScale::RANGE2
}
}

View File

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

View File

@ -48,7 +48,6 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
use embedded_hal_bus::spi::ExclusiveDevice;
use hal::gpio::Pull;
use hal::i2c::Config as I2C_Config;
use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
use hal::spi::{Config as SPI_Config, Spi};
use hal::time::Hertz;
@ -74,20 +73,25 @@ async fn main(spawner: Spawner) {
defmt::println!("Start main()");
let mut config = embassy_stm32::Config::default();
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
// 80MHz highest frequency for flash 0 wait.
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hse = Some(Hertz::mhz(8));
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV1,
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
{
use embassy_stm32::rcc::*;
// 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
// 80MHz highest frequency for flash 0 wait.
config.rcc.mux = ClockSrc::PLL1_R;
config.rcc.hse = Some(Hse {
freq: Hertz::mhz(8),
mode: HseMode::Oscillator,
});
config.rcc.pll = Some(Pll {
source: PLLSource::HSE,
prediv: PllPreDiv::DIV1,
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
}
let dp = embassy_stm32::init(config);

View File

@ -12,7 +12,8 @@ use embassy_lora::LoraTimer;
use embassy_stm32::gpio::{Level, Output, Pin, Speed};
use embassy_stm32::rng::{self, Rng};
use embassy_stm32::spi::Spi;
use embassy_stm32::{bind_interrupts, pac, peripherals};
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, peripherals};
use embassy_time::Delay;
use lora_phy::mod_params::*;
use lora_phy::sx1261_2::SX1261_2;
@ -33,11 +34,24 @@ 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,
});
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);
pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
// Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx

View File

@ -4,9 +4,9 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_stm32::rcc::{ClockSrc, MSIRange};
use embassy_stm32::rng::{self, Rng};
use embassy_stm32::{bind_interrupts, pac, peripherals};
use embassy_stm32::time::Hertz;
use embassy_stm32::{bind_interrupts, peripherals};
use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs{
@ -16,11 +16,24 @@ bind_interrupts!(struct Irqs{
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let mut config = embassy_stm32::Config::default();
config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
{
use embassy_stm32::rcc::*;
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
});
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);
pac::RCC.ccipr().modify(|w| w.set_rngsel(0b11)); // msi
info!("Hello World!");
let mut rng = Rng::new(p.RNG, Irqs);

View File

@ -402,9 +402,18 @@ pub fn config() -> Config {
#[cfg(feature = "stm32wl55jc")]
{
use embassy_stm32::rcc::*;
config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M);
embassy_stm32::pac::RCC.ccipr().modify(|w| {
w.set_rngsel(0b11); // msi
config.rcc.hse = Some(Hse {
freq: Hertz(32_000_000),
mode: HseMode::Bypass,
});
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)
});
}