diff --git a/examples/lock2.rs b/examples/lock2.rs new file mode 100644 index 0000000000..ab41cf8a74 --- /dev/null +++ b/examples/lock2.rs @@ -0,0 +1,40 @@ +//! examples/lock2.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::debug; +use lm3s6965::Interrupt; + +#[rtic::app(device = lm3s6965)] +const APP: () = { + struct Resources { + #[init(0)] + shared: u32, + #[init(0)] + shared2: u32, + } + + #[init] + fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); + } + + // when omitted priority is assumed to be `1` + #[task(binds = GPIOA, resources = [shared, shared2])] + fn gpioa(mut c: gpioa::Context) { + c.resources.shared.lock(|shared| { + *shared += 1; + rtic::pend(Interrupt::GPIOB); + }); + + debug::exit(debug::EXIT_SUCCESS); + } + + #[task(binds = GPIOB, priority = 2, resources = [shared, shared2])] + fn gpiob(c: gpiob::Context) { + *c.resources.shared += 1; + } +}; diff --git a/expand_lock.rs b/expand_lock.rs new file mode 100644 index 0000000000..2490cbe79b --- /dev/null +++ b/expand_lock.rs @@ -0,0 +1,114 @@ +#![feature(prelude_import)] +//! examples/lock2.rs +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] +#[prelude_import] +use core::prelude::v1::*; +#[macro_use] +extern crate core; +#[macro_use] +extern crate compiler_builtins; +use cortex_m_semihosting::debug; +use lm3s6965::Interrupt; +#[allow(non_snake_case)] +fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); +} +#[allow(non_snake_case)] +fn gpioa(mut c: gpioa::Context) { + use rtic::Mutex as _; + c.resources.shared.lock(|shared| { + *shared += 1; + rtic::pend(Interrupt::GPIOB); + }); + debug::exit(debug::EXIT_SUCCESS); +} +#[allow(non_snake_case)] +fn gpiob(c: gpiob::Context) { + use rtic::Mutex as _; + *c.resources.shared += 1; +} +#[allow(non_snake_case)] +///Initialization function +pub mod init { + /// Execution context + pub struct Context { + /// Core (Cortex-M) peripherals + pub core: rtic::export::Peripherals, + } + impl Context { + #[inline(always)] + pub unsafe fn new(core: rtic::export::Peripherals) -> Self { + Context { core } + } + } +} +mod resources { + use rtic::export::Priority; + #[allow(non_camel_case_types)] + pub struct shared<'a> { + priority: &'a Priority, + } + impl<'a> shared<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a Priority) -> Self { + shared { priority } + } + #[inline(always)] + pub unsafe fn priority(&self) -> &Priority { + self.priority + } + } +} +#[allow(non_snake_case)] +///Resources `gpioa` has access to +pub struct gpioaResources<'a> { + pub shared: resources::shared<'a>, +} +#[allow(non_snake_case)] +///Hardware task +pub mod gpioa { + #[doc(inline)] + pub use super::gpioaResources as Resources; + /// Execution context + pub struct Context<'a> { + /// Resources this task has access to + pub resources: Resources<'a>, + } + impl<'a> Context<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + Context { + resources: Resources::new(priority), + } + } + } +} +#[allow(non_snake_case)] +///Resources `gpiob` has access to +pub struct gpiobResources<'a> { + pub shared: &'a mut u32, +} +#[allow(non_snake_case)] +///Hardware task +pub mod gpiob { + #[doc(inline)] + pub use super::gpiobResources as Resources; + /// Execution context + pub struct Context<'a> { + /// Resources this task has access to + pub resources: Resources<'a>, + } + impl<'a> Context<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + Context { + resources: Resources::new(priority), + } + } + } +} +/// 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 ; unsafe { rtic :: export :: lock ( & mut shared , self . priority ( ) , CEILING , lm3s6965 :: NVIC_PRIO_BITS , f ) } } } # [ 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 , } } } # [ 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 ) ; 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/expand_lock2.rs b/expand_lock2.rs new file mode 100644 index 0000000000..43052a2312 --- /dev/null +++ b/expand_lock2.rs @@ -0,0 +1,153 @@ +#![feature(prelude_import)] +//! examples/lock2.rs +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] +#[prelude_import] +use core::prelude::v1::*; +#[macro_use] +extern crate core; +#[macro_use] +extern crate compiler_builtins; +use cortex_m_semihosting::debug; +use lm3s6965::Interrupt; +#[allow(non_snake_case)] +fn init(_: init::Context) { + rtic::pend(Interrupt::GPIOA); +} +#[allow(non_snake_case)] +fn gpioa(mut c: gpioa::Context) { + use rtic::Mutex as _; + c.resources.shared.lock(|shared| { + *shared += 1; + rtic::pend(Interrupt::GPIOB); + }); + debug::exit(debug::EXIT_SUCCESS); +} +#[allow(non_snake_case)] +fn gpiob(c: gpiob::Context) { + use rtic::Mutex as _; + *c.resources.shared += 1; +} +#[allow(non_snake_case)] +///Initialization function +pub mod init { + /// Execution context + pub struct Context { + /// Core (Cortex-M) peripherals + pub core: rtic::export::Peripherals, + } + impl Context { + #[inline(always)] + pub unsafe fn new(core: rtic::export::Peripherals) -> Self { + Context { core } + } + } +} +mod resources { + use rtic::export::Priority; + use core::cell::Cell; + #[allow(non_camel_case_types)] + pub struct shared<'a> { + priority: &'a Priority, + locked: Cell, + } + impl<'a> shared<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a Priority) -> Self { + shared { + priority, + locked: Cell::new(false), + } + } + #[inline(always)] + pub unsafe fn priority(&self) -> &Priority { + self.priority + } + #[inline(always)] + pub unsafe fn is_locked(&self) -> bool { + self.locked.get() + } + pub unsafe fn lock(&self) { + self.locked.set(true); + } + } + #[allow(non_camel_case_types)] + pub struct shared2<'a> { + priority: &'a Priority, + locked: Cell, + } + impl<'a> shared2<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a Priority) -> Self { + shared2 { + priority, + locked: Cell::new(false), + } + } + #[inline(always)] + pub unsafe fn priority(&self) -> &Priority { + self.priority + } + #[inline(always)] + pub unsafe fn is_locked(&self) -> bool { + self.locked.get() + } + pub unsafe fn lock(&self) { + self.locked.set(true); + } + } +} +#[allow(non_snake_case)] +///Resources `gpioa` has access to +pub struct gpioaResources<'a> { + pub shared: resources::shared<'a>, + pub shared2: resources::shared2<'a>, +} +#[allow(non_snake_case)] +///Hardware task +pub mod gpioa { + #[doc(inline)] + pub use super::gpioaResources as Resources; + /// Execution context + pub struct Context<'a> { + /// Resources this task has access to + pub resources: Resources<'a>, + } + impl<'a> Context<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + Context { + resources: Resources::new(priority), + } + } + } +} +#[allow(non_snake_case)] +///Resources `gpiob` has access to +pub struct gpiobResources<'a> { + pub shared: &'a mut u32, + pub shared2: &'a mut u32, +} +#[allow(non_snake_case)] +///Hardware task +pub mod gpiob { + #[doc(inline)] + pub use super::gpiobResources as Resources; + /// Execution context + pub struct Context<'a> { + /// Resources this task has access to + pub resources: Resources<'a>, + } + impl<'a> Context<'a> { + #[inline(always)] + pub unsafe fn new(priority: &'a rtic::export::Priority) -> Self { + Context { + resources: Resources::new(priority), + } + } + } +} +/// 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 ; unsafe { rtic :: export :: lock ( & mut shared , self . priority ( ) , CEILING , lm3s6965 :: NVIC_PRIO_BITS , f ) } } } # [ allow ( non_upper_case_globals ) ] static mut shared2 : u32 = 0 ; impl < 'a > rtic :: Mutex for resources :: shared2 < '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 ; unsafe { rtic :: export :: lock ( & mut shared2 , self . priority ( ) , CEILING , lm3s6965 :: NVIC_PRIO_BITS , f ) } } } # [ 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 ) , shared2 : resources :: shared2 :: 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 , shared2 : & mut shared2 , } } } # [ 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 ) ; 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/resources.rs b/macros/src/codegen/resources.rs index 0bec3e5ae6..6788648b39 100644 --- a/macros/src/codegen/resources.rs +++ b/macros/src/codegen/resources.rs @@ -83,6 +83,7 @@ pub fn codegen( #cfg_core pub struct #name<'a> { priority: &'a Priority, + locked: Cell, } #(#cfgs)* @@ -90,13 +91,25 @@ pub fn codegen( impl<'a> #name<'a> { #[inline(always)] pub unsafe fn new(priority: &'a Priority) -> Self { - #name { priority } + #name { + priority, + locked: Cell::new(false), + } } #[inline(always)] pub unsafe fn priority(&self) -> &Priority { self.priority } + + #[inline(always)] + pub unsafe fn is_locked(&self) -> bool { + self.locked.get() + } + + pub unsafe fn lock(&self) { + self.locked.set(true); + } } )); @@ -130,7 +143,7 @@ pub fn codegen( } else { quote!(mod resources { use rtic::export::Priority; - + use core::cell::Cell; #(#mod_resources)* }) };