From 8963e0e27ae57f7a8c3a666fe9e5a993cdd09275 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Fri, 10 Feb 2023 07:52:50 +0100 Subject: RP2040 monotonic, rename systick monotonic to not have double name --- rtic-monotonics/src/systick.rs | 163 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 rtic-monotonics/src/systick.rs (limited to 'rtic-monotonics/src/systick.rs') diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs new file mode 100644 index 0000000..885da92 --- /dev/null +++ b/rtic-monotonics/src/systick.rs @@ -0,0 +1,163 @@ +//! ... + +use super::Monotonic; +pub use super::{TimeoutError, TimerQueue}; +use atomic_polyfill::{AtomicU32, Ordering}; +use core::future::Future; +use cortex_m::peripheral::SYST; +use embedded_hal_async::delay::DelayUs; +pub use fugit::ExtU32; + +// Features should be additive, here systick_100hz gets picked if both +// `systick_100hz` and `systick_10khz` are enabled. + +cfg_if::cfg_if! { + if #[cfg(feature = "systick_100hz")] + { + const TIMER_HZ: u32 = 100; + } else if #[cfg(feature = "systick_10khz")] + { + const TIMER_HZ: u32 = 10_000; + } else { + // Default case is 1 kHz + const TIMER_HZ: u32 = 1_000; + } +} + +/// Systick implementing `rtic_monotonic::Monotonic` which runs at 1 kHz, 100Hz or 10 kHz. +pub struct Systick; + +impl Systick { + /// Start a `Monotonic` based on SysTick. + /// + /// The `sysclk` parameter is the speed at which SysTick runs at. This value should come from + /// the clock generation function of the used HAL. + /// + /// Notice that the actual rate of the timer is a best approximation based on the given + /// `sysclk` and `TIMER_HZ`. + /// + /// Note: Give the return value to `TimerQueue::initialize()` to initialize the timer queue. + pub fn start(mut systick: cortex_m::peripheral::SYST, sysclk: u32) { + // + TIMER_HZ / 2 provides round to nearest instead of round to 0. + // - 1 as the counter range is inclusive [0, reload] + let reload = (sysclk + TIMER_HZ / 2) / TIMER_HZ - 1; + + assert!(reload <= 0x00ff_ffff); + assert!(reload > 0); + + systick.disable_counter(); + systick.set_clock_source(cortex_m::peripheral::syst::SystClkSource::Core); + systick.set_reload(reload); + systick.enable_interrupt(); + systick.enable_counter(); + + SYSTICK_TIMER_QUEUE.initialize(Systick {}); + } + + fn systick() -> SYST { + unsafe { core::mem::transmute::<(), SYST>(()) } + } +} + +static SYSTICK_CNT: AtomicU32 = AtomicU32::new(0); +static SYSTICK_TIMER_QUEUE: TimerQueue = TimerQueue::new(); + +// Forward timerqueue interface +impl Systick { + /// Used to access the underlying timer queue + #[doc(hidden)] + pub fn __tq() -> &'static TimerQueue { + &SYSTICK_TIMER_QUEUE + } + + /// Timeout at a specific time. + pub async fn timeout_at( + instant: ::Instant, + future: F, + ) -> Result { + SYSTICK_TIMER_QUEUE.timeout_at(instant, future).await + } + + /// Timeout after a specific duration. + #[inline] + pub async fn timeout_after( + duration: ::Duration, + future: F, + ) -> Result { + SYSTICK_TIMER_QUEUE.timeout_after(duration, future).await + } + + /// Delay for some duration of time. + #[inline] + pub async fn delay(duration: ::Duration) { + SYSTICK_TIMER_QUEUE.delay(duration).await; + } + + /// Delay to some specific time instant. + pub async fn delay_until(instant: ::Instant) { + SYSTICK_TIMER_QUEUE.delay_until(instant).await; + } +} + +impl Monotonic for Systick { + type Instant = fugit::TimerInstantU32; + type Duration = fugit::TimerDurationU32; + + const ZERO: Self::Instant = Self::Instant::from_ticks(0); + + fn now() -> Self::Instant { + if Self::systick().has_wrapped() { + SYSTICK_CNT.fetch_add(1, Ordering::AcqRel); + } + + Self::Instant::from_ticks(SYSTICK_CNT.load(Ordering::Relaxed)) + } + + fn set_compare(_: Self::Instant) { + // No need to do something here, we get interrupts anyway. + } + + fn clear_compare_flag() { + // NOOP with SysTick interrupt + } + + fn pend_interrupt() { + cortex_m::peripheral::SCB::set_pendst(); + } + + fn on_interrupt() { + if Self::systick().has_wrapped() { + SYSTICK_CNT.fetch_add(1, Ordering::AcqRel); + } + } + + fn enable_timer() {} + + fn disable_timer() {} +} + +impl DelayUs for Systick { + type Error = core::convert::Infallible; + + async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> { + SYSTICK_TIMER_QUEUE.delay(us.micros()).await; + Ok(()) + } + + async fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> { + SYSTICK_TIMER_QUEUE.delay(ms.millis()).await; + Ok(()) + } +} + +/// Register the Systick interrupt for the monotonic. +#[macro_export] +macro_rules! make_systick_handler { + () => { + #[no_mangle] + #[allow(non_snake_case)] + unsafe extern "C" fn SysTick() { + Systick::__tq().on_monotonic_interrupt(); + } + }; +} -- cgit v1.2.3 From 002d0b0d1685473f0f81cd17346d119fc671ad9c Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Wed, 15 Feb 2023 23:21:52 +0100 Subject: Make embedded-hal-async dependency optional for better compatibility with HALs Some hals implement traits for embedded-hal version `=1.0.0.alpha.`, which is explicitly incompatible with the version `=1.0.0.alpha.9` which embedded-hal-async depends on. Making the dependency optional allows downstream projects to include rtic-monotonic without requiring that all of their other libraries also implement that specific version of embedded-hal 1.0 --- rtic-monotonics/src/systick.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'rtic-monotonics/src/systick.rs') diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs index 885da92..2711022 100644 --- a/rtic-monotonics/src/systick.rs +++ b/rtic-monotonics/src/systick.rs @@ -5,7 +5,6 @@ pub use super::{TimeoutError, TimerQueue}; use atomic_polyfill::{AtomicU32, Ordering}; use core::future::Future; use cortex_m::peripheral::SYST; -use embedded_hal_async::delay::DelayUs; pub use fugit::ExtU32; // Features should be additive, here systick_100hz gets picked if both @@ -136,7 +135,8 @@ impl Monotonic for Systick { fn disable_timer() {} } -impl DelayUs for Systick { +#[cfg(feature = "embedded-hal-async")] +impl embedded_hal_async::delay::DelayUs for Systick { type Error = core::convert::Infallible; async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> { -- cgit v1.2.3 From b9e0f36aff96ec4e39cf4f728777cbc808df2c78 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 19 Feb 2023 14:30:49 +0100 Subject: Add feature flags --- rtic-monotonics/src/systick.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rtic-monotonics/src/systick.rs') diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs index 2711022..62d4e0c 100644 --- a/rtic-monotonics/src/systick.rs +++ b/rtic-monotonics/src/systick.rs @@ -157,7 +157,7 @@ macro_rules! make_systick_handler { #[no_mangle] #[allow(non_snake_case)] unsafe extern "C" fn SysTick() { - Systick::__tq().on_monotonic_interrupt(); + rtic_monotonics::systick::Systick::__tq().on_monotonic_interrupt(); } }; } -- cgit v1.2.3 From 44af1366056a06247b3ee0f153d5274cb4658c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Sat, 4 Mar 2023 02:26:34 +0100 Subject: CFG: Align all crates to use hyphen --- rtic-monotonics/src/systick.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'rtic-monotonics/src/systick.rs') diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs index 62d4e0c..691d7c7 100644 --- a/rtic-monotonics/src/systick.rs +++ b/rtic-monotonics/src/systick.rs @@ -7,14 +7,14 @@ use core::future::Future; use cortex_m::peripheral::SYST; pub use fugit::ExtU32; -// Features should be additive, here systick_100hz gets picked if both -// `systick_100hz` and `systick_10khz` are enabled. +// Features should be additive, here systick-100hz gets picked if both +// `systick-100hz` and `systick-10khz` are enabled. cfg_if::cfg_if! { - if #[cfg(feature = "systick_100hz")] + if #[cfg(feature = "systick-100hz")] { const TIMER_HZ: u32 = 100; - } else if #[cfg(feature = "systick_10khz")] + } else if #[cfg(feature = "systick-10khz")] { const TIMER_HZ: u32 = 10_000; } else { -- cgit v1.2.3