Skip to content
Snippets Groups Projects
Commit e85d6e53 authored by Jorge Aparicio's avatar Jorge Aparicio
Browse files

update examples

parent 271df39b
No related branches found
No related tags found
No related merge requests found
//! A showcase of the `app!` macro syntax
#![deny(unsafe_code)]
#![feature(const_fn)]
#![feature(proc_macro)]
......@@ -8,7 +7,7 @@
extern crate cortex_m_rtfm as rtfm;
extern crate stm32f103xx;
use rtfm::{app, Resource, Threshold};
use rtfm::{app, Threshold};
app! {
device: stm32f103xx,
......@@ -21,23 +20,30 @@ app! {
},
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: {
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],
},
tasks: {
SYS_TICK: {
path: sys_tick,
priority: 1,
// If omitted priority is assumed to be 1
// priority: 1,
resources: [CO_OWNED, ON, SHARED],
},
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
enabled: false,
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 {
*r.OWNED != *r.OWNED;
......@@ -62,6 +71,7 @@ fn idle_(t: &mut Threshold, mut r: idle::Resources) -> ! {
}
}
}
}
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
**r.ON = !**r.ON;
......
//! Working with resources in a generic fashion
#![deny(unsafe_code)]
#![feature(proc_macro)]
#![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)
where
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) {
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) {
work(t, r.GPIOA, r.SPI1);
}
//! 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
//! letters in the comments: A, then B, then C, etc.
#![deny(unsafe_code)]
#![feature(const_fn)]
#![feature(proc_macro)]
......@@ -46,9 +45,12 @@ app! {
fn init(_p: init::Peripherals, _r: init::Resources) {}
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
rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
......@@ -58,64 +60,66 @@ fn idle() -> ! {
}
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 high = r.HIGH;
// A
// B
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
// a claim creates a critical section
// A claim creates a critical section
low.claim_mut(t, |_low, t| {
// this claim increases the preemption threshold to 2
// just high enough to not race with task `exti1` for access to the
// This claim increases the preemption threshold to 2
//
// 2 is just high enough to not race with task `exti1` for access to the
// `LOW` resource
// C
// D
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
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
rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
// E
// F
rtfm::bkpt();
// claims can be nested
// Claims can be nested
high.claim_mut(t, |_high, _| {
// 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);
// F
// G
rtfm::bkpt();
});
// upon leaving the critical section the preemption threshold drops to 2
// and `exti2` immediately preempts this task
// Upon leaving the critical section the preemption threshold drops back
// to 2 and `exti2` immediately preempts this task
// ~> exti2
});
// once again the preemption threshold drops to 1
// now the pending `exti1` can preempt this task
// Once again the preemption threshold drops but this time to 1. Now the
// pending `exti1` task can preempt this task
// ~> exti1
}
fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
// B, H
// C, I
rtfm::bkpt();
}
fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
// D, G
// E, H
rtfm::bkpt();
}
......@@ -14,11 +14,11 @@ use rtfm::{app, Threshold};
app! {
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: {
// declaration of resources looks exactly like declaration of static
// Declaration of resources looks exactly like declaration of static
// variables
static ON: bool = false;
},
......@@ -31,20 +31,24 @@ app! {
tasks: {
// Here we declare that we'll use the SYS_TICK exception as a task
SYS_TICK: {
// Path to the task *handler*
// Path to the task handler
path: sys_tick,
// 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
// the device has. This device has 4 priority bits so 16 is the
// maximum value.
// 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* 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],
},
}
......@@ -75,8 +79,10 @@ fn idle() -> ! {
// This is the task handler of the SYS_TICK exception
//
// `r` is the resources this task has access to. `SYS_TICK::Resources` has one
// field per every resource declared in `app!`.
// `_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`
// has one field per resource declared in `app!`.
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
// toggle state
**r.ON = !**r.ON;
......
//! 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)]
#![feature(const_fn)]
#![feature(proc_macro)]
......@@ -17,7 +17,7 @@ app! {
},
tasks: {
// the task `SYS_TICK` has higher priority than `TIM2`
// The `SYS_TICK` task has higher priority than `TIM2`
SYS_TICK: {
path: sys_tick,
priority: 2,
......@@ -45,7 +45,7 @@ fn idle() -> ! {
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
**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) {
// ..
// 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
// 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; });
// ..
......
//! 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)]
#![feature(const_fn)]
......@@ -13,34 +13,25 @@ use rtfm::{app, Threshold};
app! {
device: stm32f103xx,
// Resources that are plain data, not peripherals
resources: {
// Declaration of resources looks like the declaration of `static`
// variables
static COUNTER: u64 = 0;
},
// Both SYS_TICK and TIM2 have access to the `COUNTER` data
tasks: {
SYS_TICK: {
path: sys_tick,
priority: 1,
// Both this task and TIM2 have access to the `COUNTER` resource
resources: [COUNTER],
},
// An interrupt as a task
TIM2: {
// For interrupts the `enabled` field must be specified. It
// indicates if the interrupt will be enabled or disabled once
// `idle` starts
path: tim2,
priority: 1,
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
fn init(_p: init::Peripherals, _r: init::Resources) {
// ..
......
//! Minimal example with zero tasks
#![deny(unsafe_code)]
#![feature(proc_macro)] // IMPORTANT always include this feature gate
// IMPORTANT always include this feature gate
#![feature(proc_macro)]
#![no_std]
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
// `main` yourself.
app! {
// this is a path to the device crate
// this is the path to the device crate
device: stm32f103xx,
}
......@@ -28,20 +28,14 @@ fn init(p: init::Peripherals) {
p.GPIOA;
p.RCC;
// ..
// You'll hit this breakpoint first
rtfm::bkpt();
}
// 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
// endless loop.
fn idle() -> ! {
// And then this breakpoint
rtfm::bkpt();
loop {
// This puts the processor to sleep until there's a task to service
rtfm::wfi();
......
//! Minimal example with zero tasks
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![feature(proc_macro)] // IMPORTANT always include this feature gate
//! // IMPORTANT always include this feature gate
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! 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
//! // `main` yourself.
//! app! {
//! // this is a path to the device crate
//! // this is the path to the device crate
//! device: stm32f103xx,
//! }
//!
......@@ -30,20 +30,14 @@
//! p.GPIOA;
//! p.RCC;
//! // ..
//!
//! // You'll hit this breakpoint first
//! rtfm::bkpt();
//! }
//!
//! // 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
//! // endless loop.
//! fn idle() -> ! {
//! // And then this breakpoint
//! rtfm::bkpt();
//!
//! loop {
//! // This puts the processor to sleep until there's a task to service
//! rtfm::wfi();
......
//! An application with one task
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![feature(const_fn)]
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! extern crate cortex_m;
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
......@@ -18,6 +16,15 @@
//! app! {
//! 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
//! //
//! // Each task corresponds to an interrupt or an exception. Every time the
......@@ -26,22 +33,30 @@
//! tasks: {
//! // Here we declare that we'll use the SYS_TICK exception as a task
//! SYS_TICK: {
//! // Path to the task handler
//! path: sys_tick,
//!
//! // 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
//! // the device has. This device has 4 priority bits so 16 is the
//! // maximum value.
//! //
//! // 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* associated with this task
//! // These are the resources this task has access to.
//! //
//! // The peripherals that the task needs can be listed here
//! resources: [GPIOC],
//! // A resource can be a peripheral like `GPIOC` or a static variable
//! // like `ON`
//! resources: [GPIOC, ON],
//! },
//! }
//! }
//!
//! fn init(p: init::Peripherals) {
//! fn init(p: init::Peripherals, _r: init::Resources) {
//! // power on GPIOC
//! 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
//! //
//! // `t` is the preemption threshold token. We won't use it this time.
//! // `l` is the data local to this task. The type here must match the one declared
//! // in `task!`.
//! // `r` is the resources this task has access to. `SYS_TICK::Resources` has one
//! // field per resource declared in `app!`.
//! fn sys_tick(_t: &mut Threshold, l: &mut Locals, r: SYS_TICK::Resources) {
//! // `_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`
//! // has one field per resource declared in `app!`.
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
//! // toggle state
//! *l.STATE = !*l.STATE;
//! **r.ON = !**r.ON;
//!
//! if *l.STATE {
//! if **r.ON {
//! // set the pin PC13 high
//! r.GPIOC.bsrr.write(|w| w.bs13().set());
//! } else {
......
//! 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)]
//! #![no_std]
//!
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
......@@ -16,33 +15,25 @@
//! app! {
//! device: stm32f103xx,
//!
//! // Resources that are plain data, not peripherals
//! resources: {
//! // Declaration of resources looks like the declaration of `static`
//! // variables
//! static COUNTER: u64 = 0;
//! },
//!
//! // Both SYS_TICK and TIM2 have access to the `COUNTER` data
//! tasks: {
//! SYS_TICK: {
//! priority: 1,
//! // Both this task and TIM2 have access to the `COUNTER` resource
//! path: sys_tick,
//! resources: [COUNTER],
//! },
//!
//! // An interrupt as a task
//! TIM2: {
//! // For interrupts the `enabled` field must be specified. It
//! // indicates if the interrupt will be enabled or disabled once
//! // `idle` starts
//! enabled: true,
//! priority: 1,
//! path: tim2,
//! 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
//! 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.
//! // Thus both tasks have direct access to the resource
//! 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) {
//! // ..
//!
......
//! 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)]
//! #![feature(const_fn)]
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
......@@ -21,14 +19,15 @@
//! },
//!
//! tasks: {
//! // the task `SYS_TICK` has higher priority than `TIM2`
//! // The `SYS_TICK` task has higher priority than `TIM2`
//! SYS_TICK: {
//! path: sys_tick,
//! priority: 2,
//! resources: [COUNTER],
//! },
//!
//! TIM2: {
//! enabled: true,
//! path: tim2,
//! priority: 1,
//! resources: [COUNTER],
//! },
......@@ -45,27 +44,23 @@
//! }
//! }
//!
//! task!(SYS_TICK, sys_tick);
//!
//! 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
//! **r.COUNTER += 1;
//!
//! // ..
//! }
//!
//! task!(TIM2, tim2);
//!
//! 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
//! // 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; });
//!
//! // ..
......
......@@ -4,13 +4,11 @@
//! letters in the comments: A, then B, then C, etc.
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![feature(const_fn)]
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
......@@ -27,19 +25,19 @@
//!
//! tasks: {
//! EXTI0: {
//! enabled: true,
//! path: exti0,
//! priority: 1,
//! resources: [LOW, HIGH],
//! },
//!
//! EXTI1: {
//! enabled: true,
//! path: exti1,
//! priority: 2,
//! resources: [LOW],
//! },
//!
//! EXTI2: {
//! enabled: true,
//! path: exti2,
//! priority: 3,
//! resources: [HIGH],
//! },
......@@ -49,9 +47,12 @@
//! fn init(_p: init::Peripherals, _r: init::Resources) {}
//!
//! 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
//! rtfm::set_pending(Interrupt::EXTI0); // ~> exti0
//!
......@@ -60,72 +61,68 @@
//! }
//! }
//!
//! task!(EXTI0, exti0);
//!
//! 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 high = r.HIGH;
//!
//! // A
//! // B
//! 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
//!
//! // a claim creates a critical section
//! // A claim creates a critical section
//! low.claim_mut(t, |_low, t| {
//! // this claim increases the preemption threshold to 2
//! // just high enough to not race with task `exti1` for access to the
//! // This claim increases the preemption threshold to 2
//! //
//! // 2 is just high enough to not race with task `exti1` for access to the
//! // `LOW` resource
//!
//! // C
//! // D
//! 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
//! 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
//! rtfm::set_pending(Interrupt::EXTI2); // ~> exti2
//!
//! // E
//! // F
//! rtfm::bkpt();
//!
//! // claims can be nested
//! // Claims can be nested
//! high.claim_mut(t, |_high, _| {
//! // 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);
//!
//! // F
//! // G
//! rtfm::bkpt();
//! });
//!
//! // upon leaving the critical section the preemption threshold drops to 2
//! // and `exti2` immediately preempts this task
//! // Upon leaving the critical section the preemption threshold drops back
//! // to 2 and `exti2` immediately preempts this task
//! // ~> exti2
//! });
//!
//! // once again the preemption threshold drops to 1
//! // now the pending `exti1` can preempt this task
//! // Once again the preemption threshold drops but this time to 1. Now the
//! // pending `exti1` task can preempt this task
//! // ~> exti1
//! }
//!
//! task!(EXTI1, exti1);
//!
//! fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) {
//! // B, H
//! // C, I
//! rtfm::bkpt();
//! }
//!
//! task!(EXTI2, exti2);
//!
//! fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {
//! // D, G
//! // E, H
//! rtfm::bkpt();
//! }
//! ```
......
//! Working with resources in a generic fashion
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
......@@ -18,13 +16,13 @@
//!
//! tasks: {
//! EXTI0: {
//! enabled: true,
//! path: exti0,
//! priority: 1,
//! resources: [GPIOA, SPI1],
//! },
//!
//! EXTI1: {
//! enabled: true,
//! path: exti1,
//! priority: 2,
//! 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)
//! where
//! 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) {
//! 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) {
//! work(t, r.GPIOA, r.SPI1);
//! }
......
//! A showcase of the `app!` macro syntax
//!
//! ```
//!
//! #![deny(unsafe_code)]
//! #![feature(const_fn)]
//! #![feature(proc_macro)]
//! #![no_std]
//!
//! #[macro_use(task)]
//! extern crate cortex_m_rtfm as rtfm;
//! extern crate stm32f103xx;
//!
//! use rtfm::{app, Resource, Threshold};
//! use rtfm::{app, Threshold};
//!
//! app! {
//! device: stm32f103xx,
//!
//! resources: {
//! static CO_OWNED: u32 = 0;
//! static ON: bool = false;
//! static OWNED: bool = false;
//! static SHARED: bool = false;
//! },
//!
//! 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: {
//! locals: {
//! static COUNTER: u32 = 0;
//! },
//! 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],
//! },
//!
//! tasks: {
//! SYS_TICK: {
//! priority: 1,
//! resources: [CO_OWNED, SHARED],
//! path: sys_tick,
//! // If omitted priority is assumed to be 1
//! // priority: 1,
//! resources: [CO_OWNED, ON, SHARED],
//! },
//!
//! 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,
//! 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) -> ! {
//! loop {
//! *l.COUNTER += 1;
//! pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {}
//!
//! **r.OWNED != **r.OWNED;
//! pub fn idle(t: &mut Threshold, mut r: ::idle::Resources) -> ! {
//! loop {
//! *r.OWNED != *r.OWNED;
//!
//! if **r.OWNED {
//! if *r.OWNED {
//! if r.SHARED.claim(t, |shared, _| **shared) {
//! rtfm::wfi();
//! }
......@@ -65,19 +73,14 @@
//! }
//! }
//! }
//! }
//!
//! task!(SYS_TICK, sys_tick, Local {
//! static STATE: bool = true;
//! });
//!
//! fn sys_tick(_t: &mut Threshold, l: &mut Local, r: SYS_TICK::Resources) {
//! *l.STATE = !*l.STATE;
//! fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
//! **r.ON = !**r.ON;
//!
//! **r.CO_OWNED += 1;
//! }
//!
//! task!(TIM2, tim2);
//!
//! fn tim2(_t: &mut Threshold, r: TIM2::Resources) {
//! **r.CO_OWNED += 1;
//! }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment