mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-25 21:19:35 +01:00
update examples
This commit is contained in:
parent
e85d6e53c8
commit
2d80f3631b
18 changed files with 206 additions and 87 deletions
6
.gdbinit
Normal file
6
.gdbinit
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
monitor arm semihosting enable
|
||||||
|
|
||||||
|
load
|
||||||
|
step
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
*.org
|
*.org
|
||||||
|
.gdb_history
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
target/
|
target/
|
||||||
|
|
|
@ -4,7 +4,7 @@ authors = [
|
||||||
"Per Lindgren <per.lindgren@ltu.se>",
|
"Per Lindgren <per.lindgren@ltu.se>",
|
||||||
]
|
]
|
||||||
categories = ["concurrency", "embedded", "no-std"]
|
categories = ["concurrency", "embedded", "no-std"]
|
||||||
description = "Real Time For the Masses (RTFM), a framework for building concurrent applications, for ARM Cortex-M microcontrollers"
|
description = "Real Time For the Masses (RTFM) framework for ARM Cortex-M microcontrollers"
|
||||||
documentation = "https://docs.rs/cortex-m-rtfm"
|
documentation = "https://docs.rs/cortex-m-rtfm"
|
||||||
keywords = ["arm", "cortex-m"]
|
keywords = ["arm", "cortex-m"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -14,8 +14,8 @@ version = "0.2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m = "0.3.1"
|
cortex-m = "0.3.1"
|
||||||
|
rtfm-core = "0.1.0"
|
||||||
static-ref = "0.2.1"
|
static-ref = "0.2.1"
|
||||||
rtfm-core = { git = "https://github.com/japaric/rtfm-core" }
|
|
||||||
|
|
||||||
[dependencies.cortex-m-rtfm-macros]
|
[dependencies.cortex-m-rtfm-macros]
|
||||||
path = "macros"
|
path = "macros"
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
# `cortex-m-rtfm`
|
# `cortex-m-rtfm`
|
||||||
|
|
||||||
> Real Time For the Masses (RTFM), a framework for building concurrent
|
> Real Time For the Masses (RTFM) framework for ARM Cortex-M microcontrollers
|
||||||
> applications, for ARM Cortex-M MCUs
|
|
||||||
|
|
||||||
# [Manual](https://docs.rs/cortex-m-rtfm)
|
# [Documentation](https://docs.rs/cortex-m-rtfm)
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! A showcase of the `app!` macro syntax
|
//! A showcase of the `app!` macro syntax
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
//! If you run this program you'll hit the breakpoints as indicated by the
|
//! If you run this program you'll hit the breakpoints as indicated by the
|
||||||
//! letters in the comments: A, then B, then C, etc.
|
//! letters in the comments: A, then B, then C, etc.
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -59,13 +58,14 @@ fn idle() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
#[allow(non_snake_case)]
|
||||||
|
fn exti0(
|
||||||
|
t: &mut Threshold,
|
||||||
|
EXTI0::Resources { mut LOW, mut HIGH }: EXTI0::Resources,
|
||||||
|
) {
|
||||||
// Because this task has a priority of 1 the preemption threshold `t` also
|
// Because this task has a priority of 1 the preemption threshold `t` also
|
||||||
// starts at 1
|
// starts at 1
|
||||||
|
|
||||||
let mut low = r.LOW;
|
|
||||||
let mut high = r.HIGH;
|
|
||||||
|
|
||||||
// B
|
// B
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
|
rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
|
||||||
|
|
||||||
// A claim creates a critical section
|
// A claim creates a critical section
|
||||||
low.claim_mut(t, |_low, t| {
|
LOW.claim_mut(t, |_low, t| {
|
||||||
// This claim increases the preemption threshold to 2
|
// This claim increases the preemption threshold to 2
|
||||||
//
|
//
|
||||||
// 2 is just high enough to not race with task `exti1` for access to the
|
// 2 is just high enough to not race with task `exti1` for access to the
|
||||||
|
@ -94,7 +94,7 @@ fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
|
|
||||||
// Claims can be nested
|
// Claims can be nested
|
||||||
high.claim_mut(t, |_high, _| {
|
HIGH.claim_mut(t, |_high, _| {
|
||||||
// This claim increases the preemption threshold to 3
|
// This claim increases the preemption threshold to 3
|
||||||
|
|
||||||
// Now `exti2` can't preempt this task
|
// Now `exti2` can't preempt this task
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! An application with one task
|
//! An application with one task
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -34,17 +33,6 @@ app! {
|
||||||
// Path to the task handler
|
// Path to the task handler
|
||||||
path: sys_tick,
|
path: sys_tick,
|
||||||
|
|
||||||
// This is the priority of the task.
|
|
||||||
//
|
|
||||||
// 1 is the lowest priority a task can have, and the maximum
|
|
||||||
// priority is determined by the number of priority bits the device
|
|
||||||
// has. `stm32f103xx` has 4 priority bits so 16 is the maximum valid
|
|
||||||
// value.
|
|
||||||
//
|
|
||||||
// You can omit this field. If you do the priority is assumed to be
|
|
||||||
// 1.
|
|
||||||
priority: 1,
|
|
||||||
|
|
||||||
// These are the resources this task has access to.
|
// These are the resources this task has access to.
|
||||||
//
|
//
|
||||||
// A resource can be a peripheral like `GPIOC` or a static variable
|
// A resource can be a peripheral like `GPIOC` or a static variable
|
||||||
|
@ -54,7 +42,10 @@ app! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(p: init::Peripherals, _r: init::Resources) {
|
fn init(p: init::Peripherals, r: init::Resources) {
|
||||||
|
// `init` can modify all the `resources` declared in `app!`
|
||||||
|
r.ON;
|
||||||
|
|
||||||
// power on GPIOC
|
// power on GPIOC
|
||||||
p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
||||||
|
|
||||||
|
@ -81,7 +72,7 @@ fn idle() -> ! {
|
||||||
//
|
//
|
||||||
// `_t` is the preemption threshold token. We won't use it in this program.
|
// `_t` is the preemption threshold token. We won't use it in this program.
|
||||||
//
|
//
|
||||||
// `r` is the set of resources this task has access to. `TIMER0_A1::Resources`
|
// `r` is the set of resources this task has access to. `SYS_TICK::Resources`
|
||||||
// has one field per resource declared in `app!`.
|
// has one field per resource declared in `app!`.
|
||||||
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
// toggle state
|
// toggle state
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! Two tasks running at *different* priorities with access to the same resource
|
//! Two tasks running at *different* priorities with access to the same resource
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -58,8 +57,11 @@ fn tim2(t: &mut Threshold, mut r: TIM2::Resources) {
|
||||||
// As this task runs at lower priority it needs a critical section to
|
// As this task runs at lower priority it needs a critical section to
|
||||||
// prevent `sys_tick` from preempting it while it modifies this resource
|
// prevent `sys_tick` from preempting it while it modifies this resource
|
||||||
// data. The critical section is required to prevent data races which can
|
// data. The critical section is required to prevent data races which can
|
||||||
// lead to undefined behavior
|
// lead to undefined behavior.
|
||||||
r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
r.COUNTER.claim_mut(t, |counter, _t| {
|
||||||
|
// `claim_mut` creates a critical section
|
||||||
|
**counter += 1;
|
||||||
|
});
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! Two tasks running at the *same* priority with access to the same resource
|
//! Two tasks running at the *same* priority with access to the same resource
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -31,8 +29,6 @@ app! {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// When data resources are declared in the top `resources` field, `init` will
|
|
||||||
// have full access to them
|
|
||||||
fn init(_p: init::Peripherals, _r: init::Resources) {
|
fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,8 @@ version = "0.1.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
error-chain = "0.10.0"
|
error-chain = "0.10.0"
|
||||||
quote = "0.3.15"
|
quote = "0.3.15"
|
||||||
|
rtfm-syntax = "0.1.0"
|
||||||
syn = "0.11.11"
|
syn = "0.11.11"
|
||||||
|
|
||||||
[dependencies.rtfm-syntax]
|
|
||||||
git = "https://github.com/japaric/rtfm-syntax"
|
|
||||||
optional = false
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use syn::{Ident, Path};
|
use syn::{Ident, Path};
|
||||||
use syntax::check::{self, Idle, Init};
|
use syntax::check::{self, Idle, Init};
|
||||||
use syntax::{self, Idents, Statics};
|
use syntax::{self, Resources, Statics};
|
||||||
|
|
||||||
use syntax::error::*;
|
use syntax::error::*;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ pub struct Task {
|
||||||
pub kind: Kind,
|
pub kind: Kind,
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
pub priority: u8,
|
pub priority: u8,
|
||||||
pub resources: Idents,
|
pub resources: Resources,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app(app: check::App) -> Result<App> {
|
pub fn app(app: check::App) -> Result<App> {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//! Procedural macros for the RTFM framework
|
//! Procedural macros for the RTFM framework
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![recursion_limit = "128"]
|
#![recursion_limit = "128"]
|
||||||
|
@ -14,7 +13,6 @@ extern crate syn;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syntax::App;
|
use syntax::App;
|
||||||
|
|
||||||
use syntax::error::*;
|
use syntax::error::*;
|
||||||
|
|
||||||
mod analyze;
|
mod analyze;
|
||||||
|
@ -23,6 +21,148 @@ mod trans;
|
||||||
|
|
||||||
/// The `app!` macro, a macro used to specify the tasks and resources of a
|
/// The `app!` macro, a macro used to specify the tasks and resources of a
|
||||||
/// RTFM application.
|
/// RTFM application.
|
||||||
|
///
|
||||||
|
/// The contents of this macro uses a `key: value` syntax. All the possible keys
|
||||||
|
/// are shown below:
|
||||||
|
///
|
||||||
|
/// ``` text
|
||||||
|
/// app! {
|
||||||
|
/// device: ..,
|
||||||
|
///
|
||||||
|
/// resources: { .. },
|
||||||
|
///
|
||||||
|
/// init: { .. },
|
||||||
|
///
|
||||||
|
/// idle: { .. },
|
||||||
|
///
|
||||||
|
/// tasks: { .. },
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # `device`
|
||||||
|
///
|
||||||
|
/// The value of this key is a Rust path, like `foo::bar::baz`, that must point to
|
||||||
|
/// a *device crate*, a crate generated using `svd2rust`.
|
||||||
|
///
|
||||||
|
/// # `resources`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a list of `static` variables. These
|
||||||
|
/// variables are the data that can be safely accessed, modified and shared by
|
||||||
|
/// tasks.
|
||||||
|
///
|
||||||
|
/// ``` text
|
||||||
|
/// resources: {
|
||||||
|
/// static A: bool = false;
|
||||||
|
/// static B: i32 = 0;
|
||||||
|
/// static C: [u8; 16] = [0; 16];
|
||||||
|
/// static D: Thing = Thing::new(..);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If this key is omitted its value defaults to an empty list.
|
||||||
|
///
|
||||||
|
/// # `init`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a set of key values. All the possible
|
||||||
|
/// keys are shown below:
|
||||||
|
///
|
||||||
|
/// ``` text
|
||||||
|
/// init: {
|
||||||
|
/// path: ..,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## `init.path`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that
|
||||||
|
/// points to the initialization function.
|
||||||
|
///
|
||||||
|
/// If the key is omitted its value defaults to `init`.
|
||||||
|
///
|
||||||
|
/// # `idle`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a set of key values. All the possible
|
||||||
|
/// keys are shown below:
|
||||||
|
///
|
||||||
|
/// ``` text
|
||||||
|
/// idle: {
|
||||||
|
/// path: ..,
|
||||||
|
/// resources: [..],
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## `idle.path`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a Rust path, like `foo::bar::baz`, that
|
||||||
|
/// points to the idle loop function.
|
||||||
|
///
|
||||||
|
/// If the key is omitted its value defaults to `idle`.
|
||||||
|
///
|
||||||
|
/// ## `idle.resources`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a list of resources the `idle` loop has
|
||||||
|
/// access to. The resources in this list can refer to the resources listed in
|
||||||
|
/// the top `resources` key. If the name doesn't match one of the resources
|
||||||
|
/// listed in the top `resources` key the resource is assumed to be a
|
||||||
|
/// peripheral.
|
||||||
|
///
|
||||||
|
/// If omitted its value defaults to an empty list.
|
||||||
|
///
|
||||||
|
/// # `tasks`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a list of tasks. Each task itself is a
|
||||||
|
/// set of key value pair. The full syntax is shown below:
|
||||||
|
///
|
||||||
|
/// ``` text
|
||||||
|
/// tasks: {
|
||||||
|
/// $TASK: {
|
||||||
|
/// enabled: ..,
|
||||||
|
/// path: ..,
|
||||||
|
/// priority: ..,
|
||||||
|
/// resources: [..],
|
||||||
|
/// },
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If this key is omitted its value is assumed to be an empty list.
|
||||||
|
///
|
||||||
|
/// ## `tasks.$TASK`
|
||||||
|
///
|
||||||
|
/// The key must be either a Cortex-M exception or a device specific interrupt.
|
||||||
|
/// `PENDSV`, `SVCALL`, `SYS_TICK` are considered as exceptions. All other names
|
||||||
|
/// are assumed to be interrupts.
|
||||||
|
///
|
||||||
|
/// ## `tasks.$TASK.enabled`
|
||||||
|
///
|
||||||
|
/// This key is optional for interrupts and forbidden for exceptions. Its value
|
||||||
|
/// must be a boolean and indicates whether the interrupt will be enabled
|
||||||
|
/// (`true`) or disabled (`false`) after `init` ends and before `idle` starts.
|
||||||
|
///
|
||||||
|
/// If this key is omitted its value defaults to `true`.
|
||||||
|
///
|
||||||
|
/// ## `tasks.$TASK.path`
|
||||||
|
///
|
||||||
|
/// The value of this key is a Rust path, like `foo::bar::baz`, that points to
|
||||||
|
/// the handler of this task.
|
||||||
|
///
|
||||||
|
/// ## `tasks.$TASK.priority`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is an integer with type `u8` that specifies
|
||||||
|
/// the priority of this task. The minimum valid priority is 1. The maximum
|
||||||
|
/// valid priority depends on the number of the NVIC priority bits the device
|
||||||
|
/// has; if the device has 4 priority bits the maximum allowed value would be
|
||||||
|
/// 16.
|
||||||
|
///
|
||||||
|
/// If this key is omitted its value defaults to `1`.
|
||||||
|
///
|
||||||
|
/// ## `tasks.$TASK.resources`
|
||||||
|
///
|
||||||
|
/// This key is optional. Its value is a list of resources this task has access
|
||||||
|
/// to. The resources in this list can refer to the resources listed in the top
|
||||||
|
/// `resources` key. If the name doesn't match one of the resources listed in
|
||||||
|
/// the top `resources` key the resource is assumed to be a peripheral.
|
||||||
|
///
|
||||||
|
/// If omitted its value defaults to an empty list.
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn app(ts: TokenStream) -> TokenStream {
|
pub fn app(ts: TokenStream) -> TokenStream {
|
||||||
match run(ts) {
|
match run(ts) {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
|
@ -36,17 +35,6 @@
|
||||||
//! // Path to the task handler
|
//! // Path to the task handler
|
||||||
//! path: sys_tick,
|
//! path: sys_tick,
|
||||||
//!
|
//!
|
||||||
//! // This is the priority of the task.
|
|
||||||
//! //
|
|
||||||
//! // 1 is the lowest priority a task can have, and the maximum
|
|
||||||
//! // priority is determined by the number of priority bits the device
|
|
||||||
//! // has. `stm32f103xx` has 4 priority bits so 16 is the maximum valid
|
|
||||||
//! // value.
|
|
||||||
//! //
|
|
||||||
//! // You can omit this field. If you do the priority is assumed to be
|
|
||||||
//! // 1.
|
|
||||||
//! priority: 1,
|
|
||||||
//!
|
|
||||||
//! // These are the resources this task has access to.
|
//! // These are the resources this task has access to.
|
||||||
//! //
|
//! //
|
||||||
//! // A resource can be a peripheral like `GPIOC` or a static variable
|
//! // A resource can be a peripheral like `GPIOC` or a static variable
|
||||||
|
@ -56,7 +44,10 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn init(p: init::Peripherals, _r: init::Resources) {
|
//! fn init(p: init::Peripherals, r: init::Resources) {
|
||||||
|
//! // `init` can modify all the `resources` declared in `app!`
|
||||||
|
//! r.ON;
|
||||||
|
//!
|
||||||
//! // power on GPIOC
|
//! // power on GPIOC
|
||||||
//! p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
//! p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
||||||
//!
|
//!
|
||||||
|
@ -83,7 +74,7 @@
|
||||||
//! //
|
//! //
|
||||||
//! // `_t` is the preemption threshold token. We won't use it in this program.
|
//! // `_t` is the preemption threshold token. We won't use it in this program.
|
||||||
//! //
|
//! //
|
||||||
//! // `r` is the set of resources this task has access to. `TIMER0_A1::Resources`
|
//! // `r` is the set of resources this task has access to. `SYS_TICK::Resources`
|
||||||
//! // has one field per resource declared in `app!`.
|
//! // has one field per resource declared in `app!`.
|
||||||
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
//! // toggle state
|
//! // toggle state
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
//! Two tasks running at the *same* priority with access to the same resource
|
//! Two tasks running at the *same* priority with access to the same resource
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
|
@ -33,8 +31,6 @@
|
||||||
//! },
|
//! },
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // When data resources are declared in the top `resources` field, `init` will
|
|
||||||
//! // have full access to them
|
|
||||||
//! fn init(_p: init::Peripherals, _r: init::Resources) {
|
//! fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||||
//! // ..
|
//! // ..
|
||||||
//! }
|
//! }
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
|
@ -60,8 +59,11 @@
|
||||||
//! // As this task runs at lower priority it needs a critical section to
|
//! // As this task runs at lower priority it needs a critical section to
|
||||||
//! // prevent `sys_tick` from preempting it while it modifies this resource
|
//! // prevent `sys_tick` from preempting it while it modifies this resource
|
||||||
//! // data. The critical section is required to prevent data races which can
|
//! // data. The critical section is required to prevent data races which can
|
||||||
//! // lead to undefined behavior
|
//! // lead to undefined behavior.
|
||||||
//! r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
//! r.COUNTER.claim_mut(t, |counter, _t| {
|
||||||
|
//! // `claim_mut` creates a critical section
|
||||||
|
//! **counter += 1;
|
||||||
|
//! });
|
||||||
//!
|
//!
|
||||||
//! // ..
|
//! // ..
|
||||||
//! }
|
//! }
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
|
@ -61,13 +60,14 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
//! #[allow(non_snake_case)]
|
||||||
|
//! fn exti0(
|
||||||
|
//! t: &mut Threshold,
|
||||||
|
//! EXTI0::Resources { mut LOW, mut HIGH }: EXTI0::Resources,
|
||||||
|
//! ) {
|
||||||
//! // Because this task has a priority of 1 the preemption threshold `t` also
|
//! // Because this task has a priority of 1 the preemption threshold `t` also
|
||||||
//! // starts at 1
|
//! // starts at 1
|
||||||
//!
|
//!
|
||||||
//! let mut low = r.LOW;
|
|
||||||
//! let mut high = r.HIGH;
|
|
||||||
//!
|
|
||||||
//! // B
|
//! // B
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//!
|
//!
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
//! rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
|
//! rtfm::set_pending(Interrupt::EXTI1); // ~> exti1
|
||||||
//!
|
//!
|
||||||
//! // A claim creates a critical section
|
//! // A claim creates a critical section
|
||||||
//! low.claim_mut(t, |_low, t| {
|
//! LOW.claim_mut(t, |_low, t| {
|
||||||
//! // This claim increases the preemption threshold to 2
|
//! // This claim increases the preemption threshold to 2
|
||||||
//! //
|
//! //
|
||||||
//! // 2 is just high enough to not race with task `exti1` for access to the
|
//! // 2 is just high enough to not race with task `exti1` for access to the
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//!
|
//!
|
||||||
//! // Claims can be nested
|
//! // Claims can be nested
|
||||||
//! high.claim_mut(t, |_high, _| {
|
//! HIGH.claim_mut(t, |_high, _| {
|
||||||
//! // This claim increases the preemption threshold to 3
|
//! // This claim increases the preemption threshold to 3
|
||||||
//!
|
//!
|
||||||
//! // Now `exti2` can't preempt this task
|
//! // Now `exti2` can't preempt this task
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -1,5 +1,4 @@
|
||||||
//! Real Time For the Masses (RTFM), a framework for building concurrent
|
//! Real Time For the Masses (RTFM) framework for ARM Cortex-M microcontrollers
|
||||||
//! applications, for ARM Cortex-M microcontrollers
|
|
||||||
//!
|
//!
|
||||||
//! This crate is based on [the RTFM framework] created by the Embedded Systems
|
//! This crate is based on [the RTFM framework] created by the Embedded Systems
|
||||||
//! group at [Luleå University of Technology][ltu], led by Prof. Per Lindgren,
|
//! group at [Luleå University of Technology][ltu], led by Prof. Per Lindgren,
|
||||||
|
@ -37,24 +36,24 @@
|
||||||
//!
|
//!
|
||||||
//! # Dependencies
|
//! # Dependencies
|
||||||
//!
|
//!
|
||||||
//! - A device crate generated using [`svd2rust`] v0.11.x. The input SVD file
|
//! The application crate must depend on a device crate generated using
|
||||||
//! *must* contain [`<cpu>`] information.
|
//! [`svd2rust`] v0.11.x and the "rt" feature of that crate must be enabled. The
|
||||||
//! - A `start` lang time: Vanilla `main` must be supported in binary crates.
|
//! SVD file used to generate the device crate *must* contain [`<cpu>`]
|
||||||
//! You can use the [`cortex-m-rt`] crate to fulfill the requirement
|
//! information.
|
||||||
//!
|
//!
|
||||||
//! [`svd2rust`]: https://docs.rs/svd2rust/0..0/svd2rust/
|
//! [`svd2rust`]: https://docs.rs/svd2rust/0..0/svd2rust/
|
||||||
//! [`<cpu>`]: https://www.keil.com/pack/doc/CMSIS/SVD/html/elem_cpu.html
|
//! [`<cpu>`]: https://www.keil.com/pack/doc/CMSIS/SVD/html/elem_cpu.html
|
||||||
//! [`cortex-m-rt`]: https://docs.rs/cortex-m-rt/0.3.0/cortex_m_rt/
|
//!
|
||||||
|
//! # More documentation
|
||||||
|
//!
|
||||||
|
//! The `app!` macro is documented [here](../cortex_m_rtfm_macros/fn.app.html).
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! In increasing grade of complexity, see the [examples](./examples/index.html)
|
//! In increasing grade of complexity. See the [examples](./examples/index.html)
|
||||||
//! module.
|
//! module.
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![feature(asm)]
|
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(optin_builtin_traits)]
|
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -74,7 +73,9 @@ use cortex_m::register::basepri;
|
||||||
|
|
||||||
pub mod examples;
|
pub mod examples;
|
||||||
|
|
||||||
/// Executes the closure `f` in an interrupt free context
|
/// Executes the closure `f` in a preemption free context
|
||||||
|
///
|
||||||
|
/// During the execution of the closure no task can preempt the current task.
|
||||||
pub fn atomic<R, F>(t: &mut Threshold, f: F) -> R
|
pub fn atomic<R, F>(t: &mut Threshold, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Threshold) -> R,
|
F: FnOnce(&mut Threshold) -> R,
|
||||||
|
@ -127,11 +128,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets an interrupt as pending
|
/// Sets an interrupt, that is a task, as pending
|
||||||
///
|
///
|
||||||
/// If the interrupt priority is high enough the interrupt will be serviced
|
/// If the task priority is high enough the task will be serviced immediately,
|
||||||
/// immediately, otherwise it will be serviced at some point after the current
|
/// otherwise it will be serviced at some point after the current task ends.
|
||||||
/// task ends.
|
|
||||||
pub fn set_pending<I>(interrupt: I)
|
pub fn set_pending<I>(interrupt: I)
|
||||||
where
|
where
|
||||||
I: Nr,
|
I: Nr,
|
||||||
|
|
Loading…
Reference in a new issue