commit
						f503417f4c
					
				| @ -6,7 +6,6 @@ use embassy_executor::*; | |||||||
| 
 | 
 | ||||||
| use crate::interrupt; | use crate::interrupt; | ||||||
| use crate::interrupt::typelevel::Interrupt; | use crate::interrupt::typelevel::Interrupt; | ||||||
| use crate::pac::EXTI; |  | ||||||
| use crate::rcc::low_power_ready; | use crate::rcc::low_power_ready; | ||||||
| use crate::time_driver::{get_driver, RtcDriver}; | use crate::time_driver::{get_driver, RtcDriver}; | ||||||
| 
 | 
 | ||||||
| @ -99,8 +98,7 @@ impl Executor { | |||||||
|         crate::interrupt::typelevel::RTC_WKUP::unpend(); |         crate::interrupt::typelevel::RTC_WKUP::unpend(); | ||||||
|         unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; |         unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; | ||||||
| 
 | 
 | ||||||
|         EXTI.rtsr(0).modify(|w| w.set_line(22, true)); |         rtc.enable_wakeup_line(); | ||||||
|         EXTI.imr(0).modify(|w| w.set_line(22, true)); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn configure_pwr(&mut self) { |     fn configure_pwr(&mut self) { | ||||||
|  | |||||||
| @ -87,13 +87,14 @@ impl BackupDomain { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[cfg(any(
 |     #[cfg(any(
 | ||||||
|         rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb |         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)] |     #[allow(dead_code)] | ||||||
|     pub fn enable_rtc() { |     pub fn enable_rtc() { | ||||||
|         let reg = Self::read(); |         let reg = Self::read(); | ||||||
| 
 | 
 | ||||||
|         #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))] |         #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] | ||||||
|         assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |         assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); | ||||||
| 
 | 
 | ||||||
|         if !reg.rtcen() { |         if !reg.rtcen() { | ||||||
| @ -102,47 +103,21 @@ impl BackupDomain { | |||||||
| 
 | 
 | ||||||
|             Self::modify(|w| { |             Self::modify(|w| { | ||||||
|                 // Reset
 |                 // Reset
 | ||||||
|                 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] |                 #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] | ||||||
|                 w.set_bdrst(false); |                 w.set_bdrst(false); | ||||||
| 
 | 
 | ||||||
|                 w.set_rtcen(true); |                 w.set_rtcen(true); | ||||||
|                 w.set_rtcsel(reg.rtcsel()); |                 w.set_rtcsel(reg.rtcsel()); | ||||||
| 
 | 
 | ||||||
|                 // Restore bcdr
 |                 // Restore bcdr
 | ||||||
|                 #[cfg(any(rtc_v2l4, rtc_v2wb))] |                 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] | ||||||
|                 w.set_lscosel(reg.lscosel()); |                 w.set_lscosel(reg.lscosel()); | ||||||
|                 #[cfg(any(rtc_v2l4, rtc_v2wb))] |                 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))] | ||||||
|                 w.set_lscoen(reg.lscoen()); |                 w.set_lscoen(reg.lscoen()); | ||||||
| 
 | 
 | ||||||
|                 w.set_lseon(reg.lseon()); |                 w.set_lseon(reg.lseon()); | ||||||
| 
 | 
 | ||||||
|                 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] |                 #[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(any(rtc_v3, rtc_v3u5))] |  | ||||||
|     #[allow(dead_code)] |  | ||||||
|     pub fn enable_rtc() { |  | ||||||
|         let reg = Self::read(); |  | ||||||
|         assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet."); |  | ||||||
| 
 |  | ||||||
|         if !reg.rtcen() { |  | ||||||
|             Self::modify(|w| w.set_bdrst(true)); |  | ||||||
| 
 |  | ||||||
|             Self::modify(|w| { |  | ||||||
|                 w.set_bdrst(false); |  | ||||||
| 
 |  | ||||||
|                 w.set_rtcen(true); |  | ||||||
|                 w.set_rtcsel(reg.rtcsel()); |  | ||||||
| 
 |  | ||||||
|                 // Restore bcdr
 |  | ||||||
|                 w.set_lscosel(reg.lscosel()); |  | ||||||
|                 w.set_lscoen(reg.lscoen()); |  | ||||||
| 
 |  | ||||||
|                 w.set_lseon(reg.lseon()); |  | ||||||
|                 w.set_lsedrv(reg.lsedrv()); |                 w.set_lsedrv(reg.lsedrv()); | ||||||
|                 w.set_lsebyp(reg.lsebyp()); |                 w.set_lsebyp(reg.lsebyp()); | ||||||
|             }); |             }); | ||||||
|  | |||||||
| @ -47,28 +47,15 @@ struct RtcInstant { | |||||||
|     subsecond: u16, |     subsecond: u16, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(feature = "low-power")] | #[cfg(all(feature = "low-power", feature = "defmt"))] | ||||||
| impl RtcInstant { | impl defmt::Format for RtcInstant { | ||||||
|     pub fn now() -> Self { |     fn format(&self, fmt: defmt::Formatter) { | ||||||
|         let tr = RTC::regs().tr().read(); |         defmt::write!( | ||||||
|         let tr2 = RTC::regs().tr().read(); |             fmt, | ||||||
|         let ssr = RTC::regs().ssr().read().ss(); |             "{}:{}", | ||||||
|         let ssr2 = RTC::regs().ssr().read().ss(); |             self.second, | ||||||
| 
 |             RTC::regs().prer().read().prediv_s() - self.subsecond, | ||||||
|         let st = bcd2_to_byte((tr.st(), tr.su())); |         ) | ||||||
|         let st2 = bcd2_to_byte((tr2.st(), tr2.su())); |  | ||||||
| 
 |  | ||||||
|         assert!(st == st2); |  | ||||||
|         assert!(ssr == ssr2); |  | ||||||
| 
 |  | ||||||
|         let _ = RTC::regs().dr().read(); |  | ||||||
| 
 |  | ||||||
|         let subsecond = ssr; |  | ||||||
|         let second = st; |  | ||||||
| 
 |  | ||||||
|         // trace!("rtc: instant now: st, ssr: {}, {}", st, ssr);
 |  | ||||||
| 
 |  | ||||||
|         Self { second, subsecond } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -85,20 +72,13 @@ impl core::ops::Sub for RtcInstant { | |||||||
|             self.second |             self.second | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         // TODO: read prescaler
 |         let psc = RTC::regs().prer().read().prediv_s() as u32; | ||||||
| 
 | 
 | ||||||
|         let self_ticks = second as u32 * 256 + (255 - self.subsecond as u32); |         let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32); | ||||||
|         let other_ticks = rhs.second as u32 * 256 + (255 - rhs.subsecond as u32); |         let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32); | ||||||
|         let rtc_ticks = self_ticks - other_ticks; |         let rtc_ticks = self_ticks - other_ticks; | ||||||
| 
 | 
 | ||||||
|         //        trace!(
 |         Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64) | ||||||
|         //            "rtc: instant sub: self, other, rtc ticks: {}, {}, {}",
 |  | ||||||
|         //            self_ticks,
 |  | ||||||
|         //            other_ticks,
 |  | ||||||
|         //            rtc_ticks
 |  | ||||||
|         //        );
 |  | ||||||
| 
 |  | ||||||
|         Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / 256u32) as u64) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -198,6 +178,20 @@ impl Rtc { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[cfg(feature = "low-power")] | ||||||
|  |     /// Return the current instant.
 | ||||||
|  |     fn instant(&self) -> RtcInstant { | ||||||
|  |         let r = RTC::regs(); | ||||||
|  |         let tr = r.tr().read(); | ||||||
|  |         let subsecond = r.ssr().read().ss(); | ||||||
|  |         let second = bcd2_to_byte((tr.st(), tr.su())); | ||||||
|  | 
 | ||||||
|  |         // Unlock the registers
 | ||||||
|  |         r.dr().read(); | ||||||
|  | 
 | ||||||
|  |         RtcInstant { second, subsecond } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Return the current datetime.
 |     /// Return the current datetime.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// # Errors
 |     /// # Errors
 | ||||||
|  | |||||||
| @ -1,7 +1,5 @@ | |||||||
| use stm32_metapac::rtc::vals::{Init, Osel, Pol}; | use stm32_metapac::rtc::vals::{Init, Osel, Pol}; | ||||||
| 
 | 
 | ||||||
| #[cfg(feature = "low-power")] |  | ||||||
| use super::RtcInstant; |  | ||||||
| use super::{sealed, RtcConfig}; | use super::{sealed, RtcConfig}; | ||||||
| use crate::pac::rtc::Rtc; | use crate::pac::rtc::Rtc; | ||||||
| use crate::peripherals::RTC; | use crate::peripherals::RTC; | ||||||
| @ -86,17 +84,14 @@ impl super::Rtc { | |||||||
|         let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; |         let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; | ||||||
|         let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); |         let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); | ||||||
| 
 | 
 | ||||||
|         // adjust the rtc ticks to the prescaler
 |         // adjust the rtc ticks to the prescaler and subtract one rtc tick
 | ||||||
|         let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64); |         let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64); | ||||||
|         let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { |         let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { | ||||||
|             u16::MAX - 1 |             u16::MAX - 1 | ||||||
|         } else { |         } else { | ||||||
|             rtc_ticks as u16 |             rtc_ticks as u16 | ||||||
|         }; |         } | ||||||
| 
 |         .saturating_sub(1); | ||||||
|         let duration = Duration::from_ticks( |  | ||||||
|             rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz, |  | ||||||
|         ); |  | ||||||
| 
 | 
 | ||||||
|         self.write(false, |regs| { |         self.write(false, |regs| { | ||||||
|             regs.cr().modify(|w| w.set_wute(false)); |             regs.cr().modify(|w| w.set_wute(false)); | ||||||
| @ -104,13 +99,31 @@ impl super::Rtc { | |||||||
|             while !regs.isr().read().wutwf() {} |             while !regs.isr().read().wutwf() {} | ||||||
| 
 | 
 | ||||||
|             regs.cr().modify(|w| w.set_wucksel(prescaler.into())); |             regs.cr().modify(|w| w.set_wucksel(prescaler.into())); | ||||||
|  |             regs.wutr().write(|w| w.set_wut(rtc_ticks)); | ||||||
|             regs.cr().modify(|w| w.set_wute(true)); |             regs.cr().modify(|w| w.set_wute(true)); | ||||||
|             regs.cr().modify(|w| w.set_wutie(true)); |             regs.cr().modify(|w| w.set_wutie(true)); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         trace!("rtc: start wakeup alarm for {} ms", duration.as_millis()); |         trace!( | ||||||
|  |             "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}", | ||||||
|  |             Duration::from_ticks( | ||||||
|  |                 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz, | ||||||
|  |             ) | ||||||
|  |             .as_millis(), | ||||||
|  |             <WakeupPrescaler as Into<u32>>::into(prescaler), | ||||||
|  |             rtc_ticks, | ||||||
|  |             self.instant(), | ||||||
|  |         ); | ||||||
| 
 | 
 | ||||||
|         critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(RtcInstant::now())).is_none())) |         critical_section::with(|cs| assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[cfg(feature = "low-power")] | ||||||
|  |     pub(crate) fn enable_wakeup_line(&self) { | ||||||
|  |         use crate::pac::EXTI; | ||||||
|  | 
 | ||||||
|  |         EXTI.rtsr(0).modify(|w| w.set_line(22, true)); | ||||||
|  |         EXTI.imr(0).modify(|w| w.set_line(22, true)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[cfg(feature = "low-power")] |     #[cfg(feature = "low-power")] | ||||||
| @ -119,7 +132,7 @@ impl super::Rtc { | |||||||
|     pub(crate) fn stop_wakeup_alarm(&self) -> Option<embassy_time::Duration> { |     pub(crate) fn stop_wakeup_alarm(&self) -> Option<embassy_time::Duration> { | ||||||
|         use crate::interrupt::typelevel::Interrupt; |         use crate::interrupt::typelevel::Interrupt; | ||||||
| 
 | 
 | ||||||
|         trace!("rtc: stop wakeup alarm..."); |         trace!("rtc: stop wakeup alarm at {}", self.instant()); | ||||||
| 
 | 
 | ||||||
|         self.write(false, |regs| { |         self.write(false, |regs| { | ||||||
|             regs.cr().modify(|w| w.set_wutie(false)); |             regs.cr().modify(|w| w.set_wutie(false)); | ||||||
| @ -132,7 +145,7 @@ impl super::Rtc { | |||||||
| 
 | 
 | ||||||
|         critical_section::with(|cs| { |         critical_section::with(|cs| { | ||||||
|             if let Some(stop_time) = self.stop_time.borrow(cs).take() { |             if let Some(stop_time) = self.stop_time.borrow(cs).take() { | ||||||
|                 Some(RtcInstant::now() - stop_time) |                 Some(self.instant() - stop_time) | ||||||
|             } else { |             } else { | ||||||
|                 None |                 None | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -46,8 +46,10 @@ async fn async_main(_spawner: Spawner) { | |||||||
| 
 | 
 | ||||||
|     stop_with_rtc(rtc); |     stop_with_rtc(rtc); | ||||||
| 
 | 
 | ||||||
|     info!("Waiting 5 seconds"); |     info!("Waiting..."); | ||||||
|     Timer::after(Duration::from_secs(5)).await; |     Timer::after(Duration::from_secs(2)).await; | ||||||
|  |     info!("Waiting..."); | ||||||
|  |     Timer::after(Duration::from_secs(3)).await; | ||||||
| 
 | 
 | ||||||
|     info!("Test OK"); |     info!("Test OK"); | ||||||
|     cortex_m::asm::bkpt(); |     cortex_m::asm::bkpt(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user