mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-25 19:39:32 +01:00
Fixed systick monotonic
This commit is contained in:
parent
feca271a4c
commit
1f9eb45dd0
10 changed files with 137 additions and 4 deletions
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rtic-timer"
|
name = "rtic-monotonics"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -9,4 +9,4 @@ edition = "2021"
|
||||||
cortex-m = { version = "0.7.6" }
|
cortex-m = { version = "0.7.6" }
|
||||||
embedded-hal-async = "0.2.0-alpha.0"
|
embedded-hal-async = "0.2.0-alpha.0"
|
||||||
fugit = { version = "0.3.6", features = ["defmt"] }
|
fugit = { version = "0.3.6", features = ["defmt"] }
|
||||||
rtic-timer = { version = "1.0.0", path = "../rtic-timer" }
|
rtic-time = { version = "1.0.0", path = "../rtic-time" }
|
||||||
|
|
|
@ -6,6 +6,6 @@
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(async_fn_in_trait)]
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
pub use rtic_timer::{Monotonic, TimeoutError, TimerQueue};
|
pub use rtic_time::{Monotonic, TimeoutError, TimerQueue};
|
||||||
|
|
||||||
pub mod systick_monotonic;
|
pub mod systick_monotonic;
|
||||||
|
|
|
@ -1 +1,134 @@
|
||||||
//! ...
|
//! ...
|
||||||
|
|
||||||
|
use super::Monotonic;
|
||||||
|
pub use super::{TimeoutError, TimerQueue};
|
||||||
|
use core::{
|
||||||
|
ops::Deref,
|
||||||
|
sync::atomic::{AtomicU32, Ordering},
|
||||||
|
};
|
||||||
|
use cortex_m::peripheral::SYST;
|
||||||
|
use embedded_hal_async::delay::DelayUs;
|
||||||
|
use fugit::ExtU32;
|
||||||
|
|
||||||
|
/// Systick implementing `rtic_monotonic::Monotonic` which runs at a
|
||||||
|
/// settable rate using the `TIMER_HZ` parameter.
|
||||||
|
pub struct Systick<const TIMER_HZ: u32>;
|
||||||
|
|
||||||
|
impl<const TIMER_HZ: u32> Systick<TIMER_HZ> {
|
||||||
|
/// 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.
|
||||||
|
#[must_use]
|
||||||
|
pub fn start(mut systick: cortex_m::peripheral::SYST, sysclk: u32) -> Self {
|
||||||
|
// + 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 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn systick() -> SYST {
|
||||||
|
unsafe { core::mem::transmute::<(), SYST>(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SYSTICK_CNT: AtomicU32 = AtomicU32::new(0);
|
||||||
|
|
||||||
|
impl<const TIMER_HZ: u32> Monotonic for Systick<TIMER_HZ> {
|
||||||
|
type Instant = fugit::TimerInstantU32<TIMER_HZ>;
|
||||||
|
type Duration = fugit::TimerDurationU32<TIMER_HZ>;
|
||||||
|
|
||||||
|
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() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Timer queue wrapper to implement traits on
|
||||||
|
pub struct SystickTimerQueue<const TIMER_HZ: u32>(TimerQueue<Systick<TIMER_HZ>>);
|
||||||
|
|
||||||
|
impl<const TIMER_HZ: u32> SystickTimerQueue<TIMER_HZ> {
|
||||||
|
/// Create a new timer queue.
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self(TimerQueue::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const TIMER_HZ: u32> Deref for SystickTimerQueue<TIMER_HZ> {
|
||||||
|
type Target = TimerQueue<Systick<TIMER_HZ>>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const TIMER_HZ: u32> DelayUs for SystickTimerQueue<TIMER_HZ> {
|
||||||
|
type Error = core::convert::Infallible;
|
||||||
|
|
||||||
|
async fn delay_us(&mut self, us: u32) -> Result<(), Self::Error> {
|
||||||
|
self.delay(us.micros()).await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> {
|
||||||
|
self.delay(ms.millis()).await;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register the Systick interrupt and crate a timer queue with a specific name and speed.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! make_systick_timer_queue {
|
||||||
|
($timer_queue_name:ident, $systick_speed:expr) => {
|
||||||
|
static $timer_queue_name: SystickTimerQueue<$systick_speed> = SystickTimerQueue::new();
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
unsafe extern "C" fn SysTick() {
|
||||||
|
$timer_queue_name.on_monotonic_interrupt();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
0
rtic-timer/.gitignore → rtic-time/.gitignore
vendored
0
rtic-timer/.gitignore → rtic-time/.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rtic-timer"
|
name = "rtic-time"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
Loading…
Reference in a new issue