rtic_monotonics/
lib.rs

1//! In-tree implementations of the [`rtic_time::Monotonic`] (reexported) trait for
2//! timers & clocks found on commonly used microcontrollers.
3//!
4//! If you are using a microcontroller where CAS operations are not available natively, you might
5//! have to enable the `critical-section` or `unsafe-assume-single-core` feature of the
6//! [`portable-atomic`](https://docs.rs/portable-atomic/latest/portable_atomic/) dependency
7//! yourself for this dependency to compile.
8//!
9//! To enable the implementations, you must enable a feature for the specific MCU you're targeting.
10//!
11//! # Cortex-M Systick
12//! The `systick` monotonic works on all Arm Cortex-M parts, and requires that the feature `cortex-m-systick` is enabled.
13//!
14//! # RP2040
15//! The RP2040 monotonics require that the `rp2040` feature is enabled.
16//!
17//! # RP2350
18//! The RP2350 monotonics require that the `rp235x` feature is enabled.
19//!
20//! # i.MX RT
21//! The i.MX RT monotonics require that the feature `imxrt_gpt1` or `imxrt_gpt2` is enabled.
22//!
23//! # nRF
24//! nRF monotonics require that one of the available `nrf52*` features is enabled. Monotonic
25//! implementations are available for both high-resolution TIMER and low-resolution RTC peripherals.
26//!
27//! All implementations of timers for the nRF52 family are documented here. Monotonics that
28//! are not available on all parts in this family will have an `Available on crate features X only`
29//! tag, describing what parts _do_ support that monotonic. Monotonics without an
30//! `Available on crate features X only` tag are available on any `nrf52*` feature.
31//!
32//! # ESP32C3 and ESP32C6
33//! Enable either the `esp32c3-systimer` or `esp32c6-systimer` feature, as appropriate.
34//!
35//! # STM32
36//! Enable one of the `stm32*` features, as appropriate. Implementations are available for
37//! a selection of STM32 timers.
38//!
39//! # ATSAMD
40//! Monotonics for the ATSAMD family of parts using the real time clock (RTC) are provided in the
41//! [`atsamd-hal`](https://docs.rs/atsamd-hal/latest/atsamd_hal/rtc/rtic/index.html)
42//! crate with the `rtic` feature enabled.
43//! # Priority of interrupt handlers
44//!
45//! The priority of timer interrupts are based on `RTIC_ASYNC_MAX_LOGICAL_PRIO` generated by RTIC.
46//! It is calculated to be 1 less than the maximum hardware task priority (to not have impact on
47//! hardware tasks), or, if no hardware task is available, is set to the maximum priority in the
48//! system.
49
50// To build these docs correctly:
51// RUSTFLAGS="--cfg docsrs" cargo +nightly doc --features thumbv7-backend,cortex-m-systick,rp2040,nrf52840,imxrt_gpt1,imxrt_gpt2,imxrt-ral/imxrt1011,stm32h725ag,stm32_tim2,stm32_tim3,stm32_tim4,stm32_tim5,stm32_tim15
52
53#![no_std]
54#![deny(missing_docs)]
55#![allow(incomplete_features)]
56#![cfg_attr(docsrs, feature(doc_cfg))]
57
58pub use fugit;
59pub use rtic_time::{
60    self, monotonic::TimerQueueBasedMonotonic, timer_queue::TimerQueueBackend, Monotonic,
61    TimeoutError,
62};
63
64#[cfg(feature = "esp32c3-systimer")]
65pub mod esp32c3;
66
67#[cfg(feature = "esp32c6-systimer")]
68pub mod esp32c6;
69
70#[cfg(feature = "cortex-m-systick")]
71pub mod systick;
72
73#[cfg(feature = "rp2040")]
74pub mod rp2040;
75
76#[cfg(feature = "rp235x")]
77pub mod rp235x;
78
79#[cfg(feature = "imxrt")]
80pub mod imxrt;
81
82#[cfg(any(
83    feature = "nrf52805",
84    feature = "nrf52810",
85    feature = "nrf52811",
86    feature = "nrf52832",
87    feature = "nrf52833",
88    feature = "nrf52840",
89    feature = "nrf5340-app",
90    feature = "nrf5340-net",
91    feature = "nrf9160",
92))]
93pub mod nrf;
94
95// Notice that `stm32` is not a feature, it is a compilation flag set in build.rs.
96#[cfg(stm32)]
97pub mod stm32;
98
99#[allow(dead_code)]
100pub(crate) const fn cortex_logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
101    ((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
102}
103
104#[cfg(any(
105    feature = "rp235x",
106    feature = "rp2040",
107    feature = "nrf52805",
108    feature = "nrf52810",
109    feature = "nrf52811",
110    feature = "nrf52832",
111    feature = "nrf52833",
112    feature = "nrf52840",
113    feature = "nrf5340-app",
114    feature = "nrf5340-net",
115    feature = "nrf9160",
116    feature = "imxrt",
117    stm32,
118))]
119pub(crate) unsafe fn set_monotonic_prio(
120    prio_bits: u8,
121    interrupt: impl cortex_m::interrupt::InterruptNumber,
122) {
123    extern "C" {
124        static RTIC_ASYNC_MAX_LOGICAL_PRIO: u8;
125    }
126
127    let max_prio = RTIC_ASYNC_MAX_LOGICAL_PRIO.max(1).min(1 << prio_bits);
128
129    let hw_prio = crate::cortex_logical2hw(max_prio, prio_bits);
130
131    // We take ownership of the entire IRQ and all settings to it, we only change settings
132    // for the IRQ we control.
133    // This will also compile-error in case the NVIC changes in size.
134    let mut nvic: cortex_m::peripheral::NVIC = core::mem::transmute(());
135
136    nvic.set_priority(interrupt, hw_prio);
137}