Skip to content

Commit

Permalink
Merge pull request #2012 from mattico/h7-rtc
Browse files Browse the repository at this point in the history
H7: support LSE, LSI, LSEBYP, and RTCCLKSEL
  • Loading branch information
Dirbaio authored Oct 6, 2023
2 parents 65ed19a + 75c1a9a commit f30fc94
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 59 deletions.
2 changes: 1 addition & 1 deletion ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ cargo batch \

rm out/tests/stm32wb55rg/wpan_mac
rm out/tests/stm32wb55rg/wpan_ble

rm out/tests/stm32f207zg/eth

if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
echo No teleprobe token found, skipping running HIL tests
Expand Down
4 changes: 2 additions & 2 deletions embassy-stm32/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1"
atomic-polyfill = "1.0.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-172c5ea18824d7cd38decb210e4af441fa3816cb" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594" }
vcell = "0.1.3"
bxcan = "0.7.0"
nb = "1.0.0"
Expand All @@ -78,7 +78,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-172c5ea18824d7cd38decb210e4af441fa3816cb", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f0f06b4c95bd9e185e4aa5f2e1d4b76ba84f1594", default-features = false, features = ["metadata"]}


[features]
Expand Down
4 changes: 2 additions & 2 deletions embassy-stm32/src/dac/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
foreach_peripheral!(
(dac, $inst:ident) => {
// H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented
#[cfg(rcc_h7)]
#[cfg(any(rcc_h7, rcc_h7rm0433))]
impl crate::rcc::sealed::RccPeripheral for peripherals::$inst {
fn frequency() -> crate::time::Hertz {
critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 })
Expand All @@ -590,7 +590,7 @@ foreach_peripheral!(
}
}

#[cfg(rcc_h7)]
#[cfg(any(rcc_h7, rcc_h7rm0433))]
impl crate::rcc::RccPeripheral for peripherals::$inst {}

impl crate::dac::sealed::Instance for peripherals::$inst {
Expand Down
47 changes: 33 additions & 14 deletions embassy-stm32/src/rcc/bd.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
#[allow(dead_code)]
#[derive(Clone, Copy)]
pub enum LseCfg {
Oscillator(LseDrive),
Bypass,
}

impl Default for LseCfg {
fn default() -> Self {
Self::Oscillator(Default::default())
}
}

#[allow(dead_code)]
#[derive(Default, Clone, Copy)]
pub enum LseDrive {
#[cfg(any(rtc_v2f7, rtc_v2l4))]
Low = 0,
MediumLow = 0x01,
#[default]
MediumHigh = 0x02,
#[cfg(any(rtc_v2f7, rtc_v2l4))]
High = 0x03,
}

#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
// All families but these have the LSEDRV register
#[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
fn from(value: LseDrive) -> Self {
use crate::pac::rcc::vals::Lsedrv;

match value {
#[cfg(any(rtc_v2f7, rtc_v2l4))]
LseDrive::Low => Lsedrv::LOW,
LseDrive::MediumLow => Lsedrv::MEDIUMLOW,
LseDrive::MediumHigh => Lsedrv::MEDIUMHIGH,
#[cfg(any(rtc_v2f7, rtc_v2l4))]
LseDrive::High => Lsedrv::HIGH,
}
}
Expand Down Expand Up @@ -87,14 +97,19 @@ impl BackupDomain {
rtc_v3u5
))]
#[allow(dead_code, unused_variables)]
pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseDrive>) {
pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseCfg>) {
use atomic_polyfill::{compiler_fence, Ordering};

match clock_source {
RtcClockSource::LSI => assert!(lsi),
RtcClockSource::LSE => assert!(&lse.is_some()),
RtcClockSource::LSE => assert!(lse.is_some()),
_ => {}
};
let (lse_en, lse_byp, lse_drv) = match lse {
Some(LseCfg::Oscillator(lse_drv)) => (true, false, Some(lse_drv)),
Some(LseCfg::Bypass) => (true, true, None),
None => (false, false, None),
};

if lsi {
#[cfg(rtc_v3u5)]
Expand Down Expand Up @@ -131,10 +146,11 @@ impl BackupDomain {
{
ok &= reg.rtcen() == (clock_source != RtcClockSource::NOCLOCK);
}
ok &= reg.lseon() == lse.is_some();
#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
if let Some(lse_drive) = lse {
ok &= reg.lsedrv() == lse_drive.into();
ok &= reg.lseon() == lse_en;
ok &= reg.lsebyp() == lse_byp;
#[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
if let Some(lse_drv) = lse_drv {
ok &= reg.lsedrv() == lse_drv.into();
}

// if configuration is OK, we're done.
Expand All @@ -153,10 +169,13 @@ impl BackupDomain {
Self::modify(|w| w.set_bdrst(false));
}

if let Some(lse_drive) = lse {
if lse_en {
Self::modify(|w| {
#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
w.set_lsedrv(lse_drive.into());
#[cfg(not(any(rcc_f1, rcc_f1cl, rcc_f100, rcc_f2, rcc_f4, rcc_f400, rcc_f410, rcc_l1)))]
if let Some(lse_drv) = lse_drv {
w.set_lsedrv(lse_drv.into());
}
w.set_lsebyp(lse_byp);
w.set_lseon(true);
});

Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/rcc/f4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ pub(crate) unsafe fn init(config: Config) {
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pllsai: plls.pllsaiclk.map(Hertz),

rtc: rtc,
rtc,
rtc_hse: None,
});
}
Expand Down
57 changes: 54 additions & 3 deletions embassy-stm32/src/rcc/h.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
pub use crate::pac::rcc::vals::Ckpersel as PerClockSource;
use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre};
use crate::pac::{FLASH, PWR, RCC};
#[cfg(stm32h7)]
use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource};
use crate::rcc::{set_freqs, Clocks};
use crate::time::Hertz;

Expand Down Expand Up @@ -46,9 +48,9 @@ pub enum VoltageScale {
pub enum HseMode {
/// crystal/ceramic oscillator (HSEBYP=0)
Oscillator,
/// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
/// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
Bypass,
/// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
/// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
#[cfg(any(rcc_h5, rcc_h50))]
BypassDigital,
}
Expand All @@ -61,6 +63,15 @@ pub struct Hse {
pub mode: HseMode,
}

#[cfg(stm32h7)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Lse {
/// 32.768 kHz crystal/ceramic oscillator (LSEBYP=0)
Oscillator,
/// external clock input up to 1MHz (LSEBYP=1)
Bypass(Hertz),
}

#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Hsi {
/// 64Mhz
Expand Down Expand Up @@ -157,6 +168,10 @@ impl From<TimerPrescaler> for Timpre {
pub struct Config {
pub hsi: Option<Hsi>,
pub hse: Option<Hse>,
#[cfg(stm32h7)]
pub lse: Option<Lse>,
#[cfg(stm32h7)]
pub lsi: bool,
pub csi: bool,
pub hsi48: bool,
pub sys: Sysclk,
Expand All @@ -181,13 +196,19 @@ pub struct Config {
pub adc_clock_source: AdcClockSource,
pub timer_prescaler: TimerPrescaler,
pub voltage_scale: VoltageScale,
#[cfg(stm32h7)]
pub rtc_mux: Option<RtcClockSource>,
}

impl Default for Config {
fn default() -> Self {
Self {
hsi: Some(Hsi::Mhz64),
hse: None,
#[cfg(stm32h7)]
lse: None,
#[cfg(stm32h7)]
lsi: false,
csi: false,
hsi48: false,
sys: Sysclk::HSI,
Expand All @@ -210,6 +231,8 @@ impl Default for Config {
adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5
timer_prescaler: TimerPrescaler::DefaultX2,
voltage_scale: VoltageScale::Scale0,
#[cfg(stm32h7)]
rtc_mux: None,
}
}
}
Expand Down Expand Up @@ -448,6 +471,19 @@ pub(crate) unsafe fn init(config: Config) {

flash_setup(hclk, config.voltage_scale);

#[cfg(stm32h7)]
{
let lsecfg = config.lse.map(|lse| match lse {
Lse::Bypass(freq) => {
assert!(freq <= Hertz(1_000_000));
LseCfg::Bypass
}
Lse::Oscillator => LseCfg::Oscillator(Default::default()),
});

BackupDomain::configure_ls(config.rtc_mux.unwrap_or(RtcClockSource::NOCLOCK), config.lsi, lsecfg);
}

#[cfg(stm32h7)]
{
RCC.d1cfgr().modify(|w| {
Expand Down Expand Up @@ -512,6 +548,17 @@ pub(crate) unsafe fn init(config: Config) {
while !pac::SYSCFG.cccsr().read().ready() {}
}

#[cfg(stm32h7)]
let rtc_clk = match config.rtc_mux {
Some(RtcClockSource::LSI) => Some(LSI_FREQ),
Some(RtcClockSource::LSE) => Some(match config.lse {
Some(Lse::Oscillator) => Hertz(32768),
Some(Lse::Bypass(freq)) => freq,
None => panic!("LSE not configured"),
}),
_ => None,
};

set_freqs(Clocks {
sys,
ahb1: hclk,
Expand All @@ -525,7 +572,11 @@ pub(crate) unsafe fn init(config: Config) {
apb4,
apb1_tim,
apb2_tim,
adc: adc,
adc,
#[cfg(stm32h7)]
rtc: rtc_clk,
#[cfg(stm32h7)]
rtc_hse: None,
});
}

Expand Down
2 changes: 1 addition & 1 deletion embassy-stm32/src/rcc/l4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ pub(crate) unsafe fn init(config: Config) {
w.set_msirgsel(true);
w.set_msion(true);

if let RtcClockSource::LSE = config.rtc_mux {
if config.rtc_mux == RtcClockSource::LSE {
// If LSE is enabled, enable calibration of MSI
w.set_msipllen(true);
} else {
Expand Down
59 changes: 49 additions & 10 deletions embassy-stm32/src/rcc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use mco::*;
#[cfg_attr(rcc_c0, path = "c0.rs")]
#[cfg_attr(rcc_g0, path = "g0.rs")]
#[cfg_attr(rcc_g4, path = "g4.rs")]
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab), path = "h.rs")]
#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
#[cfg_attr(rcc_l0, path = "l0.rs")]
#[cfg_attr(rcc_l1, path = "l1.rs")]
#[cfg_attr(rcc_l4, path = "l4.rs")]
Expand Down Expand Up @@ -57,26 +57,54 @@ pub struct Clocks {
pub apb2: Hertz,
#[cfg(not(any(rcc_c0, rcc_g0)))]
pub apb2_tim: Hertz,
#[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5))]
#[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_u5))]
pub apb3: Hertz,
#[cfg(any(rcc_h7, rcc_h7ab))]
#[cfg(any(rcc_h7, rcc_h7rm0433, 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_wba, rcc_wl5, rcc_wle
rcc_l4,
rcc_l5,
rcc_f2,
rcc_f4,
rcc_f410,
rcc_f7,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_g4,
rcc_u5,
rcc_wb,
rcc_wba,
rcc_wl5,
rcc_wle
))]
pub ahb2: Hertz,
#[cfg(any(
rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5, rcc_wb, rcc_wl5,
rcc_l4,
rcc_l5,
rcc_f2,
rcc_f4,
rcc_f410,
rcc_f7,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_u5,
rcc_wb,
rcc_wl5,
rcc_wle
))]
pub ahb3: Hertz,
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))]
#[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab, rcc_wba))]
pub ahb4: Hertz,

#[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
Expand All @@ -88,7 +116,18 @@ pub struct Clocks {
#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
pub pllsai: Option<Hertz>,

#[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
#[cfg(any(
rcc_f1,
rcc_f100,
rcc_f1cl,
rcc_h5,
rcc_h50,
rcc_h7,
rcc_h7rm0433,
rcc_h7ab,
rcc_f3,
rcc_g4
))]
pub adc: Option<Hertz>,

#[cfg(any(rcc_f3, rcc_g4))]
Expand All @@ -97,11 +136,11 @@ pub struct Clocks {
#[cfg(stm32f334)]
pub hrtim: Option<Hertz>,

#[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7))]
#[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7, rcc_h7, rcc_h7rm0433, rcc_h7ab))]
/// Set only if the lsi or lse is configured, indicates stop is supported
pub rtc: Option<Hertz>,

#[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
#[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_h7, rcc_h7rm0433, rcc_h7ab))]
/// Set if the hse is configured, indicates stop is not supported
pub rtc_hse: Option<Hertz>,
}
Expand Down
Loading

0 comments on commit f30fc94

Please sign in to comment.