From 2d4a960c8bff347bb821c7e6c9a13710b80e7259 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Mon, 15 Jun 2020 18:56:10 +0200 Subject: [PATCH] first attemtp to support Exclusive --- Cargo.toml | 2 ++ examples/lock5.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++ examples/lock6.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++ examples/lock7.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 252 insertions(+) create mode 100644 examples/lock5.rs create mode 100644 examples/lock6.rs create mode 100644 examples/lock7.rs diff --git a/Cargo.toml b/Cargo.toml index 395501f10b..8978f0068a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,8 @@ version = '0.5.3' [lib] name = 'rtic' + +# path = "../rtic-core" [patch.crates-io.rtic-core] git = 'https://github.com/rtic-rs/rtic-core.git' branch = 'immutable_resource_proxies' diff --git a/examples/lock5.rs b/examples/lock5.rs new file mode 100644 index 0000000000..365341911b --- /dev/null +++ b/examples/lock5.rs @@ -0,0 +1,83 @@ +//! examples/lock.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::{debug, hprintln}; +use lm3s6965::Interrupt; +use panic_semihosting as _; +use rtic::Mutex; +use rtic_core::Exclusive; + +#[rtic::app(device = lm3s6965)] +const APP: () = { + struct Resources { + #[init(0)] + shared: u32, + } + + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); + } + + // when omitted priority is assumed to be `1` + #[task(binds = GPIOA, resources = [shared])] + fn gpioa(c: gpioa::Context) { + hprintln!("A").unwrap(); + + // the lower priority task requires a critical section to access the data + c.resources.shared.lock(|shared| { + // data can only be modified within this critical section (closure) + *shared += 1; + + // GPIOB will *not* run right now due to the critical section + rtic::pend(Interrupt::GPIOB); + + hprintln!("B - shared = {}", *shared).unwrap(); + + // GPIOC does not contend for `shared` so it's allowed to run now + rtic::pend(Interrupt::GPIOC); + }); + + // critical section is over: GPIOB can now start + + hprintln!("E").unwrap(); + + debug::exit(debug::EXIT_SUCCESS); + } + + #[task(binds = GPIOB, priority = 2, resources = [shared])] + fn gpiob(c: gpiob::Context) { + c.resources.shared.lock(|shared| { + *shared += 1; + hprintln!("D - shared = {}", shared).unwrap(); + }); + } + + #[task(binds = GPIOC, priority = 3, resources = [shared])] + fn gpioc(c: gpioc::Context) { + static mut STATE: u32 = 0; + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + *c.resources.shared += 2; + let ex_shared = Exclusive(c.resources.shared); + advance(STATE, ex_shared); // try swap order of (1) + *c.resources.shared += 3; // and (2), will fail + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + } +}; + +// the second parameter is generic: it can be any type that implements the `Mutex` trait +fn advance(state: &mut u32, shared: impl Mutex) { + *state += 1; + + let (old, new) = shared.lock(|shared: &mut u32| { + let old = *shared; + *shared += *state; + (old, *shared) + }); + + hprintln!("shared: {} -> {}", old, new).unwrap(); +} diff --git a/examples/lock6.rs b/examples/lock6.rs new file mode 100644 index 0000000000..6cff0dd1a9 --- /dev/null +++ b/examples/lock6.rs @@ -0,0 +1,85 @@ +//! examples/lock.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::{debug, hprintln}; +use lm3s6965::Interrupt; +use panic_semihosting as _; +use rtic::Mutex; +use rtic_core::Exclusive; + +#[rtic::app(device = lm3s6965)] +const APP: () = { + struct Resources { + #[init(0)] + shared: u32, + } + + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); + } + + // when omitted priority is assumed to be `1` + #[task(binds = GPIOA, resources = [shared])] + fn gpioa(c: gpioa::Context) { + hprintln!("A").unwrap(); + + // the lower priority task requires a critical section to access the data + c.resources.shared.lock(|shared| { + // data can only be modified within this critical section (closure) + *shared += 1; + + // GPIOB will *not* run right now due to the critical section + rtic::pend(Interrupt::GPIOB); + + hprintln!("B - shared = {}", *shared).unwrap(); + + // GPIOC does not contend for `shared` so it's allowed to run now + rtic::pend(Interrupt::GPIOC); + }); + + // critical section is over: GPIOB can now start + + hprintln!("E").unwrap(); + + debug::exit(debug::EXIT_SUCCESS); + } + + #[task(binds = GPIOB, priority = 2, resources = [shared])] + fn gpiob(c: gpiob::Context) { + c.resources.shared.lock(|shared| { + *shared += 1; + hprintln!("D - shared = {}", shared).unwrap(); + }); + } + + #[task(binds = GPIOC, priority = 3, resources = [shared])] + fn gpioc(c: gpioc::Context) { + static mut STATE: u32 = 0; + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + *c.resources.shared += 2; + let mut ex_shared = Exclusive(c.resources.shared); + // a mutable exclusive is still possible to DerefMut + *ex_shared += 1; + advance(STATE, ex_shared); // try swap order of (1) + *c.resources.shared += 3; // and (2), will fail + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + } +}; + +// the second parameter is generic: it can be any type that implements the `Mutex` trait +fn advance(state: &mut u32, shared: impl Mutex) { + *state += 1; + + let (old, new) = shared.lock(|shared: &mut u32| { + let old = *shared; + *shared += *state; + (old, *shared) + }); + + hprintln!("shared: {} -> {}", old, new).unwrap(); +} diff --git a/examples/lock7.rs b/examples/lock7.rs new file mode 100644 index 0000000000..cdb950b85b --- /dev/null +++ b/examples/lock7.rs @@ -0,0 +1,82 @@ +//! examples/lock.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::{debug, hprintln}; +use lm3s6965::Interrupt; +use panic_semihosting as _; +use rtic::Mutex; +use rtic_core::Exclusive; + +#[rtic::app(device = lm3s6965)] +const APP: () = { + struct Resources { + #[init(0)] + shared: u32, + } + + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); + } + + // when omitted priority is assumed to be `1` + #[task(binds = GPIOA, resources = [shared])] + fn gpioa(c: gpioa::Context) { + hprintln!("A").unwrap(); + + // the lower priority task requires a critical section to access the data + c.resources.shared.lock(|shared| { + // data can only be modified within this critical section (closure) + *shared += 1; + + // GPIOB will *not* run right now due to the critical section + rtic::pend(Interrupt::GPIOB); + + hprintln!("B - shared = {}", *shared).unwrap(); + + // GPIOC does not contend for `shared` so it's allowed to run now + rtic::pend(Interrupt::GPIOC); + }); + + // critical section is over: GPIOB can now start + + hprintln!("E").unwrap(); + + debug::exit(debug::EXIT_SUCCESS); + } + + #[task(binds = GPIOB, priority = 2, resources = [shared])] + fn gpiob(c: gpiob::Context) { + c.resources.shared.lock(|shared| { + *shared += 1; + hprintln!("D - shared = {}", shared).unwrap(); + }); + } + + #[task(binds = GPIOC, priority = 3, resources = [shared])] + fn gpioc(c: gpioc::Context) { + static mut STATE: u32 = 0; + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + *c.resources.shared += 2; + advance(STATE, *c.resources.shared); // try swap order of (1) + *c.resources.shared += 3; // and (2), will fail + hprintln!("GPIOC(STATE = {})", *STATE).unwrap(); + } +}; + +// the second parameter is generic: it can be any type that implements the `Mutex` trait +fn advance(state: &mut u32, shared: impl Mutex) { + *state += 1; + + let (old, new) = shared.lock(|shared: &mut u32| { + let old = *shared; + *shared += *state; + (old, *shared) + }); + + hprintln!("shared: {} -> {}", old, new).unwrap(); +}