mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 15:04:32 +01:00
update examples
This commit is contained in:
parent
271df39bdb
commit
e85d6e53c8
15 changed files with 198 additions and 294 deletions
|
@ -1,5 +1,4 @@
|
||||||
//! A showcase of the `app!` macro syntax
|
//! A showcase of the `app!` macro syntax
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
@ -8,7 +7,7 @@
|
||||||
extern crate cortex_m_rtfm as rtfm;
|
extern crate cortex_m_rtfm as rtfm;
|
||||||
extern crate stm32f103xx;
|
extern crate stm32f103xx;
|
||||||
|
|
||||||
use rtfm::{app, Resource, Threshold};
|
use rtfm::{app, Threshold};
|
||||||
|
|
||||||
app! {
|
app! {
|
||||||
device: stm32f103xx,
|
device: stm32f103xx,
|
||||||
|
@ -21,23 +20,30 @@ app! {
|
||||||
},
|
},
|
||||||
|
|
||||||
init: {
|
init: {
|
||||||
path: init_, // this is a path to the "init" function
|
// This is the path to the `init` function
|
||||||
|
//
|
||||||
|
// `init` doesn't necessarily has to be in the root of the crate
|
||||||
|
path: main::init,
|
||||||
},
|
},
|
||||||
|
|
||||||
idle: {
|
idle: {
|
||||||
path: idle_, // this is a path to the "idle" function
|
// This is a path to the `idle` function
|
||||||
|
//
|
||||||
|
// `idle` doesn't necessarily has to be in the root of the crate
|
||||||
|
path: main::idle,
|
||||||
resources: [OWNED, SHARED],
|
resources: [OWNED, SHARED],
|
||||||
},
|
},
|
||||||
|
|
||||||
tasks: {
|
tasks: {
|
||||||
SYS_TICK: {
|
SYS_TICK: {
|
||||||
path: sys_tick,
|
path: sys_tick,
|
||||||
priority: 1,
|
// If omitted priority is assumed to be 1
|
||||||
|
// priority: 1,
|
||||||
resources: [CO_OWNED, ON, SHARED],
|
resources: [CO_OWNED, ON, SHARED],
|
||||||
},
|
},
|
||||||
|
|
||||||
TIM2: {
|
TIM2: {
|
||||||
// tasks are enabled, between `init` and `idle`, by default but they
|
// Tasks are enabled, between `init` and `idle`, by default but they
|
||||||
// can start disabled if `false` is specified here
|
// can start disabled if `false` is specified here
|
||||||
enabled: false,
|
enabled: false,
|
||||||
path: tim2,
|
path: tim2,
|
||||||
|
@ -47,9 +53,12 @@ app! {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_(_p: init::Peripherals, _r: init::Resources) {}
|
mod main {
|
||||||
|
use rtfm::{self, Resource, Threshold};
|
||||||
|
|
||||||
fn idle_(t: &mut Threshold, mut r: idle::Resources) -> ! {
|
pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
|
||||||
|
|
||||||
|
pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
|
||||||
loop {
|
loop {
|
||||||
*r.OWNED != *r.OWNED;
|
*r.OWNED != *r.OWNED;
|
||||||
|
|
||||||
|
@ -61,6 +70,7 @@ fn idle_(t: &mut Threshold, mut r: idle::Resources) -> ! {
|
||||||
r.SHARED.claim_mut(t, |shared, _| **shared = !**shared);
|
r.SHARED.claim_mut(t, |shared, _| **shared = !**shared);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//! Working with resources in a generic fashion
|
//! Working with resources in a generic fashion
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
@ -36,7 +35,7 @@ fn idle() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a generic function to use resources in any task (regardless of its priority)
|
// A generic function that uses some resources
|
||||||
fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
|
fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
|
||||||
where
|
where
|
||||||
G: Resource<Data = GPIOA>,
|
G: Resource<Data = GPIOA>,
|
||||||
|
@ -53,12 +52,12 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// this task needs critical sections to access the resources
|
// This task needs critical sections to access the resources
|
||||||
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
work(t, &r.GPIOA, &r.SPI1);
|
work(t, &r.GPIOA, &r.SPI1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this task has direct access to the resources
|
// This task has direct access to the resources
|
||||||
fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
||||||
work(t, r.GPIOA, r.SPI1);
|
work(t, r.GPIOA, r.SPI1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
//! Using paths and modules
|
|
||||||
#![deny(unsafe_code)]
|
|
||||||
#![feature(const_fn)]
|
|
||||||
#![feature(proc_macro)]
|
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
extern crate cortex_m_rtfm as rtfm;
|
|
||||||
extern crate stm32f103xx;
|
|
||||||
|
|
||||||
use rtfm::app;
|
|
||||||
|
|
||||||
app! {
|
|
||||||
device: stm32f103xx,
|
|
||||||
|
|
||||||
resources: {
|
|
||||||
static CO_OWNED: u32 = 0;
|
|
||||||
static ON: bool = false;
|
|
||||||
static OWNED: bool = false;
|
|
||||||
static SHARED: bool = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
init: {
|
|
||||||
path: main::init,
|
|
||||||
},
|
|
||||||
|
|
||||||
idle: {
|
|
||||||
path: main::idle,
|
|
||||||
resources: [OWNED, SHARED],
|
|
||||||
},
|
|
||||||
|
|
||||||
tasks: {
|
|
||||||
SYS_TICK: {
|
|
||||||
path: tasks::sys_tick,
|
|
||||||
resources: [CO_OWNED, ON, SHARED],
|
|
||||||
},
|
|
||||||
|
|
||||||
TIM2: {
|
|
||||||
path: tasks::tim2,
|
|
||||||
resources: [CO_OWNED],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mod main {
|
|
||||||
use rtfm::{self, Resource, Threshold};
|
|
||||||
|
|
||||||
pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
|
|
||||||
|
|
||||||
pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
|
|
||||||
loop {
|
|
||||||
*r.OWNED != *r.OWNED;
|
|
||||||
|
|
||||||
if *r.OWNED {
|
|
||||||
if r.SHARED.claim(t, |shared, _| **shared) {
|
|
||||||
rtfm::wfi();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r.SHARED.claim_mut(t, |shared, _| **shared = !**shared);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod tasks {
|
|
||||||
use rtfm::Threshold;
|
|
||||||
|
|
||||||
pub fn sys_tick(_t: &mut Threshold, r: ::SYS_TICK::Resources) {
|
|
||||||
**r.ON = !**r.ON;
|
|
||||||
|
|
||||||
**r.CO_OWNED += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tim2(_t: &mut Threshold, r: ::TIM2::Resources) {
|
|
||||||
**r.CO_OWNED += 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,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(const_fn)]
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
@ -46,9 +45,12 @@ app! {
|
||||||
fn init(_p: init::Peripherals, _r: init::Resources) {}
|
fn init(_p: init::Peripherals, _r: init::Resources) {}
|
||||||
|
|
||||||
fn idle() -> ! {
|
fn idle() -> ! {
|
||||||
// sets task `exti0` as pending
|
// A
|
||||||
|
rtfm::bkpt();
|
||||||
|
|
||||||
|
// Sets task `exti0` as pending
|
||||||
//
|
//
|
||||||
// because `exti0` has higher priority than `idle` it will be executed
|
// Because `exti0` has higher priority than `idle` it will be executed
|
||||||
// immediately
|
// immediately
|
||||||
rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
|
rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
|
||||||
|
|
||||||
|
@ -58,64 +60,66 @@ fn idle() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
// because this task has a priority of 1 the preemption threshold is also 1
|
// Because this task has a priority of 1 the preemption threshold `t` also
|
||||||
|
// starts at 1
|
||||||
|
|
||||||
let mut low = r.LOW;
|
let mut low = r.LOW;
|
||||||
let mut high = r.HIGH;
|
let mut high = r.HIGH;
|
||||||
|
|
||||||
// A
|
// B
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
|
|
||||||
// because `exti1` has higher priority than `exti0` it can preempt it
|
// Because `exti1` has higher priority than `exti0` it can preempt it
|
||||||
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
|
||||||
// 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
|
||||||
// `LOW` resource
|
// `LOW` resource
|
||||||
|
|
||||||
// C
|
// D
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
|
|
||||||
// now `exti1` can't preempt this task because its priority is equal to
|
// Now `exti1` can't preempt this task because its priority is equal to
|
||||||
// the current preemption threshold
|
// the current preemption threshold
|
||||||
rtfm::set_pending(Interrupt::EXTI1);
|
rtfm::set_pending(Interrupt::EXTI1);
|
||||||
|
|
||||||
// but `exti2` can, because its priority is higher than the current
|
// But `exti2` can, because its priority is higher than the current
|
||||||
// preemption threshold
|
// preemption threshold
|
||||||
rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
|
rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
|
||||||
|
|
||||||
// E
|
// F
|
||||||
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
|
||||||
rtfm::set_pending(Interrupt::EXTI2);
|
rtfm::set_pending(Interrupt::EXTI2);
|
||||||
|
|
||||||
// F
|
// G
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
});
|
});
|
||||||
|
|
||||||
// upon leaving the critical section the preemption threshold drops to 2
|
// Upon leaving the critical section the preemption threshold drops back
|
||||||
// and `exti2` immediately preempts this task
|
// to 2 and `exti2` immediately preempts this task
|
||||||
// ~> exti2
|
// ~> exti2
|
||||||
});
|
});
|
||||||
|
|
||||||
// once again the preemption threshold drops to 1
|
// Once again the preemption threshold drops but this time to 1. Now the
|
||||||
// now the pending `exti1` can preempt this task
|
// pending `exti1` task can preempt this task
|
||||||
// ~> exti1
|
// ~> exti1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
|
fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
|
||||||
// B, H
|
// C, I
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
|
fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
|
||||||
// D, G
|
// E, H
|
||||||
rtfm::bkpt();
|
rtfm::bkpt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ use rtfm::{app, Threshold};
|
||||||
app! {
|
app! {
|
||||||
device: stm32f103xx,
|
device: stm32f103xx,
|
||||||
|
|
||||||
// Here resources are declared
|
// Here data resources are declared
|
||||||
//
|
//
|
||||||
// Resources are static variables that are safe to share across tasks
|
// Data resources are static variables that are safe to share across tasks
|
||||||
resources: {
|
resources: {
|
||||||
// declaration of resources looks exactly like declaration of static
|
// Declaration of resources looks exactly like declaration of static
|
||||||
// variables
|
// variables
|
||||||
static ON: bool = false;
|
static ON: bool = false;
|
||||||
},
|
},
|
||||||
|
@ -31,20 +31,24 @@ app! {
|
||||||
tasks: {
|
tasks: {
|
||||||
// Here we declare that we'll use the SYS_TICK exception as a task
|
// Here we declare that we'll use the SYS_TICK exception as a task
|
||||||
SYS_TICK: {
|
SYS_TICK: {
|
||||||
// Path to the task *handler*
|
// Path to the task handler
|
||||||
path: sys_tick,
|
path: sys_tick,
|
||||||
|
|
||||||
// This is the priority of the task.
|
// This is the priority of the task.
|
||||||
//
|
//
|
||||||
// 1 is the lowest priority a task can have.
|
// 1 is the lowest priority a task can have, and the maximum
|
||||||
// The maximum priority is determined by the number of priority bits
|
// priority is determined by the number of priority bits the device
|
||||||
// the device has. This device has 4 priority bits so 16 is the
|
// has. `stm32f103xx` has 4 priority bits so 16 is the maximum valid
|
||||||
// maximum value.
|
// value.
|
||||||
|
//
|
||||||
|
// You can omit this field. If you do the priority is assumed to be
|
||||||
|
// 1.
|
||||||
priority: 1,
|
priority: 1,
|
||||||
|
|
||||||
// These are the *resources* associated with this task
|
// These are the resources this task has access to.
|
||||||
//
|
//
|
||||||
// The peripherals that the task needs can be listed here
|
// A resource can be a peripheral like `GPIOC` or a static variable
|
||||||
|
// like `ON`
|
||||||
resources: [GPIOC, ON],
|
resources: [GPIOC, ON],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -75,8 +79,10 @@ fn idle() -> ! {
|
||||||
|
|
||||||
// This is the task handler of the SYS_TICK exception
|
// This is the task handler of the SYS_TICK exception
|
||||||
//
|
//
|
||||||
// `r` is the resources this task has access to. `SYS_TICK::Resources` has one
|
// `_t` is the preemption threshold token. We won't use it in this program.
|
||||||
// field per every resource declared in `app!`.
|
//
|
||||||
|
// `r` is the set of resources this task has access to. `TIMER0_A1::Resources`
|
||||||
|
// 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
|
||||||
**r.ON = !**r.ON;
|
**r.ON = !**r.ON;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! 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(const_fn)]
|
||||||
#![feature(proc_macro)]
|
#![feature(proc_macro)]
|
||||||
|
@ -17,7 +17,7 @@ app! {
|
||||||
},
|
},
|
||||||
|
|
||||||
tasks: {
|
tasks: {
|
||||||
// the task `SYS_TICK` has higher priority than `TIM2`
|
// The `SYS_TICK` task has higher priority than `TIM2`
|
||||||
SYS_TICK: {
|
SYS_TICK: {
|
||||||
path: sys_tick,
|
path: sys_tick,
|
||||||
priority: 2,
|
priority: 2,
|
||||||
|
@ -45,7 +45,7 @@ fn idle() -> ! {
|
||||||
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
// this task can't be preempted by `tim2` so it has direct access to the
|
// This task can't be preempted by `tim2` so it has direct access to the
|
||||||
// resource data
|
// resource data
|
||||||
**r.COUNTER += 1;
|
**r.COUNTER += 1;
|
||||||
|
|
||||||
|
@ -55,10 +55,10 @@ fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
fn tim2(t: &mut Threshold, mut r: TIM2::Resources) {
|
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 data corruption or data loss
|
// lead to undefined behavior
|
||||||
r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
||||||
|
|
||||||
// ..
|
// ..
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! 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(const_fn)]
|
||||||
|
@ -13,34 +13,25 @@ use rtfm::{app, Threshold};
|
||||||
app! {
|
app! {
|
||||||
device: stm32f103xx,
|
device: stm32f103xx,
|
||||||
|
|
||||||
// Resources that are plain data, not peripherals
|
|
||||||
resources: {
|
resources: {
|
||||||
// Declaration of resources looks like the declaration of `static`
|
|
||||||
// variables
|
|
||||||
static COUNTER: u64 = 0;
|
static COUNTER: u64 = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Both SYS_TICK and TIM2 have access to the `COUNTER` data
|
||||||
tasks: {
|
tasks: {
|
||||||
SYS_TICK: {
|
SYS_TICK: {
|
||||||
path: sys_tick,
|
path: sys_tick,
|
||||||
priority: 1,
|
|
||||||
// Both this task and TIM2 have access to the `COUNTER` resource
|
|
||||||
resources: [COUNTER],
|
resources: [COUNTER],
|
||||||
},
|
},
|
||||||
|
|
||||||
// An interrupt as a task
|
|
||||||
TIM2: {
|
TIM2: {
|
||||||
// For interrupts the `enabled` field must be specified. It
|
|
||||||
// indicates if the interrupt will be enabled or disabled once
|
|
||||||
// `idle` starts
|
|
||||||
path: tim2,
|
path: tim2,
|
||||||
priority: 1,
|
|
||||||
resources: [COUNTER],
|
resources: [COUNTER],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// when data resources are declared in the top `resources` field, `init` will
|
// When data resources are declared in the top `resources` field, `init` will
|
||||||
// have full access to them
|
// have full access to them
|
||||||
fn init(_p: init::Peripherals, _r: init::Resources) {
|
fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||||
// ..
|
// ..
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Minimal example with zero tasks
|
//! Minimal example with zero tasks
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
#![feature(proc_macro)] // IMPORTANT always include this feature gate
|
// IMPORTANT always include this feature gate
|
||||||
|
#![feature(proc_macro)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
|
extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
|
||||||
|
@ -15,7 +15,7 @@ use rtfm::app;
|
||||||
// This macro will expand to a `main` function so you don't need to supply
|
// This macro will expand to a `main` function so you don't need to supply
|
||||||
// `main` yourself.
|
// `main` yourself.
|
||||||
app! {
|
app! {
|
||||||
// this is a path to the device crate
|
// this is the path to the device crate
|
||||||
device: stm32f103xx,
|
device: stm32f103xx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,20 +28,14 @@ fn init(p: init::Peripherals) {
|
||||||
p.GPIOA;
|
p.GPIOA;
|
||||||
p.RCC;
|
p.RCC;
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
// You'll hit this breakpoint first
|
|
||||||
rtfm::bkpt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The idle loop.
|
// The idle loop.
|
||||||
//
|
//
|
||||||
// This runs afterwards and has a priority of 0. All tasks can preempt this
|
// This runs after `init` and has a priority of 0. All tasks can preempt this
|
||||||
// function. This function can never return so it must contain some sort of
|
// function. This function can never return so it must contain some sort of
|
||||||
// endless loop.
|
// endless loop.
|
||||||
fn idle() -> ! {
|
fn idle() -> ! {
|
||||||
// And then this breakpoint
|
|
||||||
rtfm::bkpt();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// This puts the processor to sleep until there's a task to service
|
// This puts the processor to sleep until there's a task to service
|
||||||
rtfm::wfi();
|
rtfm::wfi();
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Minimal example with zero tasks
|
//! Minimal example with zero tasks
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(proc_macro)] // IMPORTANT always include this feature gate
|
//! // IMPORTANT always include this feature gate
|
||||||
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
|
//! extern crate cortex_m_rtfm as rtfm; // IMPORTANT always do this rename
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
//! // This macro will expand to a `main` function so you don't need to supply
|
//! // This macro will expand to a `main` function so you don't need to supply
|
||||||
//! // `main` yourself.
|
//! // `main` yourself.
|
||||||
//! app! {
|
//! app! {
|
||||||
//! // this is a path to the device crate
|
//! // this is the path to the device crate
|
||||||
//! device: stm32f103xx,
|
//! device: stm32f103xx,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -30,20 +30,14 @@
|
||||||
//! p.GPIOA;
|
//! p.GPIOA;
|
||||||
//! p.RCC;
|
//! p.RCC;
|
||||||
//! // ..
|
//! // ..
|
||||||
//!
|
|
||||||
//! // You'll hit this breakpoint first
|
|
||||||
//! rtfm::bkpt();
|
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // The idle loop.
|
//! // The idle loop.
|
||||||
//! //
|
//! //
|
||||||
//! // This runs afterwards and has a priority of 0. All tasks can preempt this
|
//! // This runs after `init` and has a priority of 0. All tasks can preempt this
|
||||||
//! // function. This function can never return so it must contain some sort of
|
//! // function. This function can never return so it must contain some sort of
|
||||||
//! // endless loop.
|
//! // endless loop.
|
||||||
//! fn idle() -> ! {
|
//! fn idle() -> ! {
|
||||||
//! // And then this breakpoint
|
|
||||||
//! rtfm::bkpt();
|
|
||||||
//!
|
|
||||||
//! loop {
|
//! loop {
|
||||||
//! // This puts the processor to sleep until there's a task to service
|
//! // This puts the processor to sleep until there's a task to service
|
||||||
//! rtfm::wfi();
|
//! rtfm::wfi();
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
//! An application with one task
|
//! An application with one task
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
//! #![feature(const_fn)]
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! extern crate cortex_m;
|
//! extern crate cortex_m;
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
|
@ -18,6 +16,15 @@
|
||||||
//! app! {
|
//! app! {
|
||||||
//! device: stm32f103xx,
|
//! device: stm32f103xx,
|
||||||
//!
|
//!
|
||||||
|
//! // Here data resources are declared
|
||||||
|
//! //
|
||||||
|
//! // Data resources are static variables that are safe to share across tasks
|
||||||
|
//! resources: {
|
||||||
|
//! // Declaration of resources looks exactly like declaration of static
|
||||||
|
//! // variables
|
||||||
|
//! static ON: bool = false;
|
||||||
|
//! },
|
||||||
|
//!
|
||||||
//! // Here tasks are declared
|
//! // Here tasks are declared
|
||||||
//! //
|
//! //
|
||||||
//! // Each task corresponds to an interrupt or an exception. Every time the
|
//! // Each task corresponds to an interrupt or an exception. Every time the
|
||||||
|
@ -26,22 +33,30 @@
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! // Here we declare that we'll use the SYS_TICK exception as a task
|
//! // Here we declare that we'll use the SYS_TICK exception as a task
|
||||||
//! SYS_TICK: {
|
//! SYS_TICK: {
|
||||||
|
//! // Path to the task handler
|
||||||
|
//! path: sys_tick,
|
||||||
|
//!
|
||||||
//! // This is the priority of the task.
|
//! // This is the priority of the task.
|
||||||
//! // 1 is the lowest priority a task can have.
|
//! //
|
||||||
//! // The maximum priority is determined by the number of priority bits
|
//! // 1 is the lowest priority a task can have, and the maximum
|
||||||
//! // the device has. This device has 4 priority bits so 16 is the
|
//! // priority is determined by the number of priority bits the device
|
||||||
//! // maximum value.
|
//! // 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,
|
//! priority: 1,
|
||||||
//!
|
//!
|
||||||
//! // These are the *resources* associated with this task
|
//! // These are the resources this task has access to.
|
||||||
//! //
|
//! //
|
||||||
//! // The peripherals that the task needs can be listed here
|
//! // A resource can be a peripheral like `GPIOC` or a static variable
|
||||||
//! resources: [GPIOC],
|
//! // like `ON`
|
||||||
|
//! resources: [GPIOC, ON],
|
||||||
//! },
|
//! },
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn init(p: init::Peripherals) {
|
//! fn init(p: init::Peripherals, _r: init::Resources) {
|
||||||
//! // power on GPIOC
|
//! // power on GPIOC
|
||||||
//! p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
//! p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
|
||||||
//!
|
//!
|
||||||
|
@ -64,26 +79,17 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // This binds the `sys_tick` handler to the `SYS_TICK` task
|
|
||||||
//! //
|
|
||||||
//! // This particular handler has local state associated to it. The value of the
|
|
||||||
//! // `STATE` variable will be preserved across invocations of this handler
|
|
||||||
//! task!(SYS_TICK, sys_tick, Locals {
|
|
||||||
//! static STATE: bool = false;
|
|
||||||
//! });
|
|
||||||
//!
|
|
||||||
//! // This is the task handler of the SYS_TICK exception
|
//! // This is the task handler of the SYS_TICK exception
|
||||||
//! //
|
//! //
|
||||||
//! // `t` is the preemption threshold token. We won't use it this time.
|
//! // `_t` is the preemption threshold token. We won't use it in this program.
|
||||||
//! // `l` is the data local to this task. The type here must match the one declared
|
//! //
|
||||||
//! // in `task!`.
|
//! // `r` is the set of resources this task has access to. `TIMER0_A1::Resources`
|
||||||
//! // `r` is the resources this task has access to. `SYS_TICK::Resources` has one
|
//! // has one field per resource declared in `app!`.
|
||||||
//! // field per resource declared in `app!`.
|
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
//! fn sys_tick(_t: &mut Threshold, l: &mut Locals, r: SYS_TICK::Resources) {
|
|
||||||
//! // toggle state
|
//! // toggle state
|
||||||
//! *l.STATE = !*l.STATE;
|
//! **r.ON = !**r.ON;
|
||||||
//!
|
//!
|
||||||
//! if *l.STATE {
|
//! if **r.ON {
|
||||||
//! // set the pin PC13 high
|
//! // set the pin PC13 high
|
||||||
//! r.GPIOC.bsrr.write(|w| w.bs13().set());
|
//! r.GPIOC.bsrr.write(|w| w.bs13().set());
|
||||||
//! } else {
|
//! } else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! 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
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -7,7 +7,6 @@
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
|
@ -16,33 +15,25 @@
|
||||||
//! app! {
|
//! app! {
|
||||||
//! device: stm32f103xx,
|
//! device: stm32f103xx,
|
||||||
//!
|
//!
|
||||||
//! // Resources that are plain data, not peripherals
|
|
||||||
//! resources: {
|
//! resources: {
|
||||||
//! // Declaration of resources looks like the declaration of `static`
|
|
||||||
//! // variables
|
|
||||||
//! static COUNTER: u64 = 0;
|
//! static COUNTER: u64 = 0;
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
|
//! // Both SYS_TICK and TIM2 have access to the `COUNTER` data
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! SYS_TICK: {
|
//! SYS_TICK: {
|
||||||
//! priority: 1,
|
//! path: sys_tick,
|
||||||
//! // Both this task and TIM2 have access to the `COUNTER` resource
|
|
||||||
//! resources: [COUNTER],
|
//! resources: [COUNTER],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! // An interrupt as a task
|
|
||||||
//! TIM2: {
|
//! TIM2: {
|
||||||
//! // For interrupts the `enabled` field must be specified. It
|
//! path: tim2,
|
||||||
//! // indicates if the interrupt will be enabled or disabled once
|
|
||||||
//! // `idle` starts
|
|
||||||
//! enabled: true,
|
|
||||||
//! priority: 1,
|
|
||||||
//! resources: [COUNTER],
|
//! resources: [COUNTER],
|
||||||
//! },
|
//! },
|
||||||
//! },
|
//! },
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // when data resources are declared in the top `resources` field, `init` will
|
//! // When data resources are declared in the top `resources` field, `init` will
|
||||||
//! // have full access to them
|
//! // have full access to them
|
||||||
//! fn init(_p: init::Peripherals, _r: init::Resources) {
|
//! fn init(_p: init::Peripherals, _r: init::Resources) {
|
||||||
//! // ..
|
//! // ..
|
||||||
|
@ -54,8 +45,6 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(SYS_TICK, sys_tick);
|
|
||||||
//!
|
|
||||||
//! // As both tasks are running at the same priority one can't preempt the other.
|
//! // As both tasks are running at the same priority one can't preempt the other.
|
||||||
//! // Thus both tasks have direct access to the resource
|
//! // Thus both tasks have direct access to the resource
|
||||||
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
|
@ -66,8 +55,6 @@
|
||||||
//! // ..
|
//! // ..
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(TIM2, tim2);
|
|
||||||
//!
|
|
||||||
//! fn tim2(_t: &mut Threshold, r: TIM2::Resources) {
|
//! fn tim2(_t: &mut Threshold, r: TIM2::Resources) {
|
||||||
//! // ..
|
//! // ..
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
//! 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(const_fn)]
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
|
@ -21,14 +19,15 @@
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! // the task `SYS_TICK` has higher priority than `TIM2`
|
//! // The `SYS_TICK` task has higher priority than `TIM2`
|
||||||
//! SYS_TICK: {
|
//! SYS_TICK: {
|
||||||
|
//! path: sys_tick,
|
||||||
//! priority: 2,
|
//! priority: 2,
|
||||||
//! resources: [COUNTER],
|
//! resources: [COUNTER],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! TIM2: {
|
//! TIM2: {
|
||||||
//! enabled: true,
|
//! path: tim2,
|
||||||
//! priority: 1,
|
//! priority: 1,
|
||||||
//! resources: [COUNTER],
|
//! resources: [COUNTER],
|
||||||
//! },
|
//! },
|
||||||
|
@ -45,27 +44,23 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(SYS_TICK, sys_tick);
|
|
||||||
//!
|
|
||||||
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
//! // ..
|
//! // ..
|
||||||
//!
|
//!
|
||||||
//! // this task can't be preempted by `tim2` so it has direct access to the
|
//! // This task can't be preempted by `tim2` so it has direct access to the
|
||||||
//! // resource data
|
//! // resource data
|
||||||
//! **r.COUNTER += 1;
|
//! **r.COUNTER += 1;
|
||||||
//!
|
//!
|
||||||
//! // ..
|
//! // ..
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(TIM2, tim2);
|
|
||||||
//!
|
|
||||||
//! fn tim2(t: &mut Threshold, mut r: TIM2::Resources) {
|
//! 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 data corruption or data loss
|
//! // lead to undefined behavior
|
||||||
//! r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
//! r.COUNTER.claim_mut(t, |counter, _t| { **counter += 1; });
|
||||||
//!
|
//!
|
||||||
//! // ..
|
//! // ..
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
//! 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(const_fn)]
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
|
@ -27,19 +25,19 @@
|
||||||
//!
|
//!
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! EXTI0: {
|
//! EXTI0: {
|
||||||
//! enabled: true,
|
//! path: exti0,
|
||||||
//! priority: 1,
|
//! priority: 1,
|
||||||
//! resources: [LOW, HIGH],
|
//! resources: [LOW, HIGH],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! EXTI1: {
|
//! EXTI1: {
|
||||||
//! enabled: true,
|
//! path: exti1,
|
||||||
//! priority: 2,
|
//! priority: 2,
|
||||||
//! resources: [LOW],
|
//! resources: [LOW],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! EXTI2: {
|
//! EXTI2: {
|
||||||
//! enabled: true,
|
//! path: exti2,
|
||||||
//! priority: 3,
|
//! priority: 3,
|
||||||
//! resources: [HIGH],
|
//! resources: [HIGH],
|
||||||
//! },
|
//! },
|
||||||
|
@ -49,9 +47,12 @@
|
||||||
//! fn init(_p: init::Peripherals, _r: init::Resources) {}
|
//! fn init(_p: init::Peripherals, _r: init::Resources) {}
|
||||||
//!
|
//!
|
||||||
//! fn idle() -> ! {
|
//! fn idle() -> ! {
|
||||||
//! // sets task `exti0` as pending
|
//! // A
|
||||||
|
//! rtfm::bkpt();
|
||||||
|
//!
|
||||||
|
//! // Sets task `exti0` as pending
|
||||||
//! //
|
//! //
|
||||||
//! // because `exti0` has higher priority than `idle` it will be executed
|
//! // Because `exti0` has higher priority than `idle` it will be executed
|
||||||
//! // immediately
|
//! // immediately
|
||||||
//! rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
|
//! rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
|
||||||
//!
|
//!
|
||||||
|
@ -60,72 +61,68 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(EXTI0, exti0);
|
|
||||||
//!
|
|
||||||
//! fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
//! fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
//! // because this task has a priority of 1 the preemption threshold is also 1
|
//! // Because this task has a priority of 1 the preemption threshold `t` also
|
||||||
|
//! // starts at 1
|
||||||
//!
|
//!
|
||||||
//! let mut low = r.LOW;
|
//! let mut low = r.LOW;
|
||||||
//! let mut high = r.HIGH;
|
//! let mut high = r.HIGH;
|
||||||
//!
|
//!
|
||||||
//! // A
|
//! // B
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//!
|
//!
|
||||||
//! // because `exti1` has higher priority than `exti0` it can preempt it
|
//! // Because `exti1` has higher priority than `exti0` it can preempt it
|
||||||
//! 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
|
||||||
//! // 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
|
||||||
//! // `LOW` resource
|
//! // `LOW` resource
|
||||||
//!
|
//!
|
||||||
//! // C
|
//! // D
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//!
|
//!
|
||||||
//! // now `exti1` can't preempt this task because its priority is equal to
|
//! // Now `exti1` can't preempt this task because its priority is equal to
|
||||||
//! // the current preemption threshold
|
//! // the current preemption threshold
|
||||||
//! rtfm::set_pending(Interrupt::EXTI1);
|
//! rtfm::set_pending(Interrupt::EXTI1);
|
||||||
//!
|
//!
|
||||||
//! // but `exti2` can, because its priority is higher than the current
|
//! // But `exti2` can, because its priority is higher than the current
|
||||||
//! // preemption threshold
|
//! // preemption threshold
|
||||||
//! rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
|
//! rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
|
||||||
//!
|
//!
|
||||||
//! // E
|
//! // F
|
||||||
//! 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
|
||||||
//! rtfm::set_pending(Interrupt::EXTI2);
|
//! rtfm::set_pending(Interrupt::EXTI2);
|
||||||
//!
|
//!
|
||||||
//! // F
|
//! // G
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! // upon leaving the critical section the preemption threshold drops to 2
|
//! // Upon leaving the critical section the preemption threshold drops back
|
||||||
//! // and `exti2` immediately preempts this task
|
//! // to 2 and `exti2` immediately preempts this task
|
||||||
//! // ~> exti2
|
//! // ~> exti2
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! // once again the preemption threshold drops to 1
|
//! // Once again the preemption threshold drops but this time to 1. Now the
|
||||||
//! // now the pending `exti1` can preempt this task
|
//! // pending `exti1` task can preempt this task
|
||||||
//! // ~> exti1
|
//! // ~> exti1
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(EXTI1, exti1);
|
|
||||||
//!
|
|
||||||
//! fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
|
//! fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
|
||||||
//! // B, H
|
//! // C, I
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(EXTI2, exti2);
|
|
||||||
//!
|
|
||||||
//! fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
|
//! fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
|
||||||
//! // D, G
|
//! // E, H
|
||||||
//! rtfm::bkpt();
|
//! rtfm::bkpt();
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
//! Working with resources in a generic fashion
|
//! Working with resources in a generic fashion
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
|
@ -18,13 +16,13 @@
|
||||||
//!
|
//!
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! EXTI0: {
|
//! EXTI0: {
|
||||||
//! enabled: true,
|
//! path: exti0,
|
||||||
//! priority: 1,
|
//! priority: 1,
|
||||||
//! resources: [GPIOA, SPI1],
|
//! resources: [GPIOA, SPI1],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! EXTI1: {
|
//! EXTI1: {
|
||||||
//! enabled: true,
|
//! path: exti1,
|
||||||
//! priority: 2,
|
//! priority: 2,
|
||||||
//! resources: [GPIOA, SPI1],
|
//! resources: [GPIOA, SPI1],
|
||||||
//! },
|
//! },
|
||||||
|
@ -39,7 +37,7 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // a generic function to use resources in any task (regardless of its priority)
|
//! // A generic function that uses some resources
|
||||||
//! fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
|
//! fn work<G, S>(t: &mut Threshold, gpioa: &G, spi1: &S)
|
||||||
//! where
|
//! where
|
||||||
//! G: Resource<Data = GPIOA>,
|
//! G: Resource<Data = GPIOA>,
|
||||||
|
@ -56,16 +54,12 @@
|
||||||
//! });
|
//! });
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(EXTI0, exti0);
|
//! // This task needs critical sections to access the resources
|
||||||
//!
|
|
||||||
//! // this task needs critical sections to access the resources
|
|
||||||
//! fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
//! fn exti0(t: &mut Threshold, r: EXTI0::Resources) {
|
||||||
//! work(t, &r.GPIOA, &r.SPI1);
|
//! work(t, &r.GPIOA, &r.SPI1);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(EXTI1, exti1);
|
//! // This task has direct access to the resources
|
||||||
//!
|
|
||||||
//! // this task has direct access to the resources
|
|
||||||
//! fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
//! fn exti1(t: &mut Threshold, r: EXTI1::Resources) {
|
||||||
//! work(t, r.GPIOA, r.SPI1);
|
//! work(t, r.GPIOA, r.SPI1);
|
||||||
//! }
|
//! }
|
||||||
|
|
|
@ -1,62 +1,70 @@
|
||||||
//! A showcase of the `app!` macro syntax
|
//! A showcase of the `app!` macro syntax
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
|
||||||
//! #![deny(unsafe_code)]
|
//! #![deny(unsafe_code)]
|
||||||
//! #![feature(const_fn)]
|
//! #![feature(const_fn)]
|
||||||
//! #![feature(proc_macro)]
|
//! #![feature(proc_macro)]
|
||||||
//! #![no_std]
|
//! #![no_std]
|
||||||
//!
|
//!
|
||||||
//! #[macro_use(task)]
|
|
||||||
//! extern crate cortex_m_rtfm as rtfm;
|
//! extern crate cortex_m_rtfm as rtfm;
|
||||||
//! extern crate stm32f103xx;
|
//! extern crate stm32f103xx;
|
||||||
//!
|
//!
|
||||||
//! use rtfm::{app, Resource, Threshold};
|
//! use rtfm::{app, Threshold};
|
||||||
//!
|
//!
|
||||||
//! app! {
|
//! app! {
|
||||||
//! device: stm32f103xx,
|
//! device: stm32f103xx,
|
||||||
//!
|
//!
|
||||||
//! resources: {
|
//! resources: {
|
||||||
//! static CO_OWNED: u32 = 0;
|
//! static CO_OWNED: u32 = 0;
|
||||||
|
//! static ON: bool = false;
|
||||||
//! static OWNED: bool = false;
|
//! static OWNED: bool = false;
|
||||||
//! static SHARED: bool = false;
|
//! static SHARED: bool = false;
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! init: {
|
//! init: {
|
||||||
//! path: init_, // this is a path to the "init" function
|
//! // This is the path to the `init` function
|
||||||
|
//! //
|
||||||
|
//! // `init` doesn't necessarily has to be in the root of the crate
|
||||||
|
//! path: main::init,
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! idle: {
|
//! idle: {
|
||||||
//! locals: {
|
//! // This is a path to the `idle` function
|
||||||
//! static COUNTER: u32 = 0;
|
//! //
|
||||||
//! },
|
//! // `idle` doesn't necessarily has to be in the root of the crate
|
||||||
//! path: idle_, // this is a path to the "idle" function
|
//! path: main::idle,
|
||||||
//! resources: [OWNED, SHARED],
|
//! resources: [OWNED, SHARED],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! tasks: {
|
//! tasks: {
|
||||||
//! SYS_TICK: {
|
//! SYS_TICK: {
|
||||||
//! priority: 1,
|
//! path: sys_tick,
|
||||||
//! resources: [CO_OWNED, SHARED],
|
//! // If omitted priority is assumed to be 1
|
||||||
|
//! // priority: 1,
|
||||||
|
//! resources: [CO_OWNED, ON, SHARED],
|
||||||
//! },
|
//! },
|
||||||
//!
|
//!
|
||||||
//! TIM2: {
|
//! TIM2: {
|
||||||
//! enabled: true,
|
//! // Tasks are enabled, between `init` and `idle`, by default but they
|
||||||
|
//! // can start disabled if `false` is specified here
|
||||||
|
//! enabled: false,
|
||||||
|
//! path: tim2,
|
||||||
//! priority: 1,
|
//! priority: 1,
|
||||||
//! resources: [CO_OWNED],
|
//! resources: [CO_OWNED],
|
||||||
//! },
|
//! },
|
||||||
//! },
|
//! },
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn init_(_p: init::Peripherals, _r: init::Resources) {}
|
//! mod main {
|
||||||
|
//! use rtfm::{self, Resource, Threshold};
|
||||||
//!
|
//!
|
||||||
//! fn idle_(t: &mut Threshold, l: &mut idle::Locals, mut r: idle::Resources) -> ! {
|
//! pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
|
||||||
|
//!
|
||||||
|
//! pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
|
||||||
//! loop {
|
//! loop {
|
||||||
//! *l.COUNTER += 1;
|
//! *r.OWNED != *r.OWNED;
|
||||||
//!
|
//!
|
||||||
//! **r.OWNED != **r.OWNED;
|
//! if *r.OWNED {
|
||||||
//!
|
|
||||||
//! if **r.OWNED {
|
|
||||||
//! if r.SHARED.claim(t, |shared, _| **shared) {
|
//! if r.SHARED.claim(t, |shared, _| **shared) {
|
||||||
//! rtfm::wfi();
|
//! rtfm::wfi();
|
||||||
//! }
|
//! }
|
||||||
|
@ -65,19 +73,14 @@
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(SYS_TICK, sys_tick, Local {
|
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
|
||||||
//! static STATE: bool = true;
|
//! **r.ON = !**r.ON;
|
||||||
//! });
|
|
||||||
//!
|
|
||||||
//! fn sys_tick(_t: &mut Threshold, l: &mut Local, r: SYS_TICK::Resources) {
|
|
||||||
//! *l.STATE = !*l.STATE;
|
|
||||||
//!
|
//!
|
||||||
//! **r.CO_OWNED += 1;
|
//! **r.CO_OWNED += 1;
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! task!(TIM2, tim2);
|
|
||||||
//!
|
|
||||||
//! fn tim2(_t: &mut Threshold, r: TIM2::Resources) {
|
//! fn tim2(_t: &mut Threshold, r: TIM2::Resources) {
|
||||||
//! **r.CO_OWNED += 1;
|
//! **r.CO_OWNED += 1;
|
||||||
//! }
|
//! }
|
||||||
|
|
Loading…
Reference in a new issue