stm32: add stm32wba support.
This commit is contained in:
@ -154,7 +154,7 @@ pub fn init(config: Config) -> Peripherals {
|
||||
#[cfg(dbgmcu)]
|
||||
if config.enable_debug_during_sleep {
|
||||
crate::pac::DBGMCU.cr().modify(|cr| {
|
||||
#[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))]
|
||||
#[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))]
|
||||
{
|
||||
cr.set_dbg_stop(true);
|
||||
cr.set_dbg_standby(true);
|
||||
|
@ -26,19 +26,7 @@ impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum RtcClockSource {
|
||||
/// 00: No clock
|
||||
NoClock = 0b00,
|
||||
/// 01: LSE oscillator clock used as RTC clock
|
||||
LSE = 0b01,
|
||||
/// 10: LSI oscillator clock used as RTC clock
|
||||
LSI = 0b10,
|
||||
/// 11: HSE oscillator clock divided by 32 used as RTC clock
|
||||
HSE = 0b11,
|
||||
}
|
||||
pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
|
||||
|
||||
#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))]
|
||||
#[allow(dead_code)]
|
||||
@ -109,17 +97,17 @@ impl BackupDomain {
|
||||
let csr = crate::pac::RCC.csr();
|
||||
|
||||
Self::modify(|_| {
|
||||
#[cfg(not(rtc_v2wb))]
|
||||
#[cfg(not(any(rcc_wb, rcc_wba)))]
|
||||
csr.modify(|w| w.set_lsion(true));
|
||||
|
||||
#[cfg(rtc_v2wb)]
|
||||
#[cfg(any(rcc_wb, rcc_wba))]
|
||||
csr.modify(|w| w.set_lsi1on(true));
|
||||
});
|
||||
|
||||
#[cfg(not(rtc_v2wb))]
|
||||
#[cfg(not(any(rcc_wb, rcc_wba)))]
|
||||
while !csr.read().lsirdy() {}
|
||||
|
||||
#[cfg(rtc_v2wb)]
|
||||
#[cfg(any(rcc_wb, rcc_wba))]
|
||||
while !csr.read().lsi1rdy() {}
|
||||
}
|
||||
RtcClockSource::LSE => {
|
||||
@ -136,64 +124,50 @@ impl BackupDomain {
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Self::configure_rtc(clock_source);
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
|
||||
rtc_v3u5
|
||||
))]
|
||||
#[allow(dead_code, unused_variables)]
|
||||
pub fn configure_rtc(clock_source: RtcClockSource) {
|
||||
let clock_source = clock_source as u8;
|
||||
#[cfg(any(
|
||||
not(any(rtc_v3, rtc_v3u5, rtc_v2wb)),
|
||||
all(any(rtc_v3, rtc_v3u5), not(any(rcc_wl5, rcc_wle)))
|
||||
))]
|
||||
let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source);
|
||||
|
||||
#[cfg(not(rtc_v2wb))]
|
||||
Self::modify(|w| {
|
||||
// Select RTC source
|
||||
w.set_rtcsel(clock_source);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
|
||||
rtc_v3u5
|
||||
))]
|
||||
#[allow(dead_code)]
|
||||
pub fn enable_rtc() {
|
||||
let reg = Self::read();
|
||||
|
||||
#[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
|
||||
|
||||
if !reg.rtcen() {
|
||||
#[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
|
||||
Self::modify(|w| w.set_bdrst(true));
|
||||
|
||||
if clock_source == RtcClockSource::NOCLOCK {
|
||||
// disable it
|
||||
Self::modify(|w| {
|
||||
// Reset
|
||||
#[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
|
||||
w.set_bdrst(false);
|
||||
|
||||
w.set_rtcen(true);
|
||||
w.set_rtcsel(reg.rtcsel());
|
||||
|
||||
// Restore bcdr
|
||||
#[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lscosel(reg.lscosel());
|
||||
#[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lscoen(reg.lscoen());
|
||||
|
||||
w.set_lseon(reg.lseon());
|
||||
|
||||
#[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lsedrv(reg.lsedrv());
|
||||
w.set_lsebyp(reg.lsebyp());
|
||||
#[cfg(not(rcc_wba))]
|
||||
w.set_rtcen(false);
|
||||
w.set_rtcsel(clock_source);
|
||||
});
|
||||
} else {
|
||||
// check if it's already enabled and in the source we want.
|
||||
let reg = Self::read();
|
||||
let ok = reg.rtcsel() == clock_source;
|
||||
#[cfg(not(rcc_wba))]
|
||||
let ok = ok & reg.rtcen();
|
||||
|
||||
// if not, configure it.
|
||||
if !ok {
|
||||
#[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
|
||||
|
||||
#[cfg(not(any(rcc_l0, rcc_l1)))]
|
||||
Self::modify(|w| w.set_bdrst(true));
|
||||
|
||||
Self::modify(|w| {
|
||||
// Reset
|
||||
#[cfg(not(any(rcc_l0, rcc_l1)))]
|
||||
w.set_bdrst(false);
|
||||
|
||||
#[cfg(not(rcc_wba))]
|
||||
w.set_rtcen(true);
|
||||
w.set_rtcsel(clock_source);
|
||||
|
||||
// Restore bcdr
|
||||
#[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lscosel(reg.lscosel());
|
||||
#[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lscoen(reg.lscoen());
|
||||
|
||||
w.set_lseon(reg.lseon());
|
||||
|
||||
#[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
|
||||
w.set_lsedrv(reg.lsedrv());
|
||||
w.set_lsebyp(reg.lsebyp());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,10 +79,7 @@ impl From<AHBPrescaler> for rcc::vals::Hpre {
|
||||
use rcc::vals::Hpre;
|
||||
|
||||
match val {
|
||||
#[cfg(not(rcc_u5))]
|
||||
AHBPrescaler::NotDivided => Hpre::DIV1,
|
||||
#[cfg(rcc_u5)]
|
||||
AHBPrescaler::NotDivided => Hpre::NONE,
|
||||
AHBPrescaler::Div2 => Hpre::DIV2,
|
||||
AHBPrescaler::Div4 => Hpre::DIV4,
|
||||
AHBPrescaler::Div8 => Hpre::DIV8,
|
||||
@ -148,10 +145,7 @@ impl From<APBPrescaler> for rcc::vals::Ppre {
|
||||
use rcc::vals::Ppre;
|
||||
|
||||
match val {
|
||||
#[cfg(not(rcc_u5))]
|
||||
APBPrescaler::NotDivided => Ppre::DIV1,
|
||||
#[cfg(rcc_u5)]
|
||||
APBPrescaler::NotDivided => Ppre::NONE,
|
||||
APBPrescaler::Div2 => Ppre::DIV2,
|
||||
APBPrescaler::Div4 => Ppre::DIV4,
|
||||
APBPrescaler::Div8 => Ppre::DIV8,
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![macro_use]
|
||||
|
||||
pub(crate) mod bd;
|
||||
#[cfg(not(rcc_wba))]
|
||||
pub mod bus;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
@ -23,6 +24,7 @@ use crate::time::Hertz;
|
||||
#[cfg_attr(rcc_l5, path = "l5.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")]
|
||||
#[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")]
|
||||
mod _version;
|
||||
@ -46,12 +48,14 @@ pub struct Clocks {
|
||||
pub apb3: Hertz,
|
||||
#[cfg(any(rcc_h7, rcc_h7ab))]
|
||||
pub apb4: Hertz,
|
||||
#[cfg(any(rcc_wba))]
|
||||
pub apb7: Hertz,
|
||||
|
||||
// AHB
|
||||
pub ahb1: Hertz,
|
||||
#[cfg(any(
|
||||
rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb,
|
||||
rcc_wl5, rcc_wle
|
||||
rcc_wba, rcc_wl5, rcc_wle
|
||||
))]
|
||||
pub ahb2: Hertz,
|
||||
#[cfg(any(
|
||||
@ -59,7 +63,7 @@ pub struct Clocks {
|
||||
rcc_wle
|
||||
))]
|
||||
pub ahb3: Hertz,
|
||||
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))]
|
||||
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))]
|
||||
pub ahb4: Hertz,
|
||||
|
||||
#[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
|
||||
|
@ -165,7 +165,7 @@ impl Into<Sw> for ClockSrc {
|
||||
ClockSrc::MSI(..) => Sw::MSIS,
|
||||
ClockSrc::HSE(..) => Sw::HSE,
|
||||
ClockSrc::HSI16 => Sw::HSI16,
|
||||
ClockSrc::PLL1R(..) => Sw::PLL1R,
|
||||
ClockSrc::PLL1R(..) => Sw::PLL1_R,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
184
embassy-stm32/src/rcc/wba.rs
Normal file
184
embassy-stm32/src/rcc/wba.rs
Normal file
@ -0,0 +1,184 @@
|
||||
use stm32_metapac::rcc::vals::{Pllsrc, Sw};
|
||||
|
||||
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);
|
||||
|
||||
/// LSI speed
|
||||
pub const LSI_FREQ: Hertz = Hertz(32_000);
|
||||
|
||||
pub use crate::pac::pwr::vals::Vos as VoltageScale;
|
||||
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ClockSrc {
|
||||
HSE(Hertz),
|
||||
HSI16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum PllSrc {
|
||||
HSE(Hertz),
|
||||
HSI16,
|
||||
}
|
||||
|
||||
impl Into<Pllsrc> for PllSrc {
|
||||
fn into(self) -> Pllsrc {
|
||||
match self {
|
||||
PllSrc::HSE(..) => Pllsrc::HSE32,
|
||||
PllSrc::HSI16 => Pllsrc::HSI16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Sw> for ClockSrc {
|
||||
fn into(self) -> Sw {
|
||||
match self {
|
||||
ClockSrc::HSE(..) => Sw::HSE32,
|
||||
ClockSrc::HSI16 => Sw::HSI16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Div {
|
||||
fn div(&self) -> u8;
|
||||
}
|
||||
|
||||
impl Div for APBPrescaler {
|
||||
fn div(&self) -> u8 {
|
||||
match self {
|
||||
Self::DIV1 => 1,
|
||||
Self::DIV2 => 2,
|
||||
Self::DIV4 => 4,
|
||||
Self::DIV8 => 8,
|
||||
Self::DIV16 => 16,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for AHBPrescaler {
|
||||
fn div(&self) -> u8 {
|
||||
match self {
|
||||
Self::DIV1 => 1,
|
||||
Self::DIV2 => 2,
|
||||
Self::DIV4 => 4,
|
||||
Self::DIV8 => 8,
|
||||
Self::DIV16 => 16,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Config {
|
||||
pub mux: ClockSrc,
|
||||
pub ahb_pre: AHBPrescaler,
|
||||
pub apb1_pre: APBPrescaler,
|
||||
pub apb2_pre: APBPrescaler,
|
||||
pub apb7_pre: APBPrescaler,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mux: ClockSrc::HSI16,
|
||||
ahb_pre: AHBPrescaler::DIV1,
|
||||
apb1_pre: APBPrescaler::DIV1,
|
||||
apb2_pre: APBPrescaler::DIV1,
|
||||
apb7_pre: APBPrescaler::DIV1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn init(config: Config) {
|
||||
let sys_clk = match config.mux {
|
||||
ClockSrc::HSE(freq) => {
|
||||
RCC.cr().write(|w| w.set_hseon(true));
|
||||
while !RCC.cr().read().hserdy() {}
|
||||
|
||||
freq.0
|
||||
}
|
||||
ClockSrc::HSI16 => {
|
||||
RCC.cr().write(|w| w.set_hsion(true));
|
||||
while !RCC.cr().read().hsirdy() {}
|
||||
|
||||
HSI_FREQ.0
|
||||
}
|
||||
};
|
||||
|
||||
// TODO make configurable
|
||||
let power_vos = VoltageScale::RANGE1;
|
||||
|
||||
// states and programming delay
|
||||
let wait_states = match power_vos {
|
||||
VoltageScale::RANGE1 => match sys_clk {
|
||||
..=32_000_000 => 0,
|
||||
..=64_000_000 => 1,
|
||||
..=96_000_000 => 2,
|
||||
..=100_000_000 => 3,
|
||||
_ => 4,
|
||||
},
|
||||
VoltageScale::RANGE2 => match sys_clk {
|
||||
..=8_000_000 => 0,
|
||||
..=16_000_000 => 1,
|
||||
_ => 2,
|
||||
},
|
||||
};
|
||||
|
||||
FLASH.acr().modify(|w| {
|
||||
w.set_latency(wait_states);
|
||||
});
|
||||
|
||||
RCC.cfgr1().modify(|w| {
|
||||
w.set_sw(config.mux.into());
|
||||
});
|
||||
|
||||
RCC.cfgr2().modify(|w| {
|
||||
w.set_hpre(config.ahb_pre.into());
|
||||
w.set_ppre1(config.apb1_pre.into());
|
||||
w.set_ppre2(config.apb2_pre.into());
|
||||
});
|
||||
|
||||
RCC.cfgr3().modify(|w| {
|
||||
w.set_ppre7(config.apb7_pre.into());
|
||||
});
|
||||
|
||||
let ahb_freq: u32 = sys_clk / config.ahb_pre.div() as u32;
|
||||
let (apb1_freq, apb1_tim_freq) = match config.apb1_pre.div() {
|
||||
1 => (ahb_freq, ahb_freq),
|
||||
div => {
|
||||
let freq = ahb_freq / div as u32;
|
||||
(freq, freq * 2)
|
||||
}
|
||||
};
|
||||
let (apb2_freq, apb2_tim_freq) = match config.apb2_pre.div() {
|
||||
1 => (ahb_freq, ahb_freq),
|
||||
div => {
|
||||
let freq = ahb_freq / div as u32;
|
||||
(freq, freq * 2)
|
||||
}
|
||||
};
|
||||
let (apb7_freq, _apb7_tim_freq) = match config.apb7_pre.div() {
|
||||
1 => (ahb_freq, ahb_freq),
|
||||
div => {
|
||||
let freq = ahb_freq / div as u32;
|
||||
(freq, freq * 2)
|
||||
}
|
||||
};
|
||||
|
||||
set_freqs(Clocks {
|
||||
sys: Hertz(sys_clk),
|
||||
ahb1: Hertz(ahb_freq),
|
||||
ahb2: Hertz(ahb_freq),
|
||||
ahb4: Hertz(ahb_freq),
|
||||
apb1: Hertz(apb1_freq),
|
||||
apb2: Hertz(apb2_freq),
|
||||
apb7: Hertz(apb7_freq),
|
||||
apb1_tim: Hertz(apb1_tim_freq),
|
||||
apb2_tim: Hertz(apb2_tim_freq),
|
||||
});
|
||||
}
|
@ -10,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::blocking_mutex::Mutex;
|
||||
|
||||
pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
|
||||
use crate::rcc::bd::BackupDomain;
|
||||
pub use crate::rcc::RtcClockSource;
|
||||
use crate::time::Hertz;
|
||||
|
||||
@ -125,7 +124,6 @@ impl Default for RtcCalibrationCyclePeriod {
|
||||
impl Rtc {
|
||||
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||
RTC::enable_peripheral_clk();
|
||||
BackupDomain::enable_rtc();
|
||||
|
||||
let mut this = Self {
|
||||
#[cfg(feature = "low-power")]
|
||||
|
Reference in New Issue
Block a user