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:
		@@ -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::time::Hertz;
 | 
			
		||||
 | 
			
		||||
@@ -184,6 +185,8 @@ pub struct Config {
 | 
			
		||||
    pub apb1_pre: APBPrescaler,
 | 
			
		||||
    pub apb2_pre: APBPrescaler,
 | 
			
		||||
    pub enable_lsi: bool,
 | 
			
		||||
    pub enable_rtc_apb: bool,
 | 
			
		||||
    pub rtc_mux: RtcClockSource,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Config {
 | 
			
		||||
@@ -196,10 +199,25 @@ impl Default for Config {
 | 
			
		||||
            apb1_pre: APBPrescaler::NotDivided,
 | 
			
		||||
            apb2_pre: APBPrescaler::NotDivided,
 | 
			
		||||
            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) {
 | 
			
		||||
    let (sys_clk, sw, vos) = match config.mux {
 | 
			
		||||
        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 {}
 | 
			
		||||
 | 
			
		||||
    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 {
 | 
			
		||||
        ClockSrc::HSI16 => {
 | 
			
		||||
            // Enable HSI16
 | 
			
		||||
@@ -287,11 +331,26 @@ pub(crate) unsafe fn init(config: Config) {
 | 
			
		||||
                w.set_msirgsel(true);
 | 
			
		||||
                w.set_msirange(range.into());
 | 
			
		||||
                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() {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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| {
 | 
			
		||||
        if config.shd_ahb_pre == AHBPrescaler::NotDivided {
 | 
			
		||||
            w.set_shdhpre(0);
 | 
			
		||||
 
 | 
			
		||||
@@ -172,6 +172,7 @@ impl sealed::Instance for crate::peripherals::RTC {
 | 
			
		||||
    const BACKUP_REGISTER_COUNT: usize = 32;
 | 
			
		||||
 | 
			
		||||
    fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> {
 | 
			
		||||
        #[allow(clippy::if_same_then_else)]
 | 
			
		||||
        if register < Self::BACKUP_REGISTER_COUNT {
 | 
			
		||||
            //Some(rtc.bkpr()[register].read().bits())
 | 
			
		||||
            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"
 | 
			
		||||
 | 
			
		||||
[build]
 | 
			
		||||
target = "thumbv7em-none-eabihf"
 | 
			
		||||
target = "thumbv7em-none-eabi"
 | 
			
		||||
 | 
			
		||||
[env]
 | 
			
		||||
DEFMT_LOG = "trace"
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
 | 
			
		||||
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-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-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
 | 
			
		||||
lora-phy = { version = "1" }
 | 
			
		||||
@@ -25,6 +25,7 @@ embedded-storage = "0.3.0"
 | 
			
		||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
 | 
			
		||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
 | 
			
		||||
heapless = { version = "0.7.5", default-features = false }
 | 
			
		||||
chrono = { version = "^0.4", default-features = false }
 | 
			
		||||
 | 
			
		||||
[patch.crates-io]
 | 
			
		||||
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());
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user