Enable RTC on STM32WL chips (#1645)
* Add clippy allow to not report if same then branch * Support enabling RTC clock on STM32WL * Add clippy allow to not report if same then branch * Support enabling RTC clock on STM32WL * Add rtc example for stm32wl * Address code review feedback
This commit is contained in:
parent
7b36fe049d
commit
3bae533066
5 changed files with 108 additions and 4 deletions
|
@ -1,4 +1,5 @@
|
||||||
use crate::pac::{FLASH, RCC};
|
use crate::pac::pwr::vals::Dbp;
|
||||||
|
use crate::pac::{FLASH, PWR, RCC};
|
||||||
use crate::rcc::{set_freqs, Clocks};
|
use crate::rcc::{set_freqs, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
|
@ -184,6 +185,8 @@ pub struct Config {
|
||||||
pub apb1_pre: APBPrescaler,
|
pub apb1_pre: APBPrescaler,
|
||||||
pub apb2_pre: APBPrescaler,
|
pub apb2_pre: APBPrescaler,
|
||||||
pub enable_lsi: bool,
|
pub enable_lsi: bool,
|
||||||
|
pub enable_rtc_apb: bool,
|
||||||
|
pub rtc_mux: RtcClockSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
@ -196,10 +199,25 @@ impl Default for Config {
|
||||||
apb1_pre: APBPrescaler::NotDivided,
|
apb1_pre: APBPrescaler::NotDivided,
|
||||||
apb2_pre: APBPrescaler::NotDivided,
|
apb2_pre: APBPrescaler::NotDivided,
|
||||||
enable_lsi: false,
|
enable_lsi: false,
|
||||||
|
enable_rtc_apb: false,
|
||||||
|
rtc_mux: RtcClockSource::LSI32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum RtcClockSource {
|
||||||
|
LSE32,
|
||||||
|
LSI32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Lsedrv {
|
||||||
|
Low = 0,
|
||||||
|
MediumLow = 1,
|
||||||
|
MediumHigh = 2,
|
||||||
|
High = 3,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn init(config: Config) {
|
pub(crate) unsafe fn init(config: Config) {
|
||||||
let (sys_clk, sw, vos) = match config.mux {
|
let (sys_clk, sw, vos) = match config.mux {
|
||||||
ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2),
|
ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2),
|
||||||
|
@ -266,6 +284,32 @@ pub(crate) unsafe fn init(config: Config) {
|
||||||
|
|
||||||
while FLASH.acr().read().latency() != ws {}
|
while FLASH.acr().read().latency() != ws {}
|
||||||
|
|
||||||
|
match config.rtc_mux {
|
||||||
|
RtcClockSource::LSE32 => {
|
||||||
|
// 1. Unlock the backup domain
|
||||||
|
PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED));
|
||||||
|
|
||||||
|
// 2. Setup the LSE
|
||||||
|
RCC.bdcr().modify(|w| {
|
||||||
|
// Enable LSE
|
||||||
|
w.set_lseon(true);
|
||||||
|
// Max drive strength
|
||||||
|
// TODO: should probably be settable
|
||||||
|
w.set_lsedrv(Lsedrv::High as u8); //---// PAM - should not be commented
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait until LSE is running
|
||||||
|
while !RCC.bdcr().read().lserdy() {}
|
||||||
|
}
|
||||||
|
RtcClockSource::LSI32 => {
|
||||||
|
// Turn on the internal 32 kHz LSI oscillator
|
||||||
|
RCC.csr().modify(|w| w.set_lsion(true));
|
||||||
|
|
||||||
|
// Wait until LSI is running
|
||||||
|
while !RCC.csr().read().lsirdy() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match config.mux {
|
match config.mux {
|
||||||
ClockSrc::HSI16 => {
|
ClockSrc::HSI16 => {
|
||||||
// Enable HSI16
|
// Enable HSI16
|
||||||
|
@ -287,11 +331,26 @@ pub(crate) unsafe fn init(config: Config) {
|
||||||
w.set_msirgsel(true);
|
w.set_msirgsel(true);
|
||||||
w.set_msirange(range.into());
|
w.set_msirange(range.into());
|
||||||
w.set_msion(true);
|
w.set_msion(true);
|
||||||
|
|
||||||
|
if let RtcClockSource::LSE32 = config.rtc_mux {
|
||||||
|
// If LSE is enabled, enable calibration of MSI
|
||||||
|
w.set_msipllen(true);
|
||||||
|
} else {
|
||||||
|
w.set_msipllen(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
while !RCC.cr().read().msirdy() {}
|
while !RCC.cr().read().msirdy() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.enable_rtc_apb {
|
||||||
|
// enable peripheral clock for communication
|
||||||
|
crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true));
|
||||||
|
|
||||||
|
// read to allow the pwr clock to enable
|
||||||
|
crate::pac::PWR.cr1().read();
|
||||||
|
}
|
||||||
|
|
||||||
RCC.extcfgr().modify(|w| {
|
RCC.extcfgr().modify(|w| {
|
||||||
if config.shd_ahb_pre == AHBPrescaler::NotDivided {
|
if config.shd_ahb_pre == AHBPrescaler::NotDivided {
|
||||||
w.set_shdhpre(0);
|
w.set_shdhpre(0);
|
||||||
|
|
|
@ -172,6 +172,7 @@ impl sealed::Instance for crate::peripherals::RTC {
|
||||||
const BACKUP_REGISTER_COUNT: usize = 32;
|
const BACKUP_REGISTER_COUNT: usize = 32;
|
||||||
|
|
||||||
fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> {
|
fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> {
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
if register < Self::BACKUP_REGISTER_COUNT {
|
if register < Self::BACKUP_REGISTER_COUNT {
|
||||||
//Some(rtc.bkpr()[register].read().bits())
|
//Some(rtc.bkpr()[register].read().bits())
|
||||||
None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC
|
None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
runner = "probe-rs run --chip STM32WLE5JCIx"
|
runner = "probe-rs run --chip STM32WLE5JCIx"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "thumbv7em-none-eabihf"
|
target = "thumbv7em-none-eabi"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
DEFMT_LOG = "trace"
|
DEFMT_LOG = "trace"
|
||||||
|
|
|
@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0"
|
||||||
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] }
|
||||||
embassy-embedded-hal = {version = "0.1.0", path = "../../embassy-embedded-hal" }
|
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
|
||||||
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
|
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
|
||||||
lora-phy = { version = "1" }
|
lora-phy = { version = "1" }
|
||||||
lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"] }
|
lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"] }
|
||||||
|
@ -25,6 +25,7 @@ embedded-storage = "0.3.0"
|
||||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
heapless = { version = "0.7.5", default-features = false }
|
heapless = { version = "0.7.5", default-features = false }
|
||||||
|
chrono = { version = "^0.4", default-features = false }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
|
lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" }
|
||||||
|
|
43
examples/stm32wl/src/bin/rtc.rs
Normal file
43
examples/stm32wl/src/bin/rtc.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use chrono::{NaiveDate, NaiveDateTime};
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::rcc::{self, ClockSrc};
|
||||||
|
use embassy_stm32::rtc::{Rtc, RtcConfig};
|
||||||
|
use embassy_stm32::Config;
|
||||||
|
use embassy_time::{Duration, 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::HSE32;
|
||||||
|
config.rcc.rtc_mux = rcc::RtcClockSource::LSE32;
|
||||||
|
config.rcc.enable_rtc_apb = true;
|
||||||
|
embassy_stm32::init(config)
|
||||||
|
};
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let now = NaiveDate::from_ymd_opt(2020, 5, 15)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(10, 30, 15)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut rtc = Rtc::new(
|
||||||
|
p.RTC,
|
||||||
|
RtcConfig::default().clock_config(embassy_stm32::rtc::RtcClockSource::LSE),
|
||||||
|
);
|
||||||
|
info!("Got RTC! {:?}", now.timestamp());
|
||||||
|
|
||||||
|
rtc.set_datetime(now.into()).expect("datetime not set");
|
||||||
|
|
||||||
|
// In reality the delay would be much longer
|
||||||
|
Timer::after(Duration::from_millis(20000)).await;
|
||||||
|
|
||||||
|
let then: NaiveDateTime = rtc.now().unwrap().into();
|
||||||
|
info!("Got RTC! {:?}", then.timestamp());
|
||||||
|
}
|
Loading…
Reference in a new issue