diff --git a/rtic-monotonics/Cargo.toml b/rtic-monotonics/Cargo.toml index 503c22db86..728e171dc4 100644 --- a/rtic-monotonics/Cargo.toml +++ b/rtic-monotonics/Cargo.toml @@ -48,14 +48,14 @@ systick-100hz = [] systick-10khz = [] # Timer peripheral on the RP2040 -rp2040 = ["dep:rp2040-pac"] +rp2040 = ["dep:cortex-m", "dep:rp2040-pac"] # nRF Timers and RTC -nrf52810 = ["dep:nrf52810-pac", "dep:critical-section"] -nrf52811 = ["dep:nrf52811-pac", "dep:critical-section"] -nrf52832 = ["dep:nrf52832-pac", "dep:critical-section"] -nrf52833 = ["dep:nrf52833-pac", "dep:critical-section"] -nrf52840 = ["dep:nrf52840-pac", "dep:critical-section"] -nrf5340-app = ["dep:nrf5340-app-pac", "dep:critical-section"] -nrf5340-net = ["dep:nrf5340-net-pac", "dep:critical-section"] -nrf9160 = ["dep:nrf9160-pac", "dep:critical-section"] +nrf52810 = ["dep:cortex-m", "dep:nrf52810-pac", "dep:critical-section"] +nrf52811 = ["dep:cortex-m", "dep:nrf52811-pac", "dep:critical-section"] +nrf52832 = ["dep:cortex-m", "dep:nrf52832-pac", "dep:critical-section"] +nrf52833 = ["dep:cortex-m", "dep:nrf52833-pac", "dep:critical-section"] +nrf52840 = ["dep:cortex-m", "dep:nrf52840-pac", "dep:critical-section"] +nrf5340-app = ["dep:cortex-m", "dep:nrf5340-app-pac", "dep:critical-section"] +nrf5340-net = ["dep:cortex-m", "dep:nrf5340-net-pac", "dep:critical-section"] +nrf9160 = ["dep:cortex-m", "dep:nrf9160-pac", "dep:critical-section"] diff --git a/rtic-monotonics/src/lib.rs b/rtic-monotonics/src/lib.rs index fab0b2dbd1..04ce4e2451 100644 --- a/rtic-monotonics/src/lib.rs +++ b/rtic-monotonics/src/lib.rs @@ -26,6 +26,42 @@ pub mod rp2040; ))] pub mod nrf; +#[allow(dead_code)] +pub(crate) const fn cortex_logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 { + ((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits) +} + +#[cfg(any( + feature = "rp2040", + feature = "nrf52810", + feature = "nrf52811", + feature = "nrf52832", + feature = "nrf52833", + feature = "nrf52840", + feature = "nrf5340-app", + feature = "nrf5340-net", + feature = "nrf9160", +))] +pub(crate) unsafe fn set_monotonic_prio( + prio_bits: u8, + interrupt: impl cortex_m::interrupt::InterruptNumber, +) { + extern "C" { + static RTIC_ASYNC_MAX_LOGICAL_PRIO: u8; + } + + let max_prio = RTIC_ASYNC_MAX_LOGICAL_PRIO.max(1).min(1 << prio_bits); + + let hw_prio = crate::cortex_logical2hw(max_prio, prio_bits); + + // We take ownership of the entire IRQ and all settings to it, we only change settings + // for the IRQ we control. + // This will also compile-error in case the NVIC changes in size. + let mut nvic: cortex_m::peripheral::NVIC = core::mem::transmute(()); + + nvic.set_priority(interrupt, hw_prio); +} + /// This marker is implemented on an interrupt token to enforce that the right tokens /// are given to the correct monotonic implementation. /// diff --git a/rtic-monotonics/src/nrf/rtc.rs b/rtic-monotonics/src/nrf/rtc.rs index 724c477c87..03610c015b 100644 --- a/rtic-monotonics/src/nrf/rtc.rs +++ b/rtic-monotonics/src/nrf/rtc.rs @@ -5,19 +5,22 @@ //! ``` //! use rtic_monotonics::nrf::rtc::*; //! -//! # async fn usage() { -//! # let rtc = unsafe { core::mem::transmute(()) }; -//! // Generate the required token -//! let token = rtic_monotonics::create_nrf_rtc0_monotonic_token!(); +//! fn init() { +//! # // This is normally provided by the selected PAC +//! # let rtc = unsafe { core::mem::transmute(()) }; +//! // Generate the required token +//! let token = rtic_monotonics::create_nrf_rtc0_monotonic_token!(); //! -//! // Start the monotonic -//! Rtc0::start(rtc, token); -//! -//! loop { -//! // Use the monotonic -//! Rtc0::delay(100.millis()).await; +//! // Start the monotonic +//! Rtc0::start(rtc, token); +//! } +//! +//! async fn usage() { +//! loop { +//! // Use the monotonic +//! Rtc0::delay(100.millis()).await; +//! } //! } -//! # } //! ``` #[cfg(feature = "nrf52810")] @@ -106,7 +109,13 @@ macro_rules! make_rtc { $tq.initialize(Self {}); - unsafe { pac::NVIC::unmask(Interrupt::$rtc) }; + // SAFETY: We take full ownership of the peripheral and interrupt vector, + // plus we are not using any external shared resources so we won't impact + // basepri/source masking based critical sections. + unsafe { + crate::set_monotonic_prio(pac::NVIC_PRIO_BITS, Interrupt::$rtc); + pac::NVIC::unmask(Interrupt::$rtc); + } } /// Used to access the underlying timer queue diff --git a/rtic-monotonics/src/nrf/timer.rs b/rtic-monotonics/src/nrf/timer.rs index ad490cc38e..db5316f237 100644 --- a/rtic-monotonics/src/nrf/timer.rs +++ b/rtic-monotonics/src/nrf/timer.rs @@ -5,19 +5,22 @@ //! ``` //! use rtic_monotonics::nrf::timer::*; //! -//! # async fn usage() { -//! # let timer = unsafe { core::mem::transmute(()) }; -//! // Generate the required token -//! let token = rtic_monotonics::create_nrf_timer0_monotonic_token!(); +//! fn init() { +//! # // This is normally provided by the selected PAC +//! # let timer = unsafe { core::mem::transmute(()) }; +//! // Generate the required token +//! let token = rtic_monotonics::create_nrf_timer0_monotonic_token!(); //! -//! // Start the monotonic -//! Timer0::start(timer, token); -//! -//! loop { -//! // Use the monotonic -//! Timer0::delay(100.millis()).await; +//! // Start the monotonic +//! Timer0::start(timer, token); +//! } +//! +//! async fn usage() { +//! loop { +//! // Use the monotonic +//! Timer0::delay(100.millis()).await; +//! } //! } -//! # } //! ``` use super::super::Monotonic; @@ -135,7 +138,13 @@ macro_rules! make_timer { timer.events_compare[0].write(|w| w); timer.events_compare[1].write(|w| w); - unsafe { pac::NVIC::unmask(Interrupt::$timer) }; + // SAFETY: We take full ownership of the peripheral and interrupt vector, + // plus we are not using any external shared resources so we won't impact + // basepri/source masking based critical sections. + unsafe { + crate::set_monotonic_prio(pac::NVIC_PRIO_BITS, Interrupt::$timer); + pac::NVIC::unmask(Interrupt::$timer); + } } /// Used to access the underlying timer queue diff --git a/rtic-monotonics/src/rp2040.rs b/rtic-monotonics/src/rp2040.rs index 5e880cd898..c656afca74 100644 --- a/rtic-monotonics/src/rp2040.rs +++ b/rtic-monotonics/src/rp2040.rs @@ -5,20 +5,23 @@ //! ``` //! use rtic_monotonics::rp2040::*; //! -//! # async fn usage() { -//! # let timer = unsafe { core::mem::transmute(()) }; -//! # let mut resets = unsafe { core::mem::transmute(()) }; -//! // Generate the required token -//! let token = rtic_monotonics::create_rp2040_monotonic_token!(); +//! fn init() { +//! # // This is normally provided by the selected PAC +//! # let timer = unsafe { core::mem::transmute(()) }; +//! # let mut resets = unsafe { core::mem::transmute(()) }; +//! // Generate the required token +//! let token = rtic_monotonics::create_rp2040_monotonic_token!(); //! -//! // Start the monotonic -//! Timer::start(timer, &mut resets, token); -//! -//! loop { -//! // Use the monotonic -//! Timer::delay(100.millis()).await; +//! // Start the monotonic +//! Timer::start(timer, &mut resets, token); +//! } +//! +//! async fn usage() { +//! loop { +//! // Use the monotonic +//! Timer::delay(100.millis()).await; +//! } //! } -//! # } //! ``` use super::Monotonic; @@ -43,7 +46,10 @@ impl Timer { TIMER_QUEUE.initialize(Self {}); - unsafe { NVIC::unmask(Interrupt::TIMER_IRQ_0) }; + unsafe { + crate::set_monotonic_prio(rp2040_pac::NVIC_PRIO_BITS, Interrupt::TIMER_IRQ_0); + NVIC::unmask(Interrupt::TIMER_IRQ_0); + } } fn timer() -> &'static timer::RegisterBlock { diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs index f1d49daf33..6a28a11774 100644 --- a/rtic-monotonics/src/systick.rs +++ b/rtic-monotonics/src/systick.rs @@ -6,19 +6,22 @@ //! ``` //! use rtic_monotonics::systick::*; //! -//! # async fn usage() { -//! # let systick = unsafe { core::mem::transmute(()) }; -//! // Generate the required token -//! let systick_token = rtic_monotonics::create_systick_token!(); +//! fn init() { +//! # // This is normally provided by the selected PAC +//! # let systick = unsafe { core::mem::transmute(()) }; +//! // Generate the required token +//! let systick_token = rtic_monotonics::create_systick_token!(); //! -//! // Start the monotonic -//! Systick::start(systick, 12_000_000, systick_token); -//! -//! loop { -//! // Use the monotonic -//! Systick::delay(100.millis()).await; +//! // Start the monotonic +//! Systick::start(systick, 12_000_000, systick_token); +//! } +//! +//! async fn usage() { +//! loop { +//! // Use the monotonic +//! Systick::delay(100.millis()).await; +//! } //! } -//! # } //! ``` use super::Monotonic;