mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-27 14:04:56 +01:00
rtic-monotonics: Add interrupt tokens to make sure users bind interrupts
This commit is contained in:
parent
7c7d6558f6
commit
e4d9284e25
6 changed files with 49 additions and 9 deletions
|
@ -9,6 +9,8 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Interrupt tokens for `Systick` and `rp2040` to make sure an interrupt handler exists
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -13,3 +13,13 @@ pub mod systick;
|
||||||
|
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
pub mod rp2040;
|
pub mod rp2040;
|
||||||
|
|
||||||
|
/// This marker is implemented on an interrupt token to enforce that the right tokens
|
||||||
|
/// are given to the correct monotonic implementation.
|
||||||
|
///
|
||||||
|
/// This trait is implemented by this crate and not intended for user implementation.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is only safely implemented by this crate.
|
||||||
|
pub unsafe trait InterruptToken<Periperhal> {}
|
||||||
|
|
|
@ -4,14 +4,18 @@ use super::Monotonic;
|
||||||
pub use super::{TimeoutError, TimerQueue};
|
pub use super::{TimeoutError, TimerQueue};
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
pub use fugit::ExtU64;
|
pub use fugit::ExtU64;
|
||||||
use rp2040_pac::{timer, Interrupt, RESETS, TIMER};
|
use rp2040_pac::{timer, Interrupt, NVIC, RESETS, TIMER};
|
||||||
|
|
||||||
/// Timer implementing `rtic_monotonic::Monotonic` which runs at 1 MHz.
|
/// Timer implementing `rtic_monotonic::Monotonic` which runs at 1 MHz.
|
||||||
pub struct Timer;
|
pub struct Timer;
|
||||||
|
|
||||||
impl Timer {
|
impl Timer {
|
||||||
/// Start a `Monotonic` based on RP2040's Timer.
|
/// Start a `Monotonic` based on RP2040's Timer.
|
||||||
pub fn start(timer: TIMER, resets: &mut RESETS) {
|
pub fn start(
|
||||||
|
timer: TIMER,
|
||||||
|
resets: &mut RESETS,
|
||||||
|
_interrupt_token: impl crate::InterruptToken<Self>,
|
||||||
|
) {
|
||||||
resets.reset.modify(|_, w| w.timer().clear_bit());
|
resets.reset.modify(|_, w| w.timer().clear_bit());
|
||||||
while resets.reset_done.read().timer().bit_is_clear() {}
|
while resets.reset_done.read().timer().bit_is_clear() {}
|
||||||
timer.inte.modify(|_, w| w.alarm_0().set_bit());
|
timer.inte.modify(|_, w| w.alarm_0().set_bit());
|
||||||
|
@ -134,10 +138,21 @@ impl embedded_hal_async::delay::DelayUs for Timer {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! make_rp2040_monotonic_handler {
|
macro_rules! make_rp2040_monotonic_handler {
|
||||||
() => {
|
() => {
|
||||||
|
{
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern "C" fn TIMER_IRQ_0() {
|
unsafe extern "C" fn TIMER_IRQ_0() {
|
||||||
rtic_monotonics::rp2040::Timer::__tq().on_monotonic_interrupt();
|
rtic_monotonics::rp2040::Timer::__tq().on_monotonic_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Rp2040Token;
|
||||||
|
|
||||||
|
unsafe impl rtic_monotonics::InterruptToken<rtic_monotonics::rp2040::Timer>
|
||||||
|
for Rp2040Token
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Rp2040Token
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,11 @@ impl Systick {
|
||||||
/// `sysclk` and `TIMER_HZ`.
|
/// `sysclk` and `TIMER_HZ`.
|
||||||
///
|
///
|
||||||
/// Note: Give the return value to `TimerQueue::initialize()` to initialize the timer queue.
|
/// Note: Give the return value to `TimerQueue::initialize()` to initialize the timer queue.
|
||||||
pub fn start(mut systick: cortex_m::peripheral::SYST, sysclk: u32) {
|
pub fn start(
|
||||||
|
mut systick: cortex_m::peripheral::SYST,
|
||||||
|
sysclk: u32,
|
||||||
|
_interrupt_token: impl crate::InterruptToken<Self>,
|
||||||
|
) {
|
||||||
// + TIMER_HZ / 2 provides round to nearest instead of round to 0.
|
// + TIMER_HZ / 2 provides round to nearest instead of round to 0.
|
||||||
// - 1 as the counter range is inclusive [0, reload]
|
// - 1 as the counter range is inclusive [0, reload]
|
||||||
let reload = (sysclk + TIMER_HZ / 2) / TIMER_HZ - 1;
|
let reload = (sysclk + TIMER_HZ / 2) / TIMER_HZ - 1;
|
||||||
|
@ -154,10 +158,21 @@ impl embedded_hal_async::delay::DelayUs for Systick {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! make_systick_handler {
|
macro_rules! make_systick_handler {
|
||||||
() => {
|
() => {
|
||||||
|
{
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern "C" fn SysTick() {
|
unsafe extern "C" fn SysTick() {
|
||||||
rtic_monotonics::systick::Systick::__tq().on_monotonic_interrupt();
|
rtic_monotonics::systick::Systick::__tq().on_monotonic_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SystickToken;
|
||||||
|
|
||||||
|
unsafe impl rtic_monotonics::InterruptToken<rtic_monotonics::systick::Systick>
|
||||||
|
for SystickToken
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SystickToken
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,6 @@ mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use rtic_monotonics::systick::*;
|
use rtic_monotonics::systick::*;
|
||||||
|
|
||||||
rtic_monotonics::make_systick_handler!();
|
|
||||||
|
|
||||||
#[shared]
|
#[shared]
|
||||||
struct Shared {}
|
struct Shared {}
|
||||||
|
|
||||||
|
@ -26,7 +24,8 @@ mod app {
|
||||||
fn init(cx: init::Context) -> (Shared, Local) {
|
fn init(cx: init::Context) -> (Shared, Local) {
|
||||||
hprintln!("init");
|
hprintln!("init");
|
||||||
|
|
||||||
Systick::start(cx.core.SYST, 12_000_000);
|
let systick_token = rtic_monotonics::make_systick_handler!();
|
||||||
|
Systick::start(cx.core.SYST, 12_000_000, systick_token);
|
||||||
|
|
||||||
foo::spawn().ok();
|
foo::spawn().ok();
|
||||||
bar::spawn().ok();
|
bar::spawn().ok();
|
||||||
|
|
|
@ -17,8 +17,6 @@ mod app {
|
||||||
use futures::{future::FutureExt, select_biased};
|
use futures::{future::FutureExt, select_biased};
|
||||||
use rtic_monotonics::Monotonic;
|
use rtic_monotonics::Monotonic;
|
||||||
|
|
||||||
rtic_monotonics::make_systick_handler!();
|
|
||||||
|
|
||||||
#[shared]
|
#[shared]
|
||||||
struct Shared {}
|
struct Shared {}
|
||||||
|
|
||||||
|
@ -29,7 +27,8 @@ mod app {
|
||||||
fn init(cx: init::Context) -> (Shared, Local) {
|
fn init(cx: init::Context) -> (Shared, Local) {
|
||||||
hprintln!("init");
|
hprintln!("init");
|
||||||
|
|
||||||
Systick::start(cx.core.SYST, 12_000_000);
|
let systick_token = rtic_monotonics::make_systick_handler!();
|
||||||
|
Systick::start(cx.core.SYST, 12_000_000, systick_token);
|
||||||
|
|
||||||
foo::spawn().ok();
|
foo::spawn().ok();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue