diff --git a/.gitignore b/.gitignore index 8bc31d43a2..29204d6567 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ **/*.rs.bk *.org +.#* .gdb_history Cargo.lock target/ diff --git a/Cargo.toml b/Cargo.toml index 37db8565e5..05f90ab000 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,13 @@ version = "0.3.0" [dependencies] cortex-m = { git = "https://github.com/japaric/cortex-m" } untagged-option = "0.1.1" -rtfm-core = "0.1.0" +# rtfm-core = "0.2.0" +rtfm-core = { git = "https://github.com/japaric/rtfm-core" } cortex-m-rtfm-macros = { path = "macros" } [target.'cfg(target_arch = "x86_64")'.dev-dependencies] -compiletest_rs = "0.3.3" +# compiletest_rs = "0.3.4" +compiletest_rs = { git = "https://github.com/dwrensha/compiletest-rs", branch = "rustup" } [dev-dependencies.cortex-m-rt] features = ["abort-on-panic"] diff --git a/examples/custom-type.rs b/examples/custom-type.rs new file mode 100644 index 0000000000..79d6cc461c --- /dev/null +++ b/examples/custom-type.rs @@ -0,0 +1,50 @@ +#![deny(unsafe_code)] +#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m_rtfm as rtfm; +extern crate stm32f103xx; + +use rtfm::{app, Threshold}; + +pub struct Foo; + +app! { + device: stm32f103xx, + + resources: { + static CO_OWNED: Foo = Foo; + static ON: Foo = Foo; + static OWNED: Foo = Foo; + static SHARED: Foo = Foo; + }, + + idle: { + resources: [OWNED, SHARED], + }, + + tasks: { + SYS_TICK: { + path: sys_tick, + resources: [CO_OWNED, ON, SHARED], + }, + + TIM2: { + enabled: false, + path: tim2, + priority: 1, + resources: [CO_OWNED], + }, + }, +} + +fn init(_p: ::init::Peripherals, _r: ::init::Resources) {} + +fn idle(_t: &mut Threshold, _r: ::idle::Resources) -> ! { + loop {} +} + +fn sys_tick(_t: &mut Threshold, _r: SYS_TICK::Resources) {} + +fn tim2(_t: &mut Threshold, _r: TIM2::Resources) {} diff --git a/examples/full-syntax.rs b/examples/full-syntax.rs index a8f79a7210..5b27412265 100644 --- a/examples/full-syntax.rs +++ b/examples/full-syntax.rs @@ -63,22 +63,22 @@ mod main { *r.OWNED != *r.OWNED; if *r.OWNED { - if r.SHARED.claim(t, |shared, _| **shared) { + if r.SHARED.claim(t, |shared, _| *shared) { rtfm::wfi(); } } else { - r.SHARED.claim_mut(t, |shared, _| **shared = !**shared); + r.SHARED.claim_mut(t, |shared, _| *shared = !*shared); } } } } -fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) { - **r.ON = !**r.ON; +fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) { + *r.ON = !*r.ON; - **r.CO_OWNED += 1; + *r.CO_OWNED += 1; } -fn tim2(_t: &mut Threshold, r: TIM2::Resources) { - **r.CO_OWNED += 1; +fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) { + *r.CO_OWNED += 1; } diff --git a/examples/generics.rs b/examples/generics.rs index 7cf9257b32..ca7726d0b7 100644 --- a/examples/generics.rs +++ b/examples/generics.rs @@ -70,5 +70,5 @@ fn exti0(t: &mut Threshold, r: EXTI0::Resources) { // This task has direct access to the resources fn exti1(t: &mut Threshold, r: EXTI1::Resources) { - work(t, r.GPIOA, r.SPI1); + work(t, &r.GPIOA, &r.SPI1); } diff --git a/examples/late-resources.rs b/examples/late-resources.rs index d42431c28a..07c321f673 100644 --- a/examples/late-resources.rs +++ b/examples/late-resources.rs @@ -1,5 +1,4 @@ //! Demonstrates initialization of resources in `init`. - #![deny(unsafe_code)] #![deny(warnings)] #![feature(proc_macro)] diff --git a/examples/one-task.rs b/examples/one-task.rs index 2e77676891..07def59ba7 100644 --- a/examples/one-task.rs +++ b/examples/one-task.rs @@ -77,11 +77,11 @@ fn idle() -> ! { // `r` is the set of resources this task has access to. `SYS_TICK::Resources` // has one field per resource declared in `app!`. #[allow(unsafe_code)] -fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) { +fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) { // toggle state - **r.ON = !**r.ON; + *r.ON = !*r.ON; - if **r.ON { + if *r.ON { // set the pin PC13 high // NOTE(unsafe) atomic write to a stateless register unsafe { diff --git a/examples/preemption.rs b/examples/preemption.rs index 98dde8d1f3..8e501887c3 100644 --- a/examples/preemption.rs +++ b/examples/preemption.rs @@ -42,12 +42,12 @@ fn idle() -> ! { } } -fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) { +fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) { // .. // This task can't be preempted by `tim2` so it has direct access to the // resource data - **r.COUNTER += 1; + *r.COUNTER += 1; // .. } @@ -61,7 +61,7 @@ fn tim2(t: &mut Threshold, mut r: TIM2::Resources) { // lead to undefined behavior. r.COUNTER.claim_mut(t, |counter, _t| { // `claim_mut` creates a critical section - **counter += 1; + *counter += 1; }); // .. diff --git a/examples/safe-static-mut-ref.rs b/examples/safe-static-mut-ref.rs new file mode 100644 index 0000000000..bb87212281 --- /dev/null +++ b/examples/safe-static-mut-ref.rs @@ -0,0 +1,32 @@ +//! Safe creation of `&'static mut` references +#![deny(unsafe_code)] +#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m_rtfm as rtfm; +extern crate stm32f103xx; + +use rtfm::app; + +app! { + device: stm32f103xx, + + resources: { + static BUFFER: [u8; 16] = [0; 16]; + }, + + init: { + resources: [BUFFER], + }, +} + +fn init(_p: init::Peripherals, r: init::Resources) { + let _buf: &'static mut [u8] = r.BUFFER; +} + +fn idle() -> ! { + loop { + rtfm::wfi(); + } +} diff --git a/examples/two-tasks.rs b/examples/two-tasks.rs index df6e784a97..4f567f0cea 100644 --- a/examples/two-tasks.rs +++ b/examples/two-tasks.rs @@ -42,18 +42,18 @@ fn idle() -> ! { // 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) { +fn sys_tick(_t: &mut Threshold, mut r: SYS_TICK::Resources) { // .. - **r.COUNTER += 1; + *r.COUNTER += 1; // .. } -fn tim2(_t: &mut Threshold, r: TIM2::Resources) { +fn tim2(_t: &mut Threshold, mut r: TIM2::Resources) { // .. - **r.COUNTER += 1; + *r.COUNTER += 1; // .. } diff --git a/macros/Cargo.toml b/macros/Cargo.toml index d51cbc2629..27bd1f56a1 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -12,7 +12,8 @@ version = "0.2.1" [dependencies] error-chain = "0.10.0" quote = "0.3.15" -rtfm-syntax = "0.2.0" +# rtfm-syntax = "0.2.0" +rtfm-syntax = { git = "https://github.com/japaric/rtfm-syntax" } syn = "0.11.11" [lib] diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 0fc125daba..65d98e6960 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -17,6 +17,13 @@ pub enum Ownership { } impl Ownership { + pub fn ceiling(&self) -> u8 { + match *self { + Ownership::Owned { priority } => priority, + Ownership::Shared { ceiling } => ceiling, + } + } + pub fn is_owned(&self) -> bool { match *self { Ownership::Owned { .. } => true, diff --git a/macros/src/check.rs b/macros/src/check.rs index 63cac1fa5e..f6fd9cc609 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -77,7 +77,38 @@ pub fn app(app: check::App) -> Result { } fn resources(app: &App) -> Result<()> { + for name in &app.init.resources { + if let Some(resource) = app.resources.get(name) { + ensure!( + resource.expr.is_some(), + "resource `{}`, allocated to `init`, must have an initial value", + name + ); + } else { + bail!( + "resource `{}`, allocated to `init`, must be a data resource", + name + ); + } + + ensure!( + !app.idle.resources.contains(name), + "resources assigned to `init` can't be shared with `idle`" + ); + + ensure!( + app.tasks + .iter() + .all(|(_, task)| !task.resources.contains(name)), + "resources assigned to `init` can't be shared with tasks" + ) + } + for resource in app.resources.keys() { + if app.init.resources.contains(resource) { + continue; + } + if app.idle.resources.contains(resource) { continue; } diff --git a/macros/src/trans.rs b/macros/src/trans.rs index 9bf1e2a9dc..b50c73df29 100644 --- a/macros/src/trans.rs +++ b/macros/src/trans.rs @@ -1,7 +1,7 @@ use quote::{Ident, Tokens}; use syn::{Lit, StrStyle}; -use analyze::{Ownership, Ownerships}; +use analyze::Ownerships; use check::{App, Kind}; fn krate() -> Ident { @@ -81,11 +81,11 @@ fn idle(app: &App, ownerships: &Ownerships, main: &mut Vec, root: &mut V }); } else { rfields.push(quote! { - pub #name: #super_::_resource::#name, + pub #name: ::idle::#name, }); rexprs.push(quote! { - #name: #super_::_resource::#name::new(), + #name: ::idle::#name { _0: core::marker::PhantomData }, }); } } @@ -126,6 +126,85 @@ fn idle(app: &App, ownerships: &Ownerships, main: &mut Vec, root: &mut V exprs.push(quote!(unsafe { idle::Resources::new() })); } + let device = &app.device; + for name in &app.idle.resources { + let ceiling = ownerships[name].ceiling(); + + // owned resource + if ceiling == 0 { + continue + } + + let _name = Ident::new(format!("_{}", name.as_ref())); + let resource = app.resources + .get(name) + .expect(&format!("BUG: resource {} has no definition", name)); + + let ty = &resource.ty; + let _static = if resource.expr.is_some() { + quote!(#_name) + } else { + quote!(#_name.some) + }; + + mod_items.push(quote! { + #[allow(non_camel_case_types)] + pub struct #name { _0: core::marker::PhantomData<*const ()> } + }); + + root.push(quote! { + #[allow(unsafe_code)] + unsafe impl #krate::Resource for idle::#name { + type Data = #ty; + + fn borrow<'cs>(&'cs self, t: &'cs Threshold) -> &'cs Self::Data { + assert!(t.value() >= #ceiling); + + unsafe { &#_static } + } + + fn borrow_mut<'cs>( + &'cs mut self, + t: &'cs Threshold, + ) -> &'cs mut Self::Data { + assert!(t.value() >= #ceiling); + + unsafe { &mut #_static } + } + + fn claim(&self, t: &mut Threshold, f: F) -> R + where + F: FnOnce(&Self::Data, &mut Threshold) -> R + { + unsafe { + #krate::claim( + &#_static, + #ceiling, + #device::NVIC_PRIO_BITS, + t, + f, + ) + } + } + + fn claim_mut(&mut self, t: &mut Threshold, f: F) -> R + where + F: FnOnce(&mut Self::Data, &mut Threshold) -> R + { + unsafe { + #krate::claim( + &mut #_static, + #ceiling, + #device::NVIC_PRIO_BITS, + t, + f, + ) + } + } + } + }); + } + if !mod_items.is_empty() { root.push(quote! { #[allow(unsafe_code)] @@ -170,18 +249,30 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { let mut rexprs = vec![]; for (name, resource) in init_resources { - let _name = Ident::new(format!("_{}", name.as_ref())); - lifetime = Some(quote!('a)); - let ty = &resource.ty; - fields.push(quote! { - pub #name: &'a mut #krate::Static<#ty>, - }); + if app.init.resources.contains(name) { + fields.push(quote! { + pub #name: &'static mut #ty, + }); - rexprs.push(quote! { - #name: ::#krate::Static::ref_mut(&mut ::#_name), - }); + let expr = &resource.expr; + rexprs.push(quote!(#name: { + static mut #name: #ty = #expr; + &mut #name + },)); + } else { + let _name = Ident::new(format!("_{}", name.as_ref())); + lifetime = Some(quote!('a)); + + fields.push(quote! { + pub #name: &'a mut #ty, + }); + + rexprs.push(quote! { + #name: &mut ::#_name, + }); + } } root.push(quote! { @@ -323,234 +414,153 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { fn resources(app: &App, ownerships: &Ownerships, root: &mut Vec) { let krate = krate(); - let device = &app.device; - let mut items = vec![]; - let mut impls = vec![]; - for (name, ownership) in ownerships { + for name in ownerships.keys() { let _name = Ident::new(format!("_{}", name.as_ref())); - if let Some(resource) = app.resources.get(name) { - // Declare the static that holds the resource - let expr = &resource.expr; - let ty = &resource.ty; + // Declare the static that holds the resource + let resource = app.resources + .get(name) + .expect(&format!("BUG: resource {} has no definition", name)); - root.push(match *expr { - Some(ref expr) => quote! { - static mut #_name: #ty = #expr; - }, - None => quote! { - // Resource initialized in `init` - static mut #_name: #krate::UntaggedOption<#ty> = #krate::UntaggedOption { none: () }; - }, - }); - } + let expr = &resource.expr; + let ty = &resource.ty; - let mut impl_items = vec![]; - - match *ownership { - Ownership::Owned { .. } => { - // For owned resources we don't need claim() or borrow() - } - Ownership::Shared { ceiling } => { - let resource = app.resources - .get(name) - .expect(&format!("BUG: resource {} has no definition", name)); - let ty = &resource.ty; - let res_rvalue = if resource.expr.is_some() { - quote!(#_name) - } else { - quote!(#_name.some) - }; - - impl_items.push(quote! { - type Data = #ty; - - fn borrow<'cs>( - &'cs self, - t: &'cs #krate::Threshold, - ) -> &'cs #krate::Static<#ty> { - assert!(t.value() >= #ceiling); - - unsafe { #krate::Static::ref_(&#res_rvalue) } - } - - fn borrow_mut<'cs>( - &'cs mut self, - t: &'cs #krate::Threshold, - ) -> &'cs mut #krate::Static<#ty> { - assert!(t.value() >= #ceiling); - - unsafe { - #krate::Static::ref_mut(&mut #res_rvalue) - } - } - - fn claim( - &self, - t: &mut #krate::Threshold, - f: F, - ) -> R - where - F: FnOnce( - &#krate::Static<#ty>, - &mut #krate::Threshold) -> R - { - unsafe { - #krate::claim( - #krate::Static::ref_(&#res_rvalue), - #ceiling, - #device::NVIC_PRIO_BITS, - t, - f, - ) - } - } - - fn claim_mut( - &mut self, - t: &mut #krate::Threshold, - f: F, - ) -> R - where - F: FnOnce( - &mut #krate::Static<#ty>, - &mut #krate::Threshold) -> R - { - unsafe { - #krate::claim( - #krate::Static::ref_mut(&mut #res_rvalue), - #ceiling, - #device::NVIC_PRIO_BITS, - t, - f, - ) - } - } - }); - - impls.push(quote! { - #[allow(unsafe_code)] - unsafe impl #krate::Resource for _resource::#name { - #(#impl_items)* - } - }); - - items.push(quote! { - #[allow(non_camel_case_types)] - pub struct #name { _0: PhantomData<*const ()> } - - #[allow(unsafe_code)] - impl #name { - pub unsafe fn new() -> Self { - #name { _0: PhantomData } - } - } - }); - } - } + root.push(match *expr { + Some(ref expr) => quote! { + static mut #_name: #ty = #expr; + }, + None => quote! { + // Resource initialized in `init` + static mut #_name: #krate::UntaggedOption<#ty> = + #krate::UntaggedOption { none: () }; + }, + }); } - - if !items.is_empty() { - root.push(quote! { - #[allow(unsafe_code)] - mod _resource { - use core::marker::PhantomData; - - #(#items)* - } - }) - } - root.push(quote! { - #(#impls)* - }); } fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec) { let device = &app.device; let krate = krate(); - for (name, task) in &app.tasks { + for (tname, task) in &app.tasks { let mut exprs = vec![]; let mut fields = vec![]; let mut items = vec![]; - let mut lifetime = None; - let mut needs_reexport = false; - let mut needs_threshold = false; let has_resources = !task.resources.is_empty(); if has_resources { - needs_threshold = !task.resources.is_empty(); + for rname in &task.resources { + let ceiling = ownerships[rname].ceiling(); + let _rname = Ident::new(format!("_{}", rname.as_ref())); + let resource = app.resources + .get(rname) + .expect(&format!("BUG: resource {} has no definition", rname)); - for name in &task.resources { - let _name = Ident::new(format!("_{}", name.as_ref())); + let ty = &resource.ty; + let _static = if resource.expr.is_some() { + quote!(#_rname) + } else { + quote!(#_rname.some) + }; - match ownerships[name] { - Ownership::Shared { ceiling } if ceiling > task.priority => { - needs_threshold = true; - - fields.push(quote! { - pub #name: ::_resource::#name, - }); - - exprs.push(quote! { - #name: { - ::_resource::#name::new() - }, - }); - } - _ => { - lifetime = Some(quote!('a)); - let resource = app.resources - .get(name) - .expect(&format!("BUG: resource {} has no definition", name)); - - needs_reexport = true; - let ty = &resource.ty; - - fields.push(quote! { - pub #name: &'a mut ::#krate::Static<#ty>, - }); - - exprs.push(if resource.expr.is_some() { - quote! { - #name: ::#krate::Static::ref_mut(&mut ::#_name), - } - } else { - quote! { - #name: ::#krate::Static::ref_mut(::#_name.as_mut()), - } - }); - } - } - } - - if needs_reexport { - let rname = Ident::new(format!("_{}Resources", name)); - root.push(quote! { + items.push(quote! { #[allow(non_camel_case_types)] - #[allow(non_snake_case)] - pub struct #rname<#lifetime> { - #(#fields)* + pub struct #rname { _0: PhantomData<*const ()> } + }); + + root.push(quote! { + #[allow(unsafe_code)] + unsafe impl #krate::Resource for #tname::#rname { + type Data = #ty; + + fn borrow<'cs>(&'cs self, t: &'cs Threshold) -> &'cs Self::Data { + assert!(t.value() >= #ceiling); + + unsafe { &#_static } + } + + fn borrow_mut<'cs>( + &'cs mut self, + t: &'cs Threshold, + ) -> &'cs mut Self::Data { + assert!(t.value() >= #ceiling); + + unsafe { &mut #_static } + } + + fn claim(&self, t: &mut Threshold, f: F) -> R + where + F: FnOnce(&Self::Data, &mut Threshold) -> R + { + unsafe { + #krate::claim( + &#_static, + #ceiling, + #device::NVIC_PRIO_BITS, + t, + f, + ) + } + } + + fn claim_mut(&mut self, t: &mut Threshold, f: F) -> R + where + F: FnOnce(&mut Self::Data, &mut Threshold) -> R + { + unsafe { + #krate::claim( + &mut #_static, + #ceiling, + #device::NVIC_PRIO_BITS, + t, + f, + ) + } + } } }); - items.push(quote! { - pub use ::#rname as Resources; + if ceiling <= task.priority { + root.push(quote! { + #[allow(unsafe_code)] + impl core::ops::Deref for #tname::#rname { + type Target = #ty; + + fn deref(&self) -> &Self::Target { + unsafe { &#_static } + } + } + + #[allow(unsafe_code)] + impl core::ops::DerefMut for #tname::#rname { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut #_static } + } + } + }) + } + + fields.push(quote! { + pub #rname: #rname, }); - } else { - items.push(quote! { - #[allow(non_snake_case)] - pub struct Resources<#lifetime> { - #(#fields)* - } + + exprs.push(quote! { + #rname: #rname { _0: PhantomData }, }); } + items.push(quote! { + #[allow(non_snake_case)] + pub struct Resources { + #(#fields)* + } + }); + items.push(quote! { #[allow(unsafe_code)] - impl<#lifetime> Resources<#lifetime> { + impl Resources { pub unsafe fn new() -> Self { Resources { #(#exprs)* @@ -564,7 +574,7 @@ fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec) { let mut exprs = vec![]; let priority = task.priority; - if needs_threshold { + if has_resources { tys.push(quote!(&mut #krate::Threshold)); exprs.push(quote! { &mut if #priority == 1 << #device::NVIC_PRIO_BITS { @@ -576,18 +586,18 @@ fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec) { } if has_resources { - tys.push(quote!(#name::Resources)); - exprs.push(quote!(#name::Resources::new())); + tys.push(quote!(#tname::Resources)); + exprs.push(quote!(#tname::Resources::new())); } let path = &task.path; - let _name = Ident::new(format!("_{}", name)); - let export_name = Lit::Str(name.as_ref().to_owned(), StrStyle::Cooked); + let _tname = Ident::new(format!("_{}", tname)); + let export_name = Lit::Str(tname.as_ref().to_owned(), StrStyle::Cooked); root.push(quote! { #[allow(non_snake_case)] #[allow(unsafe_code)] #[export_name = #export_name] - pub unsafe extern "C" fn #_name() { + pub unsafe extern "C" fn #_tname() { let f: fn(#(#tys,)*) = #path; f(#(#exprs,)*) @@ -597,7 +607,9 @@ fn tasks(app: &App, ownerships: &Ownerships, root: &mut Vec) { root.push(quote!{ #[allow(non_snake_case)] #[allow(unsafe_code)] - mod #name { + mod #tname { + use core::marker::PhantomData; + #[allow(dead_code)] #[deny(const_err)] const CHECK_PRIORITY: (u8, u8) = ( diff --git a/src/lib.rs b/src/lib.rs index f5481bc401..be670490e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,7 +84,7 @@ extern crate untagged_option; use core::u8; -pub use rtfm_core::{Resource, Static, Threshold}; +pub use rtfm_core::{Resource, Threshold}; pub use cortex_m::asm::{bkpt, wfi}; pub use cortex_m_rtfm_macros::app; #[doc(hidden)] diff --git a/tests/cfail/init-resource-share-idle.rs b/tests/cfail/init-resource-share-idle.rs new file mode 100644 index 0000000000..d8332469d8 --- /dev/null +++ b/tests/cfail/init-resource-share-idle.rs @@ -0,0 +1,31 @@ +#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m_rtfm as rtfm; +extern crate stm32f103xx; + +use rtfm::app; + +app! { //~ proc macro panicked + device: stm32f103xx, + + resources: { + static BUFFER: [u8; 16] = [0; 16]; + }, + + init: { + resources: [BUFFER], + }, + + idle: { + // ERROR resources assigned to `init` can't be shared with `idle` + resources: [BUFFER], + }, +} + +fn init(_p: init::Peripherals, _r: init::Resources) {} + +fn idle(_r: init::Resources) -> ! { + loop {} +} diff --git a/tests/cfail/init-resource-share-task.rs b/tests/cfail/init-resource-share-task.rs new file mode 100644 index 0000000000..8fe688993e --- /dev/null +++ b/tests/cfail/init-resource-share-task.rs @@ -0,0 +1,36 @@ +#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m_rtfm as rtfm; +extern crate stm32f103xx; + +use rtfm::app; + +app! { //~ proc macro panicked + device: stm32f103xx, + + resources: { + static BUFFER: [u8; 16] = [0; 16]; + }, + + init: { + resources: [BUFFER], + }, + + tasks: { + SYS_TICK: { + path: sys_tick, + // ERROR resources assigned to `init` can't be shared with tasks + resources: [BUFFER], + }, + }, +} + +fn init(_p: init::Peripherals) {} + +fn idle() -> ! { + loop {} +} + +fn sys_tick() {} diff --git a/tests/cfail/lock.rs b/tests/cfail/lock.rs index 5630649aeb..eb03b7d541 100644 --- a/tests/cfail/lock.rs +++ b/tests/cfail/lock.rs @@ -45,22 +45,24 @@ fn idle() -> ! { } fn exti0(mut t: &mut Threshold, mut r: EXTI0::Resources) { + // ERROR need to lock to access the resource because priority < ceiling + if *r.ON { + //~^ error type `EXTI0::ON` cannot be dereferenced + } + // OK need to lock to access the resource - if r.ON.claim(&mut t, |on, _| **on) {} + if r.ON.claim(&mut t, |on, _| *on) {} // OK can claim a resource with maximum ceiling - r.MAX.claim_mut(&mut t, |max, _| **max += 1); + r.MAX.claim_mut(&mut t, |max, _| *max += 1); } fn exti1(mut t: &mut Threshold, r: EXTI1::Resources) { - // ERROR no need to lock. Has direct access because priority == ceiling - if (**r.ON).claim(&mut t, |on, _| **on) { - //~^ error no method named `claim` found for type - } + // OK to directly access the resource because priority == ceiling + if *r.ON {} - if **r.ON { - // OK - } + // though the resource can still be claimed -- the claim is a no-op + if r.ON.claim(&mut t, |on, _| *on) {} } fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) {} diff --git a/tests/cfail/token-transfer.rs b/tests/cfail/token-transfer.rs index bc6205217a..f92e4b2b73 100644 --- a/tests/cfail/token-transfer.rs +++ b/tests/cfail/token-transfer.rs @@ -9,7 +9,7 @@ extern crate stm32f103xx; use rtfm::{app, Threshold}; -app! { //~ error bound `rtfm::Threshold: core::marker::Send` is not satisfied +app! { //~ error bound `*const (): core::marker::Send` is not satisfied device: stm32f103xx, resources: {