Merge pull request #4707 from esden/update-stm32-metapack-for-l4-rtc

stm32-metapack: Corrects the RTC register map for l4p and l4q.
This commit is contained in:
Dario Nieuwenhuis 2025-09-25 23:28:06 +00:00 committed by GitHub
commit 70ad2c4482
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 36 additions and 49 deletions

View File

@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- feat: Allow OSPI DMA writes larger than 64kB using chunking - feat: Allow OSPI DMA writes larger than 64kB using chunking
- feat: More ADC enums for g0 PAC, API change for oversampling, allow separate sample times - feat: More ADC enums for g0 PAC, API change for oversampling, allow separate sample times
- feat: Add USB CRS sync support for STM32C071 - feat: Add USB CRS sync support for STM32C071
- fix: RTC register definition for STM32L4P5 and L4Q5 as they use v3 register map.
- fix: Cut down the capabilities of the STM32L412 and L422 RTC as those are missing binary timer mode and underflow interrupt.
## 0.4.0 - 2025-08-26 ## 0.4.0 - 2025-08-26

View File

@ -66,6 +66,10 @@ build = [
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l431cb", "time", "time-driver-any"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l431cb", "time", "time-driver-any"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l476vg", "time", "time-driver-any"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l476vg", "time", "time-driver-any"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l422cb", "time", "time-driver-any"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l422cb", "time", "time-driver-any"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l4p5ae", "time", "time-driver-any", "single-bank"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l4q5zg", "time", "time-driver-any", "single-bank"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l4r9vi", "time", "time-driver-any", "dual-bank"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32l4s7vi", "time", "time-driver-any", "dual-bank"]},
{target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb15cc", "time", "time-driver-any"]}, {target = "thumbv7em-none-eabi", features = ["defmt", "exti", "stm32wb15cc", "time", "time-driver-any"]},
{target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l072cz", "time", "time-driver-any"]}, {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l072cz", "time", "time-driver-any"]},
{target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l041f6", "time", "time-driver-any"]}, {target = "thumbv6m-none-eabi", features = ["defmt", "exti", "stm32l041f6", "time", "time-driver-any"]},
@ -174,7 +178,7 @@ futures-util = { version = "0.3.30", default-features = false }
sdio-host = "0.9.0" sdio-host = "0.9.0"
critical-section = "1.1" critical-section = "1.1"
#stm32-metapac = { version = "18" } #stm32-metapac = { version = "18" }
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cf72eac610259fd78ef16f1c63be69a144d75f7" } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0" }
vcell = "0.1.3" vcell = "0.1.3"
nb = "1.0.0" nb = "1.0.0"
@ -204,7 +208,7 @@ proc-macro2 = "1.0.36"
quote = "1.0.15" quote = "1.0.15"
#stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} #stm32-metapac = { version = "18", default-features = false, features = ["metadata"]}
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cf72eac610259fd78ef16f1c63be69a144d75f7", default-features = false, features = ["metadata"] } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b9f6b0c542d85ee695d71c35ced195e0cef51ac0", default-features = false, features = ["metadata"] }
[features] [features]
default = ["rt"] default = ["rt"]

View File

