From d05b3005414c1c64f3e6d5e323d1274423e8d70a Mon Sep 17 00:00:00 2001 From: Dan Whitman Date: Sun, 22 Dec 2024 18:39:33 -0500 Subject: [PATCH] feat(rtic-v2-rtc-monotonics): Extends the `MIN_COMPARE_TICKS` to address a freezing issue in release builds. --- hal/src/rtc/modes.rs | 9 --------- hal/src/rtc/rtic/backends.rs | 31 +++++++++++++++---------------- hal/src/rtc/rtic/mod.rs | 4 ++-- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/hal/src/rtc/modes.rs b/hal/src/rtc/modes.rs index 296eabfe90b..4f99605bc80 100644 --- a/hal/src/rtc/modes.rs +++ b/hal/src/rtc/modes.rs @@ -77,11 +77,6 @@ macro_rules! create_rtc_interrupt { pub trait RtcMode { /// The type of the COUNT register. type Count: Copy + PartialEq + Eq; - /// The COUNT value representing a half period. - const HALF_PERIOD: Self::Count; - /// The minimum number of ticks that compares need to be ahead of the COUNT - /// in order to trigger. - const MIN_COMPARE_TICKS: Self::Count; /// Sets this mode in the CTRL register. unsafe fn set_mode(rtc: &Rtc); @@ -219,8 +214,6 @@ pub mod mode0 { impl RtcMode for RtcMode0 { type Count = u32; - const HALF_PERIOD: Self::Count = 0x8000_0000; - const MIN_COMPARE_TICKS: Self::Count = 5; #[inline] unsafe fn set_mode(rtc: &Rtc) { @@ -286,8 +279,6 @@ pub mod mode1 { impl RtcMode for RtcMode1 { type Count = u16; - const HALF_PERIOD: Self::Count = 0x8000; - const MIN_COMPARE_TICKS: Self::Count = 5; #[inline] unsafe fn set_mode(rtc: &Rtc) { diff --git a/hal/src/rtc/rtic/backends.rs b/hal/src/rtc/rtic/backends.rs index ca5063d312c..e5eaa54e4cf 100644 --- a/hal/src/rtc/rtic/backends.rs +++ b/hal/src/rtc/rtic/backends.rs @@ -29,7 +29,7 @@ macro_rules! __internal_backend_methods { ) -> bool { let d = a.wrapping_sub(b); - d >= <$mode as RtcModeMonotonic>::HALF_PERIOD + d >= <$mode>::HALF_PERIOD } // Ensure that the COUNT is at least the compare value @@ -38,6 +38,7 @@ macro_rules! __internal_backend_methods { // before `RtcBackend::on_interrupt` is called. if <$mode>::check_interrupt_flag::<$rtic_int>(&rtc) { let compare = <$mode>::get_compare(&rtc, 0); + while less_than_with_wrap(<$mode>::count(&rtc), compare) {} } @@ -129,7 +130,6 @@ macro_rules! __internal_basic_backend { impl TimerQueueBackend for $name { type Ticks = <$mode as RtcMode>::Count; - #[hal_macro_helper] fn now() -> Self::Ticks { <$mode>::count(unsafe { &pac::Rtc::steal() }) } @@ -154,9 +154,9 @@ macro_rules! __internal_basic_backend { // This is not mentioned in the documentation or errata, but is known to be an // issue for other microcontrollers as well (e.g. nRF family). if instant.saturating_sub(Self::now()) - < <$mode as RtcModeMonotonic>::MIN_COMPARE_TICKS + < <$mode>::MIN_COMPARE_TICKS { - instant = instant.wrapping_add(<$mode as RtcModeMonotonic>::MIN_COMPARE_TICKS) + instant = instant.wrapping_add(<$mode>::MIN_COMPARE_TICKS) } unsafe { <$mode>::set_compare(&rtc, 0, instant) }; @@ -215,7 +215,7 @@ macro_rules! __internal_half_period_counting_backend { init_compares = { // Configure the compare registers <$mode>::set_compare(&rtc, 0, 0); - <$mode>::set_compare(&rtc, 1, <$mode as RtcModeMonotonic>::HALF_PERIOD); + <$mode>::set_compare(&rtc, 1, <$mode>::HALF_PERIOD); } statics = { // Make sure period counter is synced with the timer value @@ -236,7 +236,6 @@ macro_rules! __internal_half_period_counting_backend { impl TimerQueueBackend for RtcBackend { type Ticks = u64; - #[hal_macro_helper] fn now() -> Self::Ticks { calculate_now( || RTC_PERIOD_COUNT.load(Ordering::Relaxed), @@ -263,7 +262,7 @@ macro_rules! __internal_half_period_counting_backend { // Ensure that the COUNT has crossed // Due to syncing delay this may not be the case initially - while <$mode>::count(&rtc) < <$mode as RtcModeMonotonic>::HALF_PERIOD {} + while <$mode>::count(&rtc) < <$mode>::HALF_PERIOD {} } if <$mode>::check_interrupt_flag::<$overflow_int>(&rtc) { <$mode>::clear_interrupt_flag::<$overflow_int>(&rtc); @@ -272,7 +271,7 @@ macro_rules! __internal_half_period_counting_backend { // Ensure that the COUNT has wrapped // Due to syncing delay this may not be the case initially - while <$mode>::count(&rtc) > <$mode as RtcModeMonotonic>::HALF_PERIOD {} + while <$mode>::count(&rtc) > <$mode>::HALF_PERIOD {} } } @@ -293,19 +292,19 @@ macro_rules! __internal_half_period_counting_backend { let val = if diff <= MAX { // Now we know `instant` will happen within one `MAX` time duration. - // Evidently the compare interrupt will not trigger if the instant is within - // a couple of ticks, so delay it a bit if it is too - // close. This is not mentioned in the documentation - // or errata, but is known to be an issue for other - // microcontrollers as well (e.g. nRF family). - if diff < <$mode as RtcModeMonotonic>::MIN_COMPARE_TICKS.into() { + // Evidently the compare interrupt will not trigger if the instant is within a + // couple of ticks, so delay it a bit if it is too close. + // This is not mentioned in the documentation or errata, but is known to be an + // issue for other microcontrollers as well (e.g. nRF family). + if diff < <$mode>::MIN_COMPARE_TICKS.into() { instant = instant - .wrapping_add(<$mode as RtcModeMonotonic>::MIN_COMPARE_TICKS.into()) + .wrapping_add(<$mode>::MIN_COMPARE_TICKS.into()); } (instant & MAX) as <$mode as RtcMode>::Count } else { - 0 + // Just wait a full hardware counter period + <$mode>::count(&rtc).wrapping_sub(1) }; unsafe { <$mode>::set_compare(&rtc, 0, val) }; diff --git a/hal/src/rtc/rtic/mod.rs b/hal/src/rtc/rtic/mod.rs index 374b6be786c..4b4d59ca3a3 100644 --- a/hal/src/rtc/rtic/mod.rs +++ b/hal/src/rtc/rtic/mod.rs @@ -219,11 +219,11 @@ trait RtcModeMonotonic: RtcMode { } impl RtcModeMonotonic for RtcMode0 { const HALF_PERIOD: Self::Count = 0x8000_0000; - const MIN_COMPARE_TICKS: Self::Count = 5; + const MIN_COMPARE_TICKS: Self::Count = 8; } impl RtcModeMonotonic for RtcMode1 { const HALF_PERIOD: Self::Count = 0x8000; - const MIN_COMPARE_TICKS: Self::Count = 5; + const MIN_COMPARE_TICKS: Self::Count = 8; } #[hal_macro_helper]