1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! Real-Time Interrupt-driven Concurrency (RTIC) framework for ARM Cortex-M microcontrollers
//!
//! **HEADS UP** This is an **beta** pre-release; there may be breaking changes in the API and
//! semantics before a proper release is made.
//!
//! **IMPORTANT**: This crate is published as [`cortex-m-rtic`] on crates.io but the name of the
//! library is `rtic`.
//!
//! [`cortex-m-rtic`]: https://crates.io/crates/cortex-m-rtic
//!
//! The user level documentation can be found [here].
//!
//! [here]: https://rtic.rs
//!
//! Don't forget to check the documentation of the `#[app]` attribute (listed under the reexports
//! section), which is the main component of the framework.
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! This crate is guaranteed to compile on stable Rust 1.38 (2018 edition) and up. It *might*
//! compile on older versions but that may change in any new patch release.
//!
//! # Semantic Versioning
//!
//! Like the Rust project, this crate adheres to [SemVer]: breaking changes in the API and semantics
//! require a *semver bump* (a new minor version release), with the exception of breaking changes
//! that fix soundness issues -- those are considered bug fixes and can be landed in a new patch
//! release.
//!
//! [SemVer]: https://semver.org/spec/v2.0.0.html
//!
//! # Cargo features
//!
//! - `heterogeneous`. This opt-in feature enables the *experimental* heterogeneous multi-core
//! support. This feature depends on unstable feature and requires the use of the nightly channel.
//!
//! - `homogeneous`. This opt-in feature enables the *experimental* homogeneous multi-core support.
//!
//! - `cortex-m-7`. This opt-in feature changes the `cortex-m` version from the default 0.6 to the newer 0.7.
//! This is to use the `InterruptNumber` trait instead of the `Nr` trait for interrupt numbers.
//! Enabling this feature **requires disabling the default features**.

#![deny(missing_docs)]
#![deny(rust_2018_compatibility)]
#![deny(rust_2018_idioms)]
#![deny(warnings)]
#![no_std]

use core::ops::Sub;

#[cfg(feature = "cortex-m")]
use cortex_m::interrupt::Nr;

#[cfg(feature = "cortex-m-7")]
extern crate cortex_m_7 as cortex_m;
#[cfg(feature = "cortex-m-7")]
use cortex_m::interrupt::InterruptNumber;

use cortex_m::peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU};
pub use cortex_m_rtic_macros::app;
pub use rtic_core::{Exclusive, Mutex};

#[cfg(armv7m)]
pub mod cyccnt;
#[doc(hidden)]
pub mod export;
#[doc(hidden)]
mod tq;

/// `cortex_m::Peripherals` minus `SYST`
#[allow(non_snake_case)]
pub struct Peripherals {
    /// Cache and branch predictor maintenance operations (not present on Cortex-M0 variants)
    pub CBP: CBP,

    /// CPUID
    pub CPUID: CPUID,

    /// Debug Control Block
    pub DCB: DCB,

    /// Data Watchpoint and Trace unit
    pub DWT: DWT,

    /// Flash Patch and Breakpoint unit (not present on Cortex-M0 variants)
    pub FPB: FPB,

    /// Floating Point Unit (only present on `thumbv7em-none-eabihf`)
    pub FPU: FPU,

    /// Instrumentation Trace Macrocell (not present on Cortex-M0 variants)
    pub ITM: ITM,

    /// Memory Protection Unit
    pub MPU: MPU,

    /// Nested Vector Interrupt Controller
    pub NVIC: NVIC,

    /// System Control Block
    pub SCB: SCB,

    // SysTick: System Timer
    // pub SYST: SYST,
    /// Trace Port Interface Unit (not present on Cortex-M0 variants)
    pub TPIU: TPIU,
}

impl From<cortex_m::Peripherals> for Peripherals {
    fn from(p: cortex_m::Peripherals) -> Self {
        Self {
            CBP: p.CBP,
            CPUID: p.CPUID,
            DCB: p.DCB,
            DWT: p.DWT,
            FPB: p.FPB,
            FPU: p.FPU,
            ITM: p.ITM,
            MPU: p.MPU,
            NVIC: p.NVIC,
            SCB: p.SCB,
            TPIU: p.TPIU,
        }
    }
}

/// A fraction
pub struct Fraction {
    /// The numerator
    pub numerator: u32,

    /// The denominator
    pub denominator: u32,
}

/// A monotonic clock / counter
pub trait Monotonic {
    /// A measurement of this clock, use `CYCCNT` as a reference implementation for `Instant`.
    /// Note that the Instant must be a signed value such as `i32`.
    type Instant: Copy + Ord + Sub;

    /// The ratio between the system timer (SysTick) frequency and this clock frequency, i.e.
    /// `Monotonic clock * Fraction = System clock`
    ///
    /// The ratio must be expressed in *reduced* `Fraction` form to prevent overflows. That is
    /// `2 / 3` instead of `4 / 6`
    fn ratio() -> Fraction;

    /// Returns the current time
    ///
    /// # Correctness
    ///
    /// This function is *allowed* to return nonsensical values if called before `reset` is invoked
    /// by the runtime. Therefore application authors should *not* call this function during the
    /// `#[init]` phase.
    fn now() -> Self::Instant;

    /// Resets the counter to *zero*
    ///
    /// # Safety
    ///
    /// This function will be called *exactly once* by the RTIC runtime after `#[init]` returns and
    /// before tasks can start; this is also the case in multi-core applications. User code must
    /// *never* call this function.
    unsafe fn reset();

    /// A `Self::Instant` that represents a count of *zero*
    fn zero() -> Self::Instant;
}

/// A marker trait that indicates that it is correct to use this type in multi-core context
pub trait MultiCore {}

/// Sets the given `interrupt` as pending
///
/// This is a convenience function around
/// [`NVIC::pend`](../cortex_m/peripheral/struct.NVIC.html#method.pend)
#[cfg(feature = "cortex-m")]
pub fn pend<I>(interrupt: I)
where
    I: Nr,
{
    NVIC::pend(interrupt)
}

/// Sets the given `interrupt` as pending
///
/// This is a convenience function around
/// [`NVIC::pend`](../cortex_m/peripheral/struct.NVIC.html#method.pend)
#[cfg(feature = "cortex-m-7")]
pub fn pend<I>(interrupt: I)
where
    I: InterruptNumber,
{
    NVIC::pend(interrupt)
}