@ -52,9 +52,9 @@ impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
} }
} }
#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] #[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0)))]
type Bdcr = crate::pac::rcc::regs::Bdcr; type Bdcr = crate::pac::rcc::regs::Bdcr;
#[cfg(any(rtc_v2l0, rtc_v2l1))] #[cfg(any(rtc_v2_l0, rtc_v2_l1))]
type Bdcr = crate::pac::rcc::regs::Csr; type Bdcr = crate::pac::rcc::regs::Csr;
#[cfg(any(stm32c0))] #[cfg(any(stm32c0))]
type Bdcr = crate::pac::rcc::regs::Csr1; type Bdcr = crate::pac::rcc::regs::Csr1;
@ -76,9 +76,9 @@ fn unlock() {
} }
fn bdcr() -> Reg<Bdcr, RW> { fn bdcr() -> Reg<Bdcr, RW> {
#[cfg(any(rtc_v2l0, rtc_v2l1))] #[cfg(any(rtc_v2_l0, rtc_v2_l1))]
return crate::pac::RCC.csr(); return crate::pac::RCC.csr();
#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))] #[cfg(not(any(rtc_v2_l0, rtc_v2_l1, stm32c0)))]
return crate::pac::RCC.bdcr(); return crate::pac::RCC.bdcr();
#[cfg(any(stm32c0))] #[cfg(any(stm32c0))]
return crate::pac::RCC.csr1(); return crate::pac::RCC.csr1();
@ -273,7 +273,7 @@ impl LsConfig {
if self.rtc != RtcClockSource::DISABLE { if self.rtc != RtcClockSource::DISABLE {
bdcr().modify(|w| { bdcr().modify(|w| {
#[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] #[cfg(any(rtc_v2_h7, rtc_v2_l4, rtc_v2_wb, rtc_v3_base, rtc_v3_u5))]
assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet."); assert!(!w.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
#[cfg(not(rcc_wba))] #[cfg(not(rcc_wba))]

View File

@ -1,4 +1,8 @@
#[cfg(feature = "time")]
use embassy_time::{Duration, TICK_HZ};
use super::{bcd2_to_byte, DateTimeError, Rtc, RtcError}; use super::{bcd2_to_byte, DateTimeError, Rtc, RtcError};
use crate::interrupt::typelevel::Interrupt;
use crate::peripherals::RTC; use crate::peripherals::RTC;
use crate::rtc::SealedInstance; use crate::rtc::SealedInstance;
@ -11,7 +15,7 @@ pub(super) struct RtcInstant {
} }
impl RtcInstant { impl RtcInstant {
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
const fn from(second: u8, subsecond: u16) -> Result<Self, DateTimeError> { const fn from(second: u8, subsecond: u16) -> Result<Self, DateTimeError> {
if second > 59 { if second > 59 {
Err(DateTimeError::InvalidSecond) Err(DateTimeError::InvalidSecond)
@ -38,8 +42,6 @@ impl core::ops::Sub for RtcInstant {
type Output = embassy_time::Duration; type Output = embassy_time::Duration;
fn sub(self, rhs: Self) -> Self::Output { fn sub(self, rhs: Self) -> Self::Output {
use embassy_time::{Duration, TICK_HZ};
let second = if self.second < rhs.second { let second = if self.second < rhs.second {
self.second + 60 self.second + 60
} else { } else {
@ -129,11 +131,6 @@ impl Rtc {
requested_duration: embassy_time::Duration, requested_duration: embassy_time::Duration,
cs: critical_section::CriticalSection, cs: critical_section::CriticalSection,
) { ) {
use embassy_time::{Duration, TICK_HZ};
#[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
use crate::pac::rtc::vals::Calrf;
// Panic if the rcc mod knows we're not using low-power rtc // Panic if the rcc mod knows we're not using low-power rtc
#[cfg(any(rcc_wb, rcc_f4, rcc_f410))] #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
unsafe { crate::rcc::get_freqs() }.rtc.to_hertz().unwrap(); unsafe { crate::rcc::get_freqs() }.rtc.to_hertz().unwrap();
@ -150,17 +147,15 @@ impl Rtc {
self.write(false, |regs| { self.write(false, |regs| {
regs.cr().modify(|w| w.set_wute(false)); regs.cr().modify(|w| w.set_wute(false));
#[cfg(any( #[cfg(rtc_v2)]
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
))]
{ {
regs.isr().modify(|w| w.set_wutf(false)); regs.isr().modify(|w| w.set_wutf(false));
while !regs.isr().read().wutwf() {} while !regs.isr().read().wutwf() {}
} }
#[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] #[cfg(rtc_v3)]
{ {
regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); regs.scr().write(|w| w.set_cwutf(crate::pac::rtc::vals::Calrf::CLEAR));
while !regs.icsr().read().wutwf() {} while !regs.icsr().read().wutwf() {}
} }
@ -185,10 +180,6 @@ impl Rtc {
/// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
/// was called, otherwise none /// was called, otherwise none
pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> { pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
use crate::interrupt::typelevel::Interrupt;
#[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))]
use crate::pac::rtc::vals::Calrf;
let instant = self.instant().unwrap(); let instant = self.instant().unwrap();
if RTC::regs().cr().read().wute() { if RTC::regs().cr().read().wute() {
trace!("rtc: stop wakeup alarm at {}", instant); trace!("rtc: stop wakeup alarm at {}", instant);
@ -197,13 +188,10 @@ impl Rtc {
regs.cr().modify(|w| w.set_wutie(false)); regs.cr().modify(|w| w.set_wutie(false));
regs.cr().modify(|w| w.set_wute(false)); regs.cr().modify(|w| w.set_wute(false));
#[cfg(any( #[cfg(rtc_v2)]
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
))]
regs.isr().modify(|w| w.set_wutf(false)); regs.isr().modify(|w| w.set_wutf(false));
#[cfg(rtc_v3)]
#[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] regs.scr().write(|w| w.set_cwutf(crate::pac::rtc::vals::Calrf::CLEAR));
regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR));
// Check RM for EXTI and/or NVIC section, "Event event input mapping" or "EXTI interrupt/event mapping" or something similar, // Check RM for EXTI and/or NVIC section, "Event event input mapping" or "EXTI interrupt/event mapping" or something similar,
// there is a table for every "Event input" / "EXTI Line". // there is a table for every "Event input" / "EXTI Line".
@ -222,8 +210,6 @@ impl Rtc {
} }
pub(crate) fn enable_wakeup_line(&self) { pub(crate) fn enable_wakeup_line(&self) {
use crate::interrupt::typelevel::Interrupt;
<RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() }; unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };

View File

@ -18,14 +18,9 @@ use crate::pac::rtc::regs::{Dr, Tr};
use crate::time::Hertz; use crate::time::Hertz;
/// refer to AN4759 to compare features of RTC2 and RTC3 /// refer to AN4759 to compare features of RTC2 and RTC3
#[cfg_attr(any(rtc_v1), path = "v1.rs")] #[cfg_attr(rtc_v1, path = "v1.rs")]
#[cfg_attr( #[cfg_attr(rtc_v2, path = "v2.rs")]
any( #[cfg_attr(rtc_v3, path = "v3.rs")]
rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb
),
path = "v2.rs"
)]
#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs, rtc_v3c0), path = "v3.rs")]
mod _version; mod _version;
#[allow(unused_imports)] #[allow(unused_imports)]
pub use _version::*; pub use _version::*;
@ -72,12 +67,12 @@ impl RtcTimeProvider {
// Calculate second fraction and multiply to microseconds // Calculate second fraction and multiply to microseconds
// Formula from RM0410 // Formula from RM0410
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
let us = { let us = {
let prediv = RTC::regs().prer().read().prediv_s() as f32; let prediv = RTC::regs().prer().read().prediv_s() as f32;
(((prediv - _ss as f32) / (prediv + 1.0)) * 1e6).min(999_999.0) as u32 (((prediv - _ss as f32) / (prediv + 1.0)) * 1e6).min(999_999.0) as u32
}; };
#[cfg(rtc_v2f2)] #[cfg(rtc_v2_f2)]
let us = 0; let us = 0;
DateTime::from(year, month, day, weekday, hour, minute, second, us).map_err(RtcError::InvalidDateTime) DateTime::from(year, month, day, weekday, hour, minute, second, us).map_err(RtcError::InvalidDateTime)
@ -87,9 +82,9 @@ impl RtcTimeProvider {
fn read<R>(&self, mut f: impl FnMut(Dr, Tr, u16) -> Result<R, RtcError>) -> Result<R, RtcError> { fn read<R>(&self, mut f: impl FnMut(Dr, Tr, u16) -> Result<R, RtcError>) -> Result<R, RtcError> {
let r = RTC::regs(); let r = RTC::regs();
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
let read_ss = || r.ssr().read().ss(); let read_ss = || r.ssr().read().ss();
#[cfg(rtc_v2f2)] #[cfg(rtc_v2_f2)]
let read_ss = || 0; let read_ss = || 0;
let mut ss = read_ss(); let mut ss = read_ss();
@ -168,7 +163,7 @@ impl Rtc {
this.configure(async_psc, sync_psc); this.configure(async_psc, sync_psc);
// Wait for the clock to update after initialization // Wait for the clock to update after initialization
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
{ {
let now = this.time_provider().read(|_, _, ss| Ok(ss)).unwrap(); let now = this.time_provider().read(|_, _, ss| Ok(ss)).unwrap();
while now == this.time_provider().read(|_, _, ss| Ok(ss)).unwrap() {} while now == this.time_provider().read(|_, _, ss| Ok(ss)).unwrap() {}

View File

@ -11,11 +11,11 @@ impl super::Rtc {
pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
self.write(true, |rtc| { self.write(true, |rtc| {
rtc.cr().modify(|w| { rtc.cr().modify(|w| {
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
w.set_bypshad(true); w.set_bypshad(true);
#[cfg(rtc_v2f2)] #[cfg(rtc_v2_f2)]
w.set_fmt(false); w.set_fmt(false);
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR);
w.set_osel(Osel::DISABLED); w.set_osel(Osel::DISABLED);
w.set_pol(Pol::HIGH); w.set_pol(Pol::HIGH);
@ -36,7 +36,7 @@ impl super::Rtc {
/// ///
/// To perform a calibration when `async_prescaler` is less then 3, `sync_prescaler` /// To perform a calibration when `async_prescaler` is less then 3, `sync_prescaler`
/// has to be reduced accordingly (see RM0351 Rev 9, sec 38.3.12). /// has to be reduced accordingly (see RM0351 Rev 9, sec 38.3.12).
#[cfg(not(rtc_v2f2))] #[cfg(not(rtc_v2_f2))]
pub fn calibrate(&mut self, mut clock_drift: f32, period: super::RtcCalibrationCyclePeriod) { pub fn calibrate(&mut self, mut clock_drift: f32, period: super::RtcCalibrationCyclePeriod) {
const RTC_CALR_MIN_PPM: f32 = -487.1; const RTC_CALR_MIN_PPM: f32 = -487.1;
const RTC_CALR_MAX_PPM: f32 = 488.5; const RTC_CALR_MAX_PPM: f32 = 488.5;