mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-30 15:34:33 +01:00
Merge #114
114: properly handle conditional compilation r=japaric a=japaric of resources and tasks Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
commit
c2fbb28488
11 changed files with 455 additions and 119 deletions
|
@ -3,6 +3,7 @@ authors = ["Jorge Aparicio <jorge@japaric.io>"]
|
||||||
categories = ["concurrency", "embedded", "no-std"]
|
categories = ["concurrency", "embedded", "no-std"]
|
||||||
description = "Procedural macros of the cortex-m-rtfm crate"
|
description = "Procedural macros of the cortex-m-rtfm crate"
|
||||||
documentation = "https://japaric.github.io/cortex-m-rtfm/api/cortex_m_rtfm"
|
documentation = "https://japaric.github.io/cortex-m-rtfm/api/cortex_m_rtfm"
|
||||||
|
edition = "2018"
|
||||||
keywords = ["arm", "cortex-m"]
|
keywords = ["arm", "cortex-m"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "cortex-m-rtfm-macros"
|
name = "cortex-m-rtfm-macros"
|
||||||
|
@ -14,12 +15,12 @@ version = "0.4.0-beta.3"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "0.6.8"
|
quote = "0.6.10"
|
||||||
proc-macro2 = "0.4.20"
|
proc-macro2 = "0.4.24"
|
||||||
|
|
||||||
[dependencies.syn]
|
[dependencies.syn]
|
||||||
features = ["extra-traits", "full"]
|
features = ["extra-traits", "full"]
|
||||||
version = "0.15.6"
|
version = "0.15.23"
|
||||||
|
|
||||||
[dependencies.rand]
|
[dependencies.rand]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
||||||
|
|
||||||
use syn::{Attribute, Ident, Type};
|
use syn::{Attribute, Ident, Type};
|
||||||
|
|
||||||
use syntax::{App, Idents};
|
use crate::syntax::{App, Idents};
|
||||||
|
|
||||||
pub type Ownerships = HashMap<Ident, Ownership>;
|
pub type Ownerships = HashMap<Ident, Ownership>;
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@ use std::{collections::HashSet, iter};
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use syn::parse;
|
use syn::parse;
|
||||||
|
|
||||||
use syntax::App;
|
use crate::syntax::App;
|
||||||
|
|
||||||
pub fn app(app: &App) -> parse::Result<()> {
|
pub fn app(app: &App) -> parse::Result<()> {
|
||||||
// Check that all referenced resources have been declared
|
// Check that all referenced resources have been declared
|
||||||
for res in app
|
for res in app
|
||||||
.idle
|
.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> { Box::new(idle.args.resources.iter()) })
|
.map(|idle| -> Box<dyn Iterator<Item = _>> { Box::new(idle.args.resources.iter()) })
|
||||||
.unwrap_or_else(|| Box::new(iter::empty()))
|
.unwrap_or_else(|| Box::new(iter::empty()))
|
||||||
.chain(&app.init.args.resources)
|
.chain(&app.init.args.resources)
|
||||||
.chain(app.exceptions.values().flat_map(|e| &e.args.resources))
|
.chain(app.exceptions.values().flat_map(|e| &e.args.resources))
|
||||||
|
@ -53,7 +53,7 @@ pub fn app(app: &App) -> parse::Result<()> {
|
||||||
for task in app
|
for task in app
|
||||||
.idle
|
.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(idle.args.schedule.iter().chain(&idle.args.spawn))
|
Box::new(idle.args.schedule.iter().chain(&idle.args.spawn))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| Box::new(iter::empty()))
|
.unwrap_or_else(|| Box::new(iter::empty()))
|
||||||
|
@ -73,7 +73,8 @@ pub fn app(app: &App) -> parse::Result<()> {
|
||||||
app.tasks
|
app.tasks
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|t| t.args.schedule.iter().chain(&t.args.spawn)),
|
.flat_map(|t| t.args.schedule.iter().chain(&t.args.spawn)),
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
if !app.tasks.contains_key(task) {
|
if !app.tasks.contains_key(task) {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
task.span(),
|
task.span(),
|
||||||
|
|
|
@ -10,10 +10,12 @@ use std::{
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use syn::{ArgCaptured, Ident, IntSuffix, LitInt};
|
use syn::{parse_quote, ArgCaptured, Attribute, Ident, IntSuffix, LitInt};
|
||||||
|
|
||||||
use analyze::{Analysis, Ownership};
|
use crate::{
|
||||||
use syntax::{App, Idents, Static};
|
analyze::{Analysis, Ownership},
|
||||||
|
syntax::{App, Idents, Static},
|
||||||
|
};
|
||||||
|
|
||||||
// NOTE to avoid polluting the user namespaces we map some identifiers to pseudo-hygienic names.
|
// NOTE to avoid polluting the user namespaces we map some identifiers to pseudo-hygienic names.
|
||||||
// In some instances we also use the pseudo-hygienic names for safety, for example the user should
|
// In some instances we also use the pseudo-hygienic names for safety, for example the user should
|
||||||
|
@ -86,8 +88,6 @@ struct Resources {
|
||||||
pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
|
pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
|
||||||
let mut ctxt = Context::default();
|
let mut ctxt = Context::default();
|
||||||
|
|
||||||
let device = &app.args.device;
|
|
||||||
|
|
||||||
let resources = resources(&mut ctxt, &app, analysis);
|
let resources = resources(&mut ctxt, &app, analysis);
|
||||||
|
|
||||||
let tasks = tasks(&mut ctxt, &app, analysis);
|
let tasks = tasks(&mut ctxt, &app, analysis);
|
||||||
|
@ -146,6 +146,7 @@ pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
|
||||||
|
|
||||||
let assertions = assertions(app, analysis);
|
let assertions = assertions(app, analysis);
|
||||||
|
|
||||||
|
let main = mk_ident(None);
|
||||||
let init = &ctxt.init;
|
let init = &ctxt.init;
|
||||||
quote!(
|
quote!(
|
||||||
#resources
|
#resources
|
||||||
|
@ -162,11 +163,7 @@ pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
|
||||||
|
|
||||||
#root_interrupts
|
#root_interrupts
|
||||||
|
|
||||||
// We put these items into a pseudo-module to avoid a collision between the `interrupt`
|
|
||||||
// import and user code
|
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
use #device::interrupt;
|
|
||||||
|
|
||||||
#scoped_interrupts
|
#scoped_interrupts
|
||||||
|
|
||||||
#(#dispatchers)*
|
#(#dispatchers)*
|
||||||
|
@ -178,10 +175,10 @@ pub fn app(app: &App, analysis: &Analysis) -> TokenStream {
|
||||||
|
|
||||||
#idle_fn
|
#idle_fn
|
||||||
|
|
||||||
|
#[export_name = "main"]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
#[rtfm::export::entry]
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
unsafe fn main() -> ! {
|
unsafe fn #main() -> ! {
|
||||||
#assertions
|
#assertions
|
||||||
|
|
||||||
rtfm::export::interrupt::disable();
|
rtfm::export::interrupt::disable();
|
||||||
|
@ -204,6 +201,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
let mut module = vec![];
|
let mut module = vec![];
|
||||||
for (name, res) in &app.resources {
|
for (name, res) in &app.resources {
|
||||||
|
let cfgs = &res.cfgs;
|
||||||
let attrs = &res.attrs;
|
let attrs = &res.attrs;
|
||||||
let mut_ = &res.mutability;
|
let mut_ = &res.mutability;
|
||||||
let ty = &res.ty;
|
let ty = &res.ty;
|
||||||
|
@ -219,6 +217,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
|
||||||
if let Some(Ownership::Shared { ceiling }) = analysis.ownerships.get(name) {
|
if let Some(Ownership::Shared { ceiling }) = analysis.ownerships.get(name) {
|
||||||
items.push(mk_resource(
|
items.push(mk_resource(
|
||||||
ctxt,
|
ctxt,
|
||||||
|
cfgs,
|
||||||
name,
|
name,
|
||||||
quote!(#name),
|
quote!(#name),
|
||||||
*ceiling,
|
*ceiling,
|
||||||
|
@ -238,6 +237,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
|
||||||
.map(|expr| {
|
.map(|expr| {
|
||||||
quote!(
|
quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
#[doc = #symbol]
|
#[doc = #symbol]
|
||||||
static mut #alias: #ty = #expr;
|
static mut #alias: #ty = #expr;
|
||||||
)
|
)
|
||||||
|
@ -245,6 +245,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
quote!(
|
quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
#[doc = #symbol]
|
#[doc = #symbol]
|
||||||
static mut #alias: rtfm::export::MaybeUninit<#ty> =
|
static mut #alias: rtfm::export::MaybeUninit<#ty> =
|
||||||
rtfm::export::MaybeUninit::uninitialized();
|
rtfm::export::MaybeUninit::uninitialized();
|
||||||
|
@ -262,6 +263,7 @@ fn resources(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2:
|
||||||
|
|
||||||
items.push(mk_resource(
|
items.push(mk_resource(
|
||||||
ctxt,
|
ctxt,
|
||||||
|
cfgs,
|
||||||
name,
|
name,
|
||||||
quote!(#ty),
|
quote!(#ty),
|
||||||
*ceiling,
|
*ceiling,
|
||||||
|
@ -297,6 +299,7 @@ fn init(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Toke
|
||||||
.assigns
|
.assigns
|
||||||
.iter()
|
.iter()
|
||||||
.map(|assign| {
|
.map(|assign| {
|
||||||
|
let attrs = &assign.attrs;
|
||||||
if app
|
if app
|
||||||
.resources
|
.resources
|
||||||
.get(&assign.left)
|
.get(&assign.left)
|
||||||
|
@ -305,11 +308,17 @@ fn init(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Toke
|
||||||
{
|
{
|
||||||
let alias = &ctxt.statics[&assign.left];
|
let alias = &ctxt.statics[&assign.left];
|
||||||
let expr = &assign.right;
|
let expr = &assign.right;
|
||||||
quote!(unsafe { #alias.set(#expr); })
|
quote!(
|
||||||
|
#(#attrs)*
|
||||||
|
unsafe { #alias.set(#expr); }
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let left = &assign.left;
|
let left = &assign.left;
|
||||||
let right = &assign.right;
|
let right = &assign.right;
|
||||||
quote!(#left = #right;)
|
quote!(
|
||||||
|
#(#attrs)*
|
||||||
|
#left = #right;
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -607,12 +616,14 @@ fn prelude(
|
||||||
|
|
||||||
// NOTE This field is just to avoid unused type parameter errors around `'a`
|
// NOTE This field is just to avoid unused type parameter errors around `'a`
|
||||||
defs.push(quote!(#[allow(dead_code)] #priority: &'a core::cell::Cell<u8>));
|
defs.push(quote!(#[allow(dead_code)] #priority: &'a core::cell::Cell<u8>));
|
||||||
exprs.push(quote!(#priority));
|
exprs.push(parse_quote!(#priority));
|
||||||
|
|
||||||
let mut may_call_lock = false;
|
let mut may_call_lock = false;
|
||||||
let mut needs_unsafe = false;
|
let mut needs_unsafe = false;
|
||||||
for name in resources {
|
for name in resources {
|
||||||
let res = &app.resources[name];
|
let res = &app.resources[name];
|
||||||
|
let cfgs = &res.cfgs;
|
||||||
|
|
||||||
let initialized = res.expr.is_some();
|
let initialized = res.expr.is_some();
|
||||||
let singleton = res.singleton;
|
let singleton = res.singleton;
|
||||||
let mut_ = res.mutability;
|
let mut_ = res.mutability;
|
||||||
|
@ -624,23 +635,40 @@ fn prelude(
|
||||||
// owned by Init
|
// owned by Init
|
||||||
if singleton {
|
if singleton {
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
defs.push(quote!(pub #name: #name));
|
defs.push(quote!(
|
||||||
exprs.push(quote!(#name: <#name as owned_singleton::Singleton>::new()));
|
#(#cfgs)*
|
||||||
|
pub #name: #name
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: <#name as owned_singleton::Singleton>::new()
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
defs.push(quote!(pub #name: &'static #mut_ #ty));
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &'static #mut_ #ty
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// owned by someone else
|
// owned by someone else
|
||||||
if singleton {
|
if singleton {
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
defs.push(quote!(pub #name: &'a mut #name));
|
defs.push(quote!(
|
||||||
exprs
|
#(#cfgs)*
|
||||||
.push(quote!(#name: &mut <#name as owned_singleton::Singleton>::new()));
|
pub #name: &'a mut #name
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &mut <#name as owned_singleton::Singleton>::new()
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
force_mut = true;
|
force_mut = true;
|
||||||
defs.push(quote!(pub #name: &'a mut #ty));
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &'a mut #ty
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,9 +676,15 @@ fn prelude(
|
||||||
// Resources assigned to init are always const initialized
|
// Resources assigned to init are always const initialized
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
if force_mut {
|
if force_mut {
|
||||||
exprs.push(quote!(#name: &mut #alias));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &mut #alias
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
exprs.push(quote!(#name: &#mut_ #alias));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &#mut_ #alias
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let ownership = &analysis.ownerships[name];
|
let ownership = &analysis.ownerships[name];
|
||||||
|
@ -661,23 +695,43 @@ fn prelude(
|
||||||
if singleton {
|
if singleton {
|
||||||
if mut_.is_none() {
|
if mut_.is_none() {
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
defs.push(quote!(pub #name: &'a #name));
|
defs.push(quote!(
|
||||||
exprs
|
#(#cfgs)*
|
||||||
.push(quote!(#name: &<#name as owned_singleton::Singleton>::new()));
|
pub #name: &'a #name
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &<#name as owned_singleton::Singleton>::new()
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
// Generate a resource proxy
|
// Generate a resource proxy
|
||||||
defs.push(quote!(pub #name: resources::#name<'a>));
|
defs.push(quote!(
|
||||||
exprs.push(quote!(#name: resources::#name { #priority }));
|
#(#cfgs)*
|
||||||
|
pub #name: resources::#name<'a>
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: resources::#name { #priority }
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if mut_.is_none() {
|
if mut_.is_none() {
|
||||||
defs.push(quote!(pub #name: &'a #ty));
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &'a #ty
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
// Generate a resource proxy
|
// Generate a resource proxy
|
||||||
defs.push(quote!(pub #name: resources::#name<'a>));
|
defs.push(quote!(
|
||||||
exprs.push(quote!(#name: resources::#name { #priority }));
|
#(#cfgs)*
|
||||||
|
pub #name: resources::#name<'a>
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: resources::#name { #priority }
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,29 +739,47 @@ fn prelude(
|
||||||
if singleton {
|
if singleton {
|
||||||
if kind.runs_once() {
|
if kind.runs_once() {
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
defs.push(quote!(pub #name: #name));
|
defs.push(quote!(
|
||||||
exprs.push(quote!(#name: <#name as owned_singleton::Singleton>::new()));
|
#(#cfgs)*
|
||||||
|
pub #name: #name
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: <#name as owned_singleton::Singleton>::new()
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
if ownership.is_owned() || mut_.is_none() {
|
if ownership.is_owned() || mut_.is_none() {
|
||||||
defs.push(quote!(pub #name: &'a #mut_ #name));
|
defs.push(quote!(
|
||||||
let alias = mk_ident(None);
|
#(#cfgs)*
|
||||||
items.push(quote!(
|
pub #name: &'a #mut_ #name
|
||||||
let #mut_ #alias = unsafe {
|
|
||||||
<#name as owned_singleton::Singleton>::new()
|
|
||||||
};
|
|
||||||
));
|
));
|
||||||
exprs.push(quote!(#name: &#mut_ #alias));
|
|
||||||
} else {
|
|
||||||
may_call_lock = true;
|
|
||||||
defs.push(quote!(pub #name: rtfm::Exclusive<'a, #name>));
|
|
||||||
let alias = mk_ident(None);
|
let alias = mk_ident(None);
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
let #mut_ #alias = unsafe {
|
let #mut_ #alias = unsafe {
|
||||||
<#name as owned_singleton::Singleton>::new()
|
<#name as owned_singleton::Singleton>::new()
|
||||||
};
|
};
|
||||||
));
|
));
|
||||||
exprs.push(quote!(
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &#mut_ #alias
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
may_call_lock = true;
|
||||||
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: rtfm::Exclusive<'a, #name>
|
||||||
|
));
|
||||||
|
let alias = mk_ident(None);
|
||||||
|
items.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
let #mut_ #alias = unsafe {
|
||||||
|
<#name as owned_singleton::Singleton>::new()
|
||||||
|
};
|
||||||
|
));
|
||||||
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
#name: rtfm::Exclusive(&mut #alias)
|
#name: rtfm::Exclusive(&mut #alias)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -715,11 +787,17 @@ fn prelude(
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if ownership.is_owned() || mut_.is_none() {
|
if ownership.is_owned() || mut_.is_none() {
|
||||||
defs.push(quote!(pub #name: &#lt #mut_ #ty));
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &#lt #mut_ #ty
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
exclusive = true;
|
exclusive = true;
|
||||||
may_call_lock = true;
|
may_call_lock = true;
|
||||||
defs.push(quote!(pub #name: rtfm::Exclusive<#lt, #ty>));
|
defs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: rtfm::Exclusive<#lt, #ty>
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,9 +806,15 @@ fn prelude(
|
||||||
needs_unsafe = true;
|
needs_unsafe = true;
|
||||||
if initialized {
|
if initialized {
|
||||||
if exclusive {
|
if exclusive {
|
||||||
exprs.push(quote!(#name: rtfm::Exclusive(&mut #alias)));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: rtfm::Exclusive(&mut #alias)
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
exprs.push(quote!(#name: &#mut_ #alias));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &#mut_ #alias
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let method = if mut_.is_some() {
|
let method = if mut_.is_some() {
|
||||||
|
@ -740,9 +824,15 @@ fn prelude(
|
||||||
};
|
};
|
||||||
|
|
||||||
if exclusive {
|
if exclusive {
|
||||||
exprs.push(quote!(#name: rtfm::Exclusive(#alias.#method()) ));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: rtfm::Exclusive(#alias.#method())
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
exprs.push(quote!(#name: #alias.#method() ));
|
exprs.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: #alias.#method()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -755,6 +845,7 @@ fn prelude(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let defs = &defs;
|
||||||
let doc = format!("`{}::Resources`", kind.ident().to_string());
|
let doc = format!("`{}::Resources`", kind.ident().to_string());
|
||||||
let decl = quote!(
|
let decl = quote!(
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
|
@ -893,7 +984,6 @@ fn exceptions(ctxt: &mut Context, app: &App, analysis: &Analysis) -> Vec<proc_ma
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(ident, exception)| {
|
.map(|(ident, exception)| {
|
||||||
let attrs = &exception.attrs;
|
let attrs = &exception.attrs;
|
||||||
let statics = &exception.statics;
|
|
||||||
let stmts = &exception.stmts;
|
let stmts = &exception.stmts;
|
||||||
|
|
||||||
let prelude = prelude(
|
let prelude = prelude(
|
||||||
|
@ -934,15 +1024,18 @@ fn exceptions(ctxt: &mut Context, app: &App, analysis: &Analysis) -> Vec<proc_ma
|
||||||
() => quote!(),
|
() => quote!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let locals = mk_locals(&exception.statics, false);
|
||||||
|
let symbol = ident.to_string();
|
||||||
|
let alias = mk_ident(None);
|
||||||
let unsafety = &exception.unsafety;
|
let unsafety = &exception.unsafety;
|
||||||
quote!(
|
quote!(
|
||||||
#module
|
#module
|
||||||
|
|
||||||
#[rtfm::export::exception]
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[export_name = #symbol]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#unsafety fn #ident() {
|
#unsafety fn #alias() {
|
||||||
#(#statics)*
|
#(#locals)*
|
||||||
|
|
||||||
#baseline_let
|
#baseline_let
|
||||||
|
|
||||||
|
@ -967,9 +1060,9 @@ fn interrupts(
|
||||||
let mut root = vec![];
|
let mut root = vec![];
|
||||||
let mut scoped = vec![];
|
let mut scoped = vec![];
|
||||||
|
|
||||||
|
let device = &app.args.device;
|
||||||
for (ident, interrupt) in &app.interrupts {
|
for (ident, interrupt) in &app.interrupts {
|
||||||
let attrs = &interrupt.attrs;
|
let attrs = &interrupt.attrs;
|
||||||
let statics = &interrupt.statics;
|
|
||||||
let stmts = &interrupt.stmts;
|
let stmts = &interrupt.stmts;
|
||||||
|
|
||||||
let prelude = prelude(
|
let prelude = prelude(
|
||||||
|
@ -1010,12 +1103,18 @@ fn interrupts(
|
||||||
() => quote!(),
|
() => quote!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let locals = mk_locals(&interrupt.statics, false);
|
||||||
|
let alias = mk_ident(None);
|
||||||
|
let symbol = ident.to_string();
|
||||||
let unsafety = &interrupt.unsafety;
|
let unsafety = &interrupt.unsafety;
|
||||||
scoped.push(quote!(
|
scoped.push(quote!(
|
||||||
#[interrupt]
|
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#unsafety fn #ident() {
|
#[export_name = #symbol]
|
||||||
#(#statics)*
|
#unsafety fn #alias() {
|
||||||
|
// check that this interrupt exists
|
||||||
|
let _ = #device::interrupt::#ident;
|
||||||
|
|
||||||
|
#(#locals)*
|
||||||
|
|
||||||
#baseline_let
|
#baseline_let
|
||||||
|
|
||||||
|
@ -1053,6 +1152,7 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
|
||||||
|
|
||||||
let resource = mk_resource(
|
let resource = mk_resource(
|
||||||
ctxt,
|
ctxt,
|
||||||
|
&[],
|
||||||
&free_alias,
|
&free_alias,
|
||||||
quote!(rtfm::export::FreeQueue<#capacity_ty>),
|
quote!(rtfm::export::FreeQueue<#capacity_ty>),
|
||||||
*analysis.free_queues.get(name).unwrap_or(&0),
|
*analysis.free_queues.get(name).unwrap_or(&0),
|
||||||
|
@ -1112,7 +1212,6 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
|
||||||
|
|
||||||
// second pass to generate the actual task function
|
// second pass to generate the actual task function
|
||||||
for (name, task) in &app.tasks {
|
for (name, task) in &app.tasks {
|
||||||
let attrs = &task.attrs;
|
|
||||||
let inputs = &task.inputs;
|
let inputs = &task.inputs;
|
||||||
let locals = mk_locals(&task.statics, false);
|
let locals = mk_locals(&task.statics, false);
|
||||||
let stmts = &task.stmts;
|
let stmts = &task.stmts;
|
||||||
|
@ -1147,6 +1246,8 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
|
||||||
app,
|
app,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let attrs = &task.attrs;
|
||||||
|
let cfgs = &task.cfgs;
|
||||||
let task_alias = &ctxt.tasks[name].alias;
|
let task_alias = &ctxt.tasks[name].alias;
|
||||||
let baseline_arg = match () {
|
let baseline_arg = match () {
|
||||||
#[cfg(feature = "timer-queue")]
|
#[cfg(feature = "timer-queue")]
|
||||||
|
@ -1159,6 +1260,7 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
|
||||||
};
|
};
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
#unsafety fn #task_alias(#baseline_arg #(#inputs,)*) {
|
#unsafety fn #task_alias(#baseline_arg #(#inputs,)*) {
|
||||||
#(#locals)*
|
#(#locals)*
|
||||||
|
|
||||||
|
@ -1182,18 +1284,32 @@ fn dispatchers(
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
let mut dispatchers = vec![];
|
let mut dispatchers = vec![];
|
||||||
|
|
||||||
|
let device = &app.args.device;
|
||||||
for (level, dispatcher) in &analysis.dispatchers {
|
for (level, dispatcher) in &analysis.dispatchers {
|
||||||
let ready_alias = mk_ident(None);
|
let ready_alias = mk_ident(None);
|
||||||
let enum_alias = mk_ident(None);
|
let enum_alias = mk_ident(None);
|
||||||
let tasks = &dispatcher.tasks;
|
|
||||||
let capacity = mk_typenum_capacity(dispatcher.capacity, true);
|
let capacity = mk_typenum_capacity(dispatcher.capacity, true);
|
||||||
|
|
||||||
|
let variants = dispatcher
|
||||||
|
.tasks
|
||||||
|
.iter()
|
||||||
|
.map(|task| {
|
||||||
|
let task_ = &app.tasks[task];
|
||||||
|
let cfgs = &task_.cfgs;
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#task
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let symbol = format!("P{}::READY_QUEUE::{}", level, ready_alias);
|
let symbol = format!("P{}::READY_QUEUE::{}", level, ready_alias);
|
||||||
let e = quote!(rtfm::export);
|
let e = quote!(rtfm::export);
|
||||||
let ty = quote!(#e::ReadyQueue<#enum_alias, #capacity>);
|
let ty = quote!(#e::ReadyQueue<#enum_alias, #capacity>);
|
||||||
let ceiling = *analysis.ready_queues.get(&level).unwrap_or(&0);
|
let ceiling = *analysis.ready_queues.get(&level).unwrap_or(&0);
|
||||||
let resource = mk_resource(
|
let resource = mk_resource(
|
||||||
ctxt,
|
ctxt,
|
||||||
|
&[],
|
||||||
&ready_alias,
|
&ready_alias,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
ceiling,
|
ceiling,
|
||||||
|
@ -1204,7 +1320,7 @@ fn dispatchers(
|
||||||
data.push(quote!(
|
data.push(quote!(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
enum #enum_alias { #(#tasks,)* }
|
enum #enum_alias { #(#variants,)* }
|
||||||
|
|
||||||
#[doc = #symbol]
|
#[doc = #symbol]
|
||||||
static mut #ready_alias: #e::MaybeUninit<#ty> = #e::MaybeUninit::uninitialized();
|
static mut #ready_alias: #e::MaybeUninit<#ty> = #e::MaybeUninit::uninitialized();
|
||||||
|
@ -1212,8 +1328,6 @@ fn dispatchers(
|
||||||
#resource
|
#resource
|
||||||
));
|
));
|
||||||
|
|
||||||
let interrupt = &dispatcher.interrupt;
|
|
||||||
|
|
||||||
let arms = dispatcher
|
let arms = dispatcher
|
||||||
.tasks
|
.tasks
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1221,9 +1335,12 @@ fn dispatchers(
|
||||||
let task_ = &ctxt.tasks[task];
|
let task_ = &ctxt.tasks[task];
|
||||||
let inputs = &task_.inputs;
|
let inputs = &task_.inputs;
|
||||||
let free = &task_.free_queue;
|
let free = &task_.free_queue;
|
||||||
let pats = tuple_pat(&app.tasks[task].inputs);
|
|
||||||
let alias = &task_.alias;
|
let alias = &task_.alias;
|
||||||
|
|
||||||
|
let task__ = &app.tasks[task];
|
||||||
|
let pats = tuple_pat(&task__.inputs);
|
||||||
|
let cfgs = &task__.cfgs;
|
||||||
|
|
||||||
let baseline_let;
|
let baseline_let;
|
||||||
let call;
|
let call;
|
||||||
match () {
|
match () {
|
||||||
|
@ -1243,23 +1360,32 @@ fn dispatchers(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
quote!(#enum_alias::#task => {
|
quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#enum_alias::#task => {
|
||||||
#baseline_let
|
#baseline_let
|
||||||
let input = ptr::read(#inputs.get_ref().get_unchecked(usize::from(index)));
|
let input = ptr::read(#inputs.get_ref().get_unchecked(usize::from(index)));
|
||||||
#free.get_mut().split().0.enqueue_unchecked(index);
|
#free.get_mut().split().0.enqueue_unchecked(index);
|
||||||
let (#pats) = input;
|
let (#pats) = input;
|
||||||
#call
|
#call
|
||||||
})
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let attrs = &dispatcher.attrs;
|
let attrs = &dispatcher.attrs;
|
||||||
|
let interrupt = &dispatcher.interrupt;
|
||||||
|
let symbol = interrupt.to_string();
|
||||||
|
let alias = mk_ident(None);
|
||||||
dispatchers.push(quote!(
|
dispatchers.push(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[interrupt]
|
#[export_name = #symbol]
|
||||||
unsafe fn #interrupt() {
|
unsafe fn #alias() {
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
// check that this interrupt exists
|
||||||
|
let _ = #device::interrupt::#interrupt;
|
||||||
|
|
||||||
rtfm::export::run(|| {
|
rtfm::export::run(|| {
|
||||||
while let Some((task, index)) = #ready_alias.get_mut().split().1.dequeue() {
|
while let Some((task, index)) = #ready_alias.get_mut().split().1.dequeue() {
|
||||||
match task {
|
match task {
|
||||||
|
@ -1293,6 +1419,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
|
||||||
for (name, task) in &ctxt.tasks {
|
for (name, task) in &ctxt.tasks {
|
||||||
let alias = &task.spawn_fn;
|
let alias = &task.spawn_fn;
|
||||||
let task_ = &app.tasks[name];
|
let task_ = &app.tasks[name];
|
||||||
|
let cfgs = &task_.cfgs;
|
||||||
let free = &task.free_queue;
|
let free = &task.free_queue;
|
||||||
let level = task_.args.priority;
|
let level = task_.args.priority;
|
||||||
let dispatcher = &ctxt.dispatchers[&level];
|
let dispatcher = &ctxt.dispatchers[&level];
|
||||||
|
@ -1328,6 +1455,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#(#cfgs)*
|
||||||
unsafe fn #alias(
|
unsafe fn #alias(
|
||||||
#baseline_arg
|
#baseline_arg
|
||||||
#priority: &core::cell::Cell<u8>,
|
#priority: &core::cell::Cell<u8>,
|
||||||
|
@ -1366,8 +1494,10 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
|
||||||
|
|
||||||
let mut methods = vec![];
|
let mut methods = vec![];
|
||||||
for task in spawn {
|
for task in spawn {
|
||||||
|
let task_ = &app.tasks[task];
|
||||||
let alias = &ctxt.tasks[task].spawn_fn;
|
let alias = &ctxt.tasks[task].spawn_fn;
|
||||||
let inputs = &app.tasks[task].inputs;
|
let inputs = &task_.inputs;
|
||||||
|
let cfgs = &task_.cfgs;
|
||||||
let ty = tuple_ty(inputs);
|
let ty = tuple_ty(inputs);
|
||||||
let pats = tuple_pat(inputs);
|
let pats = tuple_pat(inputs);
|
||||||
|
|
||||||
|
@ -1386,6 +1516,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#(#cfgs)*
|
||||||
pub fn #task(&self, #(#inputs,)*) -> Result<(), #ty> {
|
pub fn #task(&self, #(#inputs,)*) -> Result<(), #ty> {
|
||||||
unsafe { #alias(#instant &self.#priority, #pats) }
|
unsafe { #alias(#instant &self.#priority, #pats) }
|
||||||
}
|
}
|
||||||
|
@ -1415,12 +1546,15 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
|
||||||
let enum_ = &ctxt.schedule_enum;
|
let enum_ = &ctxt.schedule_enum;
|
||||||
let inputs = &task_.inputs;
|
let inputs = &task_.inputs;
|
||||||
let scheduleds = &task_.scheduleds;
|
let scheduleds = &task_.scheduleds;
|
||||||
let args = &app.tasks[task].inputs;
|
let task__ = &app.tasks[task];
|
||||||
|
let args = &task__.inputs;
|
||||||
|
let cfgs = &task__.cfgs;
|
||||||
let ty = tuple_ty(args);
|
let ty = tuple_ty(args);
|
||||||
let pats = tuple_pat(args);
|
let pats = tuple_pat(args);
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#(#cfgs)*
|
||||||
unsafe fn #alias(
|
unsafe fn #alias(
|
||||||
#priority: &core::cell::Cell<u8>,
|
#priority: &core::cell::Cell<u8>,
|
||||||
instant: rtfm::Instant,
|
instant: rtfm::Instant,
|
||||||
|
@ -1464,12 +1598,15 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
|
||||||
let mut methods = vec![];
|
let mut methods = vec![];
|
||||||
for task in schedule {
|
for task in schedule {
|
||||||
let alias = &ctxt.schedule_fn[task];
|
let alias = &ctxt.schedule_fn[task];
|
||||||
let inputs = &app.tasks[task].inputs;
|
let task_ = &app.tasks[task];
|
||||||
|
let inputs = &task_.inputs;
|
||||||
|
let cfgs = &task_.cfgs;
|
||||||
let ty = tuple_ty(inputs);
|
let ty = tuple_ty(inputs);
|
||||||
let pats = tuple_pat(inputs);
|
let pats = tuple_pat(inputs);
|
||||||
|
|
||||||
methods.push(quote!(
|
methods.push(quote!(
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#(#cfgs)*
|
||||||
pub fn #task(
|
pub fn #task(
|
||||||
&self,
|
&self,
|
||||||
instant: rtfm::Instant,
|
instant: rtfm::Instant,
|
||||||
|
@ -1499,12 +1636,22 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
|
||||||
|
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
|
let variants = tasks
|
||||||
|
.iter()
|
||||||
|
.map(|task| {
|
||||||
|
let cfgs = &app.tasks[task].cfgs;
|
||||||
|
quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#task
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let enum_ = &ctxt.schedule_enum;
|
let enum_ = &ctxt.schedule_enum;
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum #enum_ { #(#tasks,)* }
|
enum #enum_ { #(#variants,)* }
|
||||||
));
|
));
|
||||||
|
|
||||||
let cap = mk_typenum_capacity(analysis.timer_queue.capacity, false);
|
let cap = mk_typenum_capacity(analysis.timer_queue.capacity, false);
|
||||||
|
@ -1519,6 +1666,7 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
|
||||||
|
|
||||||
items.push(mk_resource(
|
items.push(mk_resource(
|
||||||
ctxt,
|
ctxt,
|
||||||
|
&[],
|
||||||
tq,
|
tq,
|
||||||
quote!(rtfm::export::TimerQueue<#enum_, #cap>),
|
quote!(rtfm::export::TimerQueue<#enum_, #cap>),
|
||||||
analysis.timer_queue.ceiling,
|
analysis.timer_queue.ceiling,
|
||||||
|
@ -1532,13 +1680,16 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
|
||||||
let arms = tasks
|
let arms = tasks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|task| {
|
.map(|task| {
|
||||||
let level = app.tasks[task].args.priority;
|
let task_ = &app.tasks[task];
|
||||||
|
let level = task_.args.priority;
|
||||||
|
let cfgs = &task_.cfgs;
|
||||||
let dispatcher_ = &ctxt.dispatchers[&level];
|
let dispatcher_ = &ctxt.dispatchers[&level];
|
||||||
let tenum = &dispatcher_.enum_;
|
let tenum = &dispatcher_.enum_;
|
||||||
let ready = &dispatcher_.ready_queue;
|
let ready = &dispatcher_.ready_queue;
|
||||||
let dispatcher = &analysis.dispatchers[&level].interrupt;
|
let dispatcher = &analysis.dispatchers[&level].interrupt;
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
#(#cfgs)*
|
||||||
#enum_::#task => {
|
#enum_::#task => {
|
||||||
(#ready { #priority }).lock(|rq| {
|
(#ready { #priority }).lock(|rq| {
|
||||||
rq.split().0.enqueue_unchecked((#tenum::#task, index))
|
rq.split().0.enqueue_unchecked((#tenum::#task, index))
|
||||||
|
@ -1551,10 +1702,11 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let logical_prio = analysis.timer_queue.priority;
|
let logical_prio = analysis.timer_queue.priority;
|
||||||
|
let alias = mk_ident(None);
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[rtfm::export::exception]
|
#[export_name = "SysTick"]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
unsafe fn SysTick() {
|
unsafe fn #alias() {
|
||||||
use rtfm::Mutex;
|
use rtfm::Mutex;
|
||||||
|
|
||||||
let ref #priority = core::cell::Cell::new(#logical_prio);
|
let ref #priority = core::cell::Cell::new(#logical_prio);
|
||||||
|
@ -1680,6 +1832,7 @@ fn assertions(app: &App, analysis: &Analysis) -> proc_macro2::TokenStream {
|
||||||
|
|
||||||
fn mk_resource(
|
fn mk_resource(
|
||||||
ctxt: &Context,
|
ctxt: &Context,
|
||||||
|
cfgs: &[Attribute],
|
||||||
struct_: &Ident,
|
struct_: &Ident,
|
||||||
ty: proc_macro2::TokenStream,
|
ty: proc_macro2::TokenStream,
|
||||||
ceiling: u8,
|
ceiling: u8,
|
||||||
|
@ -1696,6 +1849,7 @@ fn mk_resource(
|
||||||
let doc = format!("`{}`", ty);
|
let doc = format!("`{}`", ty);
|
||||||
module.push(quote!(
|
module.push(quote!(
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
|
#(#cfgs)*
|
||||||
pub struct #struct_<'a> {
|
pub struct #struct_<'a> {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub #priority: &'a core::cell::Cell<u8>,
|
pub #priority: &'a core::cell::Cell<u8>,
|
||||||
|
@ -1705,6 +1859,7 @@ fn mk_resource(
|
||||||
quote!(resources::#struct_)
|
quote!(resources::#struct_)
|
||||||
} else {
|
} else {
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
struct #struct_<'a> {
|
struct #struct_<'a> {
|
||||||
#priority: &'a core::cell::Cell<u8>,
|
#priority: &'a core::cell::Cell<u8>,
|
||||||
}
|
}
|
||||||
|
@ -1714,6 +1869,7 @@ fn mk_resource(
|
||||||
};
|
};
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
impl<'a> rtfm::Mutex for #path<'a> {
|
impl<'a> rtfm::Mutex for #path<'a> {
|
||||||
type T = #ty;
|
type T = #ty;
|
||||||
|
|
||||||
|
@ -1852,7 +2008,7 @@ fn tuple_ty(inputs: &[ArgCaptured]) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
enum Kind {
|
enum Kind {
|
||||||
Exception(Ident),
|
Exception(Ident),
|
||||||
Idle,
|
Idle,
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
// #![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![recursion_limit = "128"]
|
#![recursion_limit = "128"]
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
extern crate proc_macro2;
|
|
||||||
extern crate quote;
|
|
||||||
extern crate rand;
|
|
||||||
extern crate syn;
|
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syn::parse_macro_input;
|
use syn::parse_macro_input;
|
||||||
|
@ -308,5 +304,5 @@ pub fn app(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let analysis = analyze::app(&app);
|
let analysis = analyze::app(&app);
|
||||||
|
|
||||||
// Code generation
|
// Code generation
|
||||||
codegen::app(&app, &analysis)
|
codegen::app(&app, &analysis).into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub struct AppArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AppArgs {
|
impl Parse for AppArgs {
|
||||||
fn parse(input: ParseStream) -> parse::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
|
||||||
let mut device = None;
|
let mut device = None;
|
||||||
loop {
|
loop {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
|
@ -47,7 +47,7 @@ impl Parse for AppArgs {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
ident.span(),
|
ident.span(),
|
||||||
"expected `device`; other keys are not accepted",
|
"expected `device`; other keys are not accepted",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ pub struct Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Input {
|
impl Parse for Input {
|
||||||
fn parse(input: ParseStream) -> parse::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
|
||||||
fn parse_items(input: ParseStream) -> parse::Result<Vec<Item>> {
|
fn parse_items(input: ParseStream<'_>) -> parse::Result<Vec<Item>> {
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
|
||||||
while !input.is_empty() {
|
while !input.is_empty() {
|
||||||
|
@ -228,7 +228,7 @@ impl App {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
item.span(),
|
item.span(),
|
||||||
"this item must live outside the `#[app]` module",
|
"this item must live outside the `#[app]` module",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ impl App {
|
||||||
pub fn resource_accesses(&self) -> impl Iterator<Item = (u8, &Ident)> {
|
pub fn resource_accesses(&self) -> impl Iterator<Item = (u8, &Ident)> {
|
||||||
self.idle
|
self.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(idle.args.resources.iter().map(|res| (0, res)))
|
Box::new(idle.args.resources.iter().map(|res| (0, res)))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| Box::new(iter::empty()))
|
.unwrap_or_else(|| Box::new(iter::empty()))
|
||||||
|
@ -293,7 +293,7 @@ impl App {
|
||||||
.chain(
|
.chain(
|
||||||
self.idle
|
self.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(idle.args.spawn.iter().map(|s| (Some(0), s)))
|
Box::new(idle.args.spawn.iter().map(|s| (Some(0), s)))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| Box::new(iter::empty())),
|
.unwrap_or_else(|| Box::new(iter::empty())),
|
||||||
|
@ -329,7 +329,7 @@ impl App {
|
||||||
.chain(
|
.chain(
|
||||||
self.idle
|
self.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(idle.args.schedule.iter().map(|s| (Some(0), s)))
|
Box::new(idle.args.schedule.iter().map(|s| (Some(0), s)))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| Box::new(iter::empty())),
|
.unwrap_or_else(|| Box::new(iter::empty())),
|
||||||
|
@ -358,7 +358,7 @@ impl App {
|
||||||
pub fn schedule_callers(&self) -> impl Iterator<Item = (Ident, &Idents)> {
|
pub fn schedule_callers(&self) -> impl Iterator<Item = (Ident, &Idents)> {
|
||||||
self.idle
|
self.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(iter::once((
|
Box::new(iter::once((
|
||||||
Ident::new("idle", Span::call_site()),
|
Ident::new("idle", Span::call_site()),
|
||||||
&idle.args.schedule,
|
&idle.args.schedule,
|
||||||
|
@ -389,7 +389,7 @@ impl App {
|
||||||
pub fn spawn_callers(&self) -> impl Iterator<Item = (Ident, &Idents)> {
|
pub fn spawn_callers(&self) -> impl Iterator<Item = (Ident, &Idents)> {
|
||||||
self.idle
|
self.idle
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|idle| -> Box<Iterator<Item = _>> {
|
.map(|idle| -> Box<dyn Iterator<Item = _>> {
|
||||||
Box::new(iter::once((
|
Box::new(iter::once((
|
||||||
Ident::new("idle", Span::call_site()),
|
Ident::new("idle", Span::call_site()),
|
||||||
&idle.args.spawn,
|
&idle.args.spawn,
|
||||||
|
@ -492,7 +492,7 @@ impl Default for InitArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for InitArgs {
|
impl Parse for InitArgs {
|
||||||
fn parse(input: ParseStream) -> parse::Result<InitArgs> {
|
fn parse(input: ParseStream<'_>) -> parse::Result<InitArgs> {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
return Ok(InitArgs::default());
|
return Ok(InitArgs::default());
|
||||||
}
|
}
|
||||||
|
@ -526,7 +526,7 @@ impl Parse for InitArgs {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
ident.span(),
|
ident.span(),
|
||||||
"expected one of: resources, schedule or spawn",
|
"expected one of: resources, schedule or spawn",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,6 +597,7 @@ impl Parse for InitArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Assign {
|
pub struct Assign {
|
||||||
|
pub attrs: Vec<Attribute>,
|
||||||
pub left: Ident,
|
pub left: Ident,
|
||||||
pub right: Box<Expr>,
|
pub right: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
@ -649,7 +650,7 @@ pub struct Exception {
|
||||||
pub args: ExceptionArgs,
|
pub args: ExceptionArgs,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub unsafety: Option<Token![unsafe]>,
|
pub unsafety: Option<Token![unsafe]>,
|
||||||
pub statics: Statics,
|
pub statics: HashMap<Ident, Static>,
|
||||||
pub stmts: Vec<Stmt>,
|
pub stmts: Vec<Stmt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,7 +662,7 @@ pub struct ExceptionArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ExceptionArgs {
|
impl Parse for ExceptionArgs {
|
||||||
fn parse(input: ParseStream) -> parse::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
|
||||||
parse_args(input, false).map(
|
parse_args(input, false).map(
|
||||||
|TaskArgs {
|
|TaskArgs {
|
||||||
priority,
|
priority,
|
||||||
|
@ -727,7 +728,7 @@ impl Exception {
|
||||||
args,
|
args,
|
||||||
attrs: item.attrs,
|
attrs: item.attrs,
|
||||||
unsafety: item.unsafety,
|
unsafety: item.unsafety,
|
||||||
statics,
|
statics: Static::parse(statics)?,
|
||||||
stmts,
|
stmts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -737,7 +738,7 @@ pub struct Interrupt {
|
||||||
pub args: InterruptArgs,
|
pub args: InterruptArgs,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub unsafety: Option<Token![unsafe]>,
|
pub unsafety: Option<Token![unsafe]>,
|
||||||
pub statics: Statics,
|
pub statics: HashMap<Ident, Static>,
|
||||||
pub stmts: Vec<Stmt>,
|
pub stmts: Vec<Stmt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,7 +781,7 @@ impl Interrupt {
|
||||||
args,
|
args,
|
||||||
attrs: item.attrs,
|
attrs: item.attrs,
|
||||||
unsafety: item.unsafety,
|
unsafety: item.unsafety,
|
||||||
statics,
|
statics: Static::parse(statics)?,
|
||||||
stmts,
|
stmts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -788,6 +789,7 @@ impl Interrupt {
|
||||||
|
|
||||||
pub struct Resource {
|
pub struct Resource {
|
||||||
pub singleton: bool,
|
pub singleton: bool,
|
||||||
|
pub cfgs: Vec<Attribute>,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub mutability: Option<Token![mut]>,
|
pub mutability: Option<Token![mut]>,
|
||||||
pub ty: Box<Type>,
|
pub ty: Box<Type>,
|
||||||
|
@ -817,9 +819,12 @@ impl Resource {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (cfgs, attrs) = extract_cfgs(item.attrs);
|
||||||
|
|
||||||
Ok(Resource {
|
Ok(Resource {
|
||||||
singleton: pos.is_some(),
|
singleton: pos.is_some(),
|
||||||
attrs: item.attrs,
|
cfgs,
|
||||||
|
attrs,
|
||||||
mutability: item.mutability,
|
mutability: item.mutability,
|
||||||
ty: item.ty,
|
ty: item.ty,
|
||||||
expr: if uninitialized { None } else { Some(item.expr) },
|
expr: if uninitialized { None } else { Some(item.expr) },
|
||||||
|
@ -848,13 +853,13 @@ impl Default for TaskArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TaskArgs {
|
impl Parse for TaskArgs {
|
||||||
fn parse(input: ParseStream) -> parse::Result<Self> {
|
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
|
||||||
parse_args(input, true)
|
parse_args(input, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parser shared by TaskArgs and ExceptionArgs / InterruptArgs
|
// Parser shared by TaskArgs and ExceptionArgs / InterruptArgs
|
||||||
fn parse_args(input: ParseStream, accept_capacity: bool) -> parse::Result<TaskArgs> {
|
fn parse_args(input: ParseStream<'_>, accept_capacity: bool) -> parse::Result<TaskArgs> {
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
return Ok(TaskArgs::default());
|
return Ok(TaskArgs::default());
|
||||||
}
|
}
|
||||||
|
@ -981,7 +986,7 @@ fn parse_args(input: ParseStream, accept_capacity: bool) -> parse::Result<TaskAr
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
ident.span(),
|
ident.span(),
|
||||||
"expected one of: priority, resources, schedule or spawn",
|
"expected one of: priority, resources, schedule or spawn",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,6 +1047,7 @@ impl Static {
|
||||||
|
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
pub args: TaskArgs,
|
pub args: TaskArgs,
|
||||||
|
pub cfgs: Vec<Attribute>,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub unsafety: Option<Token![unsafe]>,
|
pub unsafety: Option<Token![unsafe]>,
|
||||||
pub inputs: Vec<ArgCaptured>,
|
pub inputs: Vec<ArgCaptured>,
|
||||||
|
@ -1093,9 +1099,11 @@ impl Task {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (cfgs, attrs) = extract_cfgs(item.attrs);
|
||||||
Ok(Task {
|
Ok(Task {
|
||||||
args,
|
args,
|
||||||
attrs: item.attrs,
|
cfgs,
|
||||||
|
attrs,
|
||||||
unsafety: item.unsafety,
|
unsafety: item.unsafety,
|
||||||
inputs,
|
inputs,
|
||||||
statics: Static::parse(statics)?,
|
statics: Static::parse(statics)?,
|
||||||
|
@ -1210,6 +1218,7 @@ fn extract_assignments(stmts: Vec<Stmt>) -> (Vec<Stmt>, Vec<Assign>) {
|
||||||
if let Expr::Path(ref expr) = *assign.left {
|
if let Expr::Path(ref expr) = *assign.left {
|
||||||
if expr.path.segments.len() == 1 {
|
if expr.path.segments.len() == 1 {
|
||||||
assigns.push(Assign {
|
assigns.push(Assign {
|
||||||
|
attrs: assign.attrs,
|
||||||
left: expr.path.segments[0].ident.clone(),
|
left: expr.path.segments[0].ident.clone(),
|
||||||
right: assign.right,
|
right: assign.right,
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,6 @@ pub use cortex_m::{
|
||||||
asm::wfi, interrupt, peripheral::scb::SystemHandler, peripheral::syst::SystClkSource,
|
asm::wfi, interrupt, peripheral::scb::SystemHandler, peripheral::syst::SystClkSource,
|
||||||
peripheral::Peripherals,
|
peripheral::Peripherals,
|
||||||
};
|
};
|
||||||
pub use cortex_m_rt::{entry, exception};
|
|
||||||
pub use heapless::consts;
|
pub use heapless::consts;
|
||||||
use heapless::spsc::{Queue, SingleCore};
|
use heapless::spsc::{Queue, SingleCore};
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,7 @@ impl<'a, T> fmt::Debug for Exclusive<'a, T>
|
||||||
where
|
where
|
||||||
T: fmt::Debug,
|
T: fmt::Debug,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
(**self).fmt(f)
|
(**self).fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ impl<'a, T> fmt::Display for Exclusive<'a, T>
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
(**self).fmt(f)
|
(**self).fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
64
tests/cfail/cfg-resources.rs
Normal file
64
tests/cfail/cfg-resources.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate lm3s6965;
|
||||||
|
extern crate panic_halt;
|
||||||
|
extern crate rtfm;
|
||||||
|
|
||||||
|
use rtfm::app;
|
||||||
|
|
||||||
|
#[app(device = lm3s6965)]
|
||||||
|
const APP: () = {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut O1: u32 = 0; // init
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut O2: u32 = 0; // idle
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut O3: u32 = 0; // EXTI0
|
||||||
|
#[cfg(never)]
|
||||||
|
static O4: u32 = 0; // idle
|
||||||
|
#[cfg(never)]
|
||||||
|
static O5: u32 = 0; // EXTI1
|
||||||
|
#[cfg(never)]
|
||||||
|
static O6: u32 = 0; // init
|
||||||
|
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut S1: u32 = 0; // idle & EXTI0
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut S2: u32 = 0; // EXTI0 & EXTI1
|
||||||
|
#[cfg(never)]
|
||||||
|
static S3: u32 = 0;
|
||||||
|
|
||||||
|
#[init(resources = [O1, O4, O5, O6, S3])]
|
||||||
|
fn init() {
|
||||||
|
resources.O1; //~ ERROR no field `O1`
|
||||||
|
resources.O4; //~ ERROR no field `O4`
|
||||||
|
resources.O5; //~ ERROR no field `O5`
|
||||||
|
resources.O6; //~ ERROR no field `O6`
|
||||||
|
resources.S3; //~ ERROR no field `S3`
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle(resources = [O2, O4, S1, S3])]
|
||||||
|
fn idle() -> ! {
|
||||||
|
resources.O2; //~ ERROR no field `O2`
|
||||||
|
resources.O4; //~ ERROR no field `O4`
|
||||||
|
resources.S1; //~ ERROR no field `S1`
|
||||||
|
resources.S3; //~ ERROR no field `S3`
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt(resources = [O3, S1, S2, S3])]
|
||||||
|
fn UART0() {
|
||||||
|
resources.O3; //~ ERROR no field `O3`
|
||||||
|
resources.S1; //~ ERROR no field `S1`
|
||||||
|
resources.S2; //~ ERROR no field `S2`
|
||||||
|
resources.S3; //~ ERROR no field `S3`
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt(resources = [S2, O5])]
|
||||||
|
fn UART1() {
|
||||||
|
resources.S2; //~ ERROR no field `S2`
|
||||||
|
resources.O5; //~ ERROR no field `O5`
|
||||||
|
}
|
||||||
|
};
|
57
tests/cfail/cfg-static.rs
Normal file
57
tests/cfail/cfg-static.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate lm3s6965;
|
||||||
|
extern crate panic_halt;
|
||||||
|
extern crate rtfm;
|
||||||
|
|
||||||
|
use rtfm::app;
|
||||||
|
|
||||||
|
#[app(device = lm3s6965)]
|
||||||
|
const APP: () = {
|
||||||
|
#[init]
|
||||||
|
fn init() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
FOO; //~ ERROR cannot find value `FOO` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle]
|
||||||
|
fn idle() -> ! {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
FOO; //~ ERROR cannot find value `FOO` in this scope
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[exception]
|
||||||
|
fn SVCall() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
FOO; //~ ERROR cannot find value `FOO` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt]
|
||||||
|
fn UART0() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
FOO; //~ ERROR cannot find value `FOO` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
fn foo() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
FOO; //~ ERROR cannot find value `FOO` in this scope
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn UART1();
|
||||||
|
}
|
||||||
|
};
|
53
tests/cpass/cfg.rs
Normal file
53
tests/cpass/cfg.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
//! Compile-pass test that checks that `#[cfg]` attributes are respected
|
||||||
|
|
||||||
|
#![deny(unsafe_code)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
extern crate lm3s6965;
|
||||||
|
extern crate panic_semihosting;
|
||||||
|
extern crate rtfm;
|
||||||
|
|
||||||
|
use rtfm::app;
|
||||||
|
|
||||||
|
#[app(device = lm3s6965)]
|
||||||
|
const APP: () = {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
#[init]
|
||||||
|
fn init() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut BAR: u32 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle]
|
||||||
|
fn idle() -> ! {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut BAR: u32 = 0;
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(resources = [FOO], schedule = [quux], spawn = [quux])]
|
||||||
|
fn foo() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut BAR: u32 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(priority = 3, resources = [FOO], schedule = [quux], spawn = [quux])]
|
||||||
|
fn bar() {
|
||||||
|
#[cfg(never)]
|
||||||
|
static mut BAR: u32 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(never)]
|
||||||
|
#[task]
|
||||||
|
fn quux() {}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn UART0();
|
||||||
|
fn UART1();
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue