diff options
author | 2017-07-27 22:40:47 -0500 | |
---|---|---|
committer | 2017-07-27 22:40:47 -0500 | |
commit | e85d6e53c89cd1ea1da8826778c5a74154fb651d (patch) | |
tree | 76fbc30063df22724b9b160c85055e1d294513b0 /src | |
parent | 271df39bdba0690ea7ba77a6ff5d8d7edb9b8036 (diff) | |
download | rtic-e85d6e53c89cd1ea1da8826778c5a74154fb651d.tar.gz rtic-e85d6e53c89cd1ea1da8826778c5a74154fb651d.tar.zst rtic-e85d6e53c89cd1ea1da8826778c5a74154fb651d.zip |
update examples
Diffstat (limited to 'src')
-rw-r--r-- | src/examples/_0_zero_tasks.rs | 14 | ||||
-rw-r--r-- | src/examples/_1_one_task.rs | 58 | ||||
-rw-r--r-- | src/examples/_2_two_tasks.rs | 23 | ||||
-rw-r--r-- | src/examples/_3_preemption.rs | 19 | ||||
-rw-r--r-- | src/examples/_4_nested.rs | 61 | ||||
-rw-r--r-- | src/examples/_5_generics.rs | 16 | ||||
-rw-r--r-- | src/examples/_6_full_syntax.rs | 61 |
7 files changed, 114 insertions, 138 deletions
diff --git a/src/examples/_0_zero_tasks.rs b/src/examples/_0_zero_tasks.rs index 15231818..7ea08597 100644 --- a/src/examples/_0_zero_tasks.rs +++ b/src/examples/_0_zero_tasks.rs @@ -1,9 +1,9 @@ //! 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(); diff --git a/src/examples/_1_one_task.rs b/src/examples/_1_one_task.rs index 33e8bf7f..1bccc219 100644 --- a/src/examples/_1_one_task.rs +++ b/src/examples/_1_one_task.rs @@ -1,14 +1,12 @@ //! 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 { diff --git a/src/examples/_2_two_tasks.rs b/src/examples/_2_two_tasks.rs index 9eb61b18..451293cf 100644 --- a/src/examples/_2_two_tasks.rs +++ b/src/examples/_2_two_tasks.rs @@ -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)] //! #![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) { //! // .. //! diff --git a/src/examples/_3_preemption.rs b/src/examples/_3_preemption.rs index b93ec086..1f6b244b 100644 --- a/src/examples/_3_preemption.rs +++ b/src/examples/_3_preemption.rs @@ -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)] //! #![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; }); //! //! // .. diff --git a/src/examples/_4_nested.rs b/src/examples/_4_nested.rs index 6be68d8e..d0306210 100644 --- a/src/examples/_4_nested.rs +++ b/src/examples/_4_nested.rs @@ -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(); //! } //! ``` diff --git a/src/examples/_5_generics.rs b/src/examples/_5_generics.rs index a8f42cdf..82ecdf99 100644 --- a/src/examples/_5_generics.rs +++ b/src/examples/_5_generics.rs @@ -1,12 +1,10 @@ //! 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); //! } diff --git a/src/examples/_6_full_syntax.rs b/src/examples/_6_full_syntax.rs index 9e932436..449bee6c 100644 --- a/src/examples/_6_full_syntax.rs +++ b/src/examples/_6_full_syntax.rs @@ -1,83 +1,86 @@ //! 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.SHARED.claim(t, |shared, _| **shared) { -//! rtfm::wfi(); +//! if *r.OWNED { +//! if r.SHARED.claim(t, |shared, _| **shared) { +//! rtfm::wfi(); +//! } +//! } else { +//! r.SHARED.claim_mut(t, |shared, _| **shared = !**shared); //! } -//! } else { -//! r.SHARED.claim_mut(t, |shared, _| **shared = !**shared); //! } //! } //! } //! -//! 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; //! } |