diff options
| author | Jorge Aparicio <jorge@japaric.io> | 2017-07-27 22:40:47 -0500 |
|---|---|---|
| committer | Jorge Aparicio <jorge@japaric.io> | 2017-07-27 22:40:47 -0500 |
| commit | e85d6e53c89cd1ea1da8826778c5a74154fb651d (patch) | |
| tree | 76fbc30063df22724b9b160c85055e1d294513b0 /examples | |
| parent | 271df39bdba0690ea7ba77a6ff5d8d7edb9b8036 (diff) | |
update examples
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/full-syntax.rs | 40 | ||||
| -rw-r--r-- | examples/generics.rs | 7 | ||||
| -rw-r--r-- | examples/modules.rs | 76 | ||||
| -rw-r--r-- | examples/nested.rs | 48 | ||||
| -rw-r--r-- | examples/one-task.rs | 30 | ||||
| -rw-r--r-- | examples/preemption.rs | 10 | ||||
| -rw-r--r-- | examples/two-tasks.rs | 15 | ||||
| -rw-r--r-- | examples/zero-tasks.rs | 14 |
8 files changed, 84 insertions, 156 deletions
diff --git a/examples/full-syntax.rs b/examples/full-syntax.rs index 184349b..20e8dfb 100644 --- a/examples/full-syntax.rs +++ b/examples/full-syntax.rs @@ -1,5 +1,4 @@ //! 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,18 +53,22 @@ app! { }, } -fn init_(_p: init::Peripherals, _r: init::Resources) {} +mod main { + use rtfm::{self, Resource, Threshold}; + + pub fn init(_p: ::init::Peripherals, _r: ::init::Resources) {} -fn idle_(t: &mut Threshold, mut r: idle::Resources) -> ! { - loop { - *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); } } } diff --git a/examples/generics.rs b/examples/generics.rs index 6c6e1d6..57c9b8e 100644 --- a/examples/generics.rs +++ b/examples/generics.rs @@ -1,5 +1,4 @@ //! 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); } diff --git a/examples/modules.rs b/examples/modules.rs deleted file mode 100644 index 6bdf8d9..0000000 --- a/examples/modules.rs +++ /dev/null @@ -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; - } -} diff --git a/examples/nested.rs b/examples/nested.rs index 92f90cb..7013170 100644 --- a/examples/nested.rs +++ b/examples/nested.rs @@ -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(); } diff --git a/examples/one-task.rs b/examples/one-task.rs index e1d598d..556177d 100644 --- a/examples/one-task.rs +++ b/examples/one-task.rs @@ -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; diff --git a/examples/preemption.rs b/examples/preemption.rs index 057e4fd..256b9bd 100644 --- a/examples/preemption.rs +++ b/examples/preemption.rs @@ -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)] #![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; }); // .. diff --git a/examples/two-tasks.rs b/examples/two-tasks.rs index 42b91e4..ea059a0 100644 --- a/examples/two-tasks.rs +++ b/examples/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 #![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) { // .. diff --git a/examples/zero-tasks.rs b/examples/zero-tasks.rs index 1320167..9176103 100644 --- a/examples/zero-tasks.rs +++ b/examples/zero-tasks.rs @@ -1,7 +1,7 @@ //! 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(); |
