From 7c504668dab4334baefefefd952044a28bc1f4c8 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Sat, 13 Jun 2020 01:21:22 +0200 Subject: [PATCH] wip3, examples lock3 and lock4 now express intended use, relation to Exclusive still not resolved --- Cargo.toml | 176 ++++++++++++++++++++----------------- examples/lock4.rs | 63 +++++++++++++ expand_lock.rs | 107 +++++++++++++++++++++- macros/src/codegen/util.rs | 2 +- src/lib.rs | 2 +- 5 files changed, 263 insertions(+), 87 deletions(-) create mode 100644 examples/lock4.rs diff --git a/Cargo.toml b/Cargo.toml index 8d966d273f..395501f10b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,111 +1,121 @@ +[[example]] +name = 'baseline' +required-features = ['__v7'] + +[[example]] +name = 'periodic' +required-features = ['__v7'] + +[[example]] +name = 'pool' +required-features = ['__v7'] + +[[example]] +name = 'schedule' +required-features = ['__v7'] + +[[example]] +name = 't-cfg' +required-features = ['__v7'] + +[[example]] +name = 't-cfg-resources' +required-features = ['__min_r1_43'] + +[[example]] +name = 't-schedule' +required-features = ['__v7'] + +[[example]] +name = 'types' +required-features = ['__v7'] + [package] authors = [ - "The Real-Time Interrupt-driven Concurrency developers", - "Jorge Aparicio ", - "Per Lindgren ", + 'The Real-Time Interrupt-driven Concurrency developers', + 'Jorge Aparicio ', + 'Per Lindgren ', ] -categories = ["concurrency", "embedded", "no-std"] -description = "Real-Time Interrupt-driven Concurrency (RTIC): a concurrency framework for building real time systems" -documentation = "https://rtic.rs/" -edition = "2018" -keywords = ["arm", "cortex-m"] -license = "MIT OR Apache-2.0" -name = "cortex-m-rtic" -readme = "README.md" -repository = "https://github.com/rtic-rs/cortex-m-rtic" -version = "0.5.3" +categories = [ + 'concurrency', + 'embedded', + 'no-std', +] +description = 'Real-Time Interrupt-driven Concurrency (RTIC): a concurrency framework for building real time systems' +documentation = 'https://rtic.rs/' +edition = '2018' +keywords = [ + 'arm', + 'cortex-m', +] +license = 'MIT OR Apache-2.0' +name = 'cortex-m-rtic' +readme = 'README.md' +repository = 'https://github.com/rtic-rs/cortex-m-rtic' +version = '0.5.3' [lib] -name = "rtic" - -[[example]] -name = "baseline" -required-features = ["__v7"] - -[[example]] -name = "periodic" -required-features = ["__v7"] - -[[example]] -name = "pool" -required-features = ["__v7"] - -[[example]] -name = "schedule" -required-features = ["__v7"] - -[[example]] -name = "t-cfg" -required-features = ["__v7"] - -[[example]] -name = "t-cfg-resources" -required-features = ["__min_r1_43"] - -[[example]] -name = "t-schedule" -required-features = ["__v7"] - -[[example]] -name = "types" -required-features = ["__v7"] +name = 'rtic' +[patch.crates-io.rtic-core] +git = 'https://github.com/rtic-rs/rtic-core.git' +branch = 'immutable_resource_proxies' [dependencies] -cortex-m = "0.6.2" -cortex-m-rtic-macros = { path = "macros", version = "0.5.0" } -rtic-core = "0.3.0" -cortex-m-rt = "0.6.9" -heapless = "0.5.0" +cortex-m = '0.6.2' +rtic-core = '0.3.0' +cortex-m-rt = '0.6.9' +heapless = '0.5.0' -[build-dependencies] -version_check = "0.9" +[dependencies.cortex-m-rtic-macros] +path = 'macros' +version = '0.5.0' [dependencies.microamp] optional = true -version = "0.1.0-alpha.2" +version = '0.1.0-alpha.2' + +[build-dependencies] +version_check = '0.9' [dev-dependencies] -lm3s6965 = "0.1.3" -panic-halt = "0.2.0" -cortex-m-semihosting = "0.3.3" +lm3s6965 = '0.1.3' +panic-halt = '0.2.0' +cortex-m-semihosting = '0.3.3' [dev-dependencies.panic-semihosting] -features = ["exit"] -version = "0.5.2" - +features = ['exit'] +version = '0.5.2' [target.x86_64-unknown-linux-gnu.dev-dependencies] -trybuild = "1" +trybuild = '1' [features] -heterogeneous = ["cortex-m-rtic-macros/heterogeneous", "microamp"] -homogeneous = ["cortex-m-rtic-macros/homogeneous"] -# used for testing this crate; do not use in applications -__v7 =[] -__min_r1_43 =[] - +heterogeneous = [ + 'cortex-m-rtic-macros/heterogeneous', + 'microamp', +] +homogeneous = ['cortex-m-rtic-macros/homogeneous'] +__v7 = [] +__min_r1_43 = [] [profile.release] codegen-units = 1 lto = true -[workspace] -members = [ - "heterogeneous", - "homogeneous", - "macros", -] - -# do not optimize proc-macro deps or build scripts -[profile.dev.build-override] -codegen-units = 16 -debug = false -debug-assertions = false -opt-level = 0 -overflow-checks = false - - [profile.release.build-override] codegen-units = 16 debug = false debug-assertions = false opt-level = 0 overflow-checks = false +[profile.dev.build-override] +codegen-units = 16 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[workspace] +members = [ + 'heterogeneous', + 'homogeneous', + 'macros', +] diff --git a/examples/lock4.rs b/examples/lock4.rs new file mode 100644 index 0000000000..cf4c181923 --- /dev/null +++ b/examples/lock4.rs @@ -0,0 +1,63 @@ +//! 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 _; + +#[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(); + + c.resources.shared.lock(|_shared| {}); + // 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) { + // the higher priority task does *not* need a critical section + *c.resources.shared += 1; + + hprintln!("D - shared = {}", *c.resources.shared).unwrap(); + } + + #[task(binds = GPIOC, priority = 3)] + fn gpioc(_: gpioc::Context) { + hprintln!("C").unwrap(); + } +}; diff --git a/expand_lock.rs b/expand_lock.rs index fe8c16eb18..23754a9788 100644 --- a/expand_lock.rs +++ b/expand_lock.rs @@ -75,8 +75,8 @@ pub mod init { } } mod resources { - use rtic::export::Priority; use core::cell::Cell; + use rtic::export::Priority; #[allow(non_camel_case_types)] pub struct shared<'a> { priority: &'a Priority, @@ -163,5 +163,108 @@ pub mod gpioc { } } } + /// Implementation details -const APP: () = { # [ doc = r" Always include the device crate which contains the vector table" ] use lm3s6965 as _ ; # [ allow ( non_upper_case_globals ) ] static mut shared : u32 = 0 ; impl < 'a > rtic :: Mutex for resources :: shared < 'a > { type T = u32 ; # [ inline ( always ) ] fn lock < R > ( & mut self , f : impl FnOnce ( & mut u32 ) -> R ) -> R { # [ doc = r" Priority ceiling" ] const CEILING : u8 = 2u8 ; if self . get_locked ( ) { :: core :: panicking :: panic ( "Resource locked in sequential context" ) ; } ; self . set_locked ( true ) ; let r = unsafe { rtic :: export :: lock ( & mut shared , self . priority ( ) , CEILING , lm3s6965 :: NVIC_PRIO_BITS , f ) } ; self . set_locked ( false ) ; r } } # [ allow ( non_snake_case ) ] # [ no_mangle ] unsafe fn GPIOA ( ) { const PRIORITY : u8 = 1u8 ; rtic :: export :: run ( PRIORITY , | | { crate :: gpioa ( gpioa :: Context :: new ( & rtic :: export :: Priority :: new ( PRIORITY ) ) ) } ) ; } impl < 'a > gpioaResources < 'a > { # [ inline ( always ) ] unsafe fn new ( priority : & 'a rtic :: export :: Priority ) -> Self { gpioaResources { shared : resources :: shared :: new ( priority ) , } } } # [ allow ( non_snake_case ) ] # [ no_mangle ] unsafe fn GPIOB ( ) { const PRIORITY : u8 = 2u8 ; rtic :: export :: run ( PRIORITY , | | { crate :: gpiob ( gpiob :: Context :: new ( & rtic :: export :: Priority :: new ( PRIORITY ) ) ) } ) ; } impl < 'a > gpiobResources < 'a > { # [ inline ( always ) ] unsafe fn new ( priority : & 'a rtic :: export :: Priority ) -> Self { gpiobResources { shared : & mut shared , } } } # [ allow ( non_snake_case ) ] # [ no_mangle ] unsafe fn GPIOC ( ) { const PRIORITY : u8 = 3u8 ; rtic :: export :: run ( PRIORITY , | | { crate :: gpioc ( gpioc :: Context :: new ( & rtic :: export :: Priority :: new ( PRIORITY ) ) ) } ) ; } # [ no_mangle ] unsafe extern "C" fn main ( ) -> ! { let _TODO : ( ) = ( ) ; rtic :: export :: interrupt :: disable ( ) ; let mut core : rtic :: export :: Peripherals = core :: mem :: transmute ( ( ) ) ; let _ = [ ( ) ; ( ( 1 << lm3s6965 :: NVIC_PRIO_BITS ) - 1u8 as usize ) ] ; core . NVIC . set_priority ( lm3s6965 :: Interrupt :: GPIOA , rtic :: export :: logical2hw ( 1u8 , lm3s6965 :: NVIC_PRIO_BITS ) ) ; rtic :: export :: NVIC :: unmask ( lm3s6965 :: Interrupt :: GPIOA ) ; let _ = [ ( ) ; ( ( 1 << lm3s6965 :: NVIC_PRIO_BITS ) - 2u8 as usize ) ] ; core . NVIC . set_priority ( lm3s6965 :: Interrupt :: GPIOB , rtic :: export :: logical2hw ( 2u8 , lm3s6965 :: NVIC_PRIO_BITS ) ) ; rtic :: export :: NVIC :: unmask ( lm3s6965 :: Interrupt :: GPIOB ) ; let _ = [ ( ) ; ( ( 1 << lm3s6965 :: NVIC_PRIO_BITS ) - 3u8 as usize ) ] ; core . NVIC . set_priority ( lm3s6965 :: Interrupt :: GPIOC , rtic :: export :: logical2hw ( 3u8 , lm3s6965 :: NVIC_PRIO_BITS ) ) ; rtic :: export :: NVIC :: unmask ( lm3s6965 :: Interrupt :: GPIOC ) ; core . SCB . scr . modify ( | r | r | 1 << 1 ) ; let late = crate :: init ( init :: Context :: new ( core . into ( ) ) ) ; rtic :: export :: interrupt :: enable ( ) ; loop { rtic :: export :: wfi ( ) } } }; +const APP: () = { + #[doc = r" Always include the device crate which contains the vector table"] + use lm3s6965 as _; + #[allow(non_upper_case_globals)] + static mut shared: u32 = 0; + impl<'a> rtic::Mutex for resources::shared<'a> { + type T = u32; + #[inline(always)] + fn lock(&self, f: impl FnOnce(&mut u32) -> R) -> R { + #[doc = r" Priority ceiling"] + const CEILING: u8 = 2u8; + if unsafe { self.get_locked() } { + ::core::panicking::panic("Resource locked in sequential context"); + }; + unsafe { + self.set_locked(true); + } + let r = unsafe { + rtic::export::lock( + &mut shared, + self.priority(), + CEILING, + lm3s6965::NVIC_PRIO_BITS, + f, + ) + }; + unsafe { + self.set_locked(false); + } + r + } + } + #[allow(non_snake_case)] + #[no_mangle] + unsafe fn GPIOA() { + const PRIORITY: u8 = 1u8; + rtic::export::run(PRIORITY, || { + crate::gpioa(gpioa::Context::new(&rtic::export::Priority::new(PRIORITY))) + }); + } + impl<'a> gpioaResources<'a> { + #[inline(always)] + unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + gpioaResources { + shared: resources::shared::new(priority), + } + } + } + #[allow(non_snake_case)] + #[no_mangle] + unsafe fn GPIOB() { + const PRIORITY: u8 = 2u8; + rtic::export::run(PRIORITY, || { + crate::gpiob(gpiob::Context::new(&rtic::export::Priority::new(PRIORITY))) + }); + } + impl<'a> gpiobResources<'a> { + #[inline(always)] + unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + gpiobResources { + shared: &mut shared, + } + } + } + #[allow(non_snake_case)] + #[no_mangle] + unsafe fn GPIOC() { + const PRIORITY: u8 = 3u8; + rtic::export::run(PRIORITY, || { + crate::gpioc(gpioc::Context::new(&rtic::export::Priority::new(PRIORITY))) + }); + } + #[no_mangle] + unsafe extern "C" fn main() -> ! { + let _TODO: () = (); + rtic::export::interrupt::disable(); + let mut core: rtic::export::Peripherals = core::mem::transmute(()); + let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 1u8 as usize)]; + core.NVIC.set_priority( + lm3s6965::Interrupt::GPIOA, + rtic::export::logical2hw(1u8, lm3s6965::NVIC_PRIO_BITS), + ); + rtic::export::NVIC::unmask(lm3s6965::Interrupt::GPIOA); + let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 2u8 as usize)]; + core.NVIC.set_priority( + lm3s6965::Interrupt::GPIOB, + rtic::export::logical2hw(2u8, lm3s6965::NVIC_PRIO_BITS), + ); + rtic::export::NVIC::unmask(lm3s6965::Interrupt::GPIOB); + let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 3u8 as usize)]; + core.NVIC.set_priority( + lm3s6965::Interrupt::GPIOC, + rtic::export::logical2hw(3u8, lm3s6965::NVIC_PRIO_BITS), + ); + rtic::export::NVIC::unmask(lm3s6965::Interrupt::GPIOC); + core.SCB.scr.modify(|r| r | 1 << 1); + let late = crate::init(init::Context::new(core.into())); + rtic::export::interrupt::enable(); + loop { + rtic::export::wfi() + } + } +}; diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index d8d05453fa..0d50b0ac5a 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -72,7 +72,7 @@ pub fn impl_mutex( impl<'a> rtic::Mutex for #path<'a> { type T = #ty; #[inline(always)] - fn lock(&mut self, f: impl FnOnce(&mut #ty) -> R) -> R { + fn lock(&self, f: impl FnOnce(&mut #ty) -> R) -> R { /// Priority ceiling const CEILING: u8 = #ceiling; diff --git a/src/lib.rs b/src/lib.rs index 5003653168..5705711c39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,7 +51,7 @@ use cortex_m::{ #[cfg(all(not(feature = "heterogeneous"), not(feature = "homogeneous")))] use cortex_m_rt as _; // vector table pub use cortex_m_rtic_macros::app; -pub use rtic_core::{Exclusive, Mutex}; +pub use rtic_core::Mutex; #[cfg(armv7m)] pub mod cyccnt;