From 6bd168d711cd6304af72a106bb98f0cbebff0742 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Mon, 5 Oct 2020 21:57:44 +0200 Subject: [PATCH 1/9] spawn POC works, likely unsound --- examples/spawn.rs | 33 ++++++++++++ macros/src/codegen.rs | 1 + macros/src/codegen/dispatchers.rs | 4 +- macros/src/codegen/hardware_tasks.rs | 1 + macros/src/codegen/idle.rs | 3 +- macros/src/codegen/init.rs | 8 ++- macros/src/codegen/module.rs | 74 +++++++++++++++++++++++++- macros/src/codegen/software_tasks.rs | 7 +-- macros/src/codegen/spawn_module.rs | 79 ++++++++++++++++++++++++++++ 9 files changed, 201 insertions(+), 9 deletions(-) create mode 100644 examples/spawn.rs create mode 100644 macros/src/codegen/spawn_module.rs diff --git a/examples/spawn.rs b/examples/spawn.rs new file mode 100644 index 0000000000..3ea775940b --- /dev/null +++ b/examples/spawn.rs @@ -0,0 +1,33 @@ +//! examples/message.rs + +#![deny(unsafe_code)] +// #![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::{debug, hprintln}; +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965)] +mod app { + #[init(spawn = [foo])] + fn init(_c: init::Context) { + foo::spawn(1, 2).unwrap(); + } + + #[task()] + fn foo(_c: foo::Context, x: i32, y: u32) { + hprintln!("foo {}, {}", x, y).unwrap(); + if x == 2 { + debug::exit(debug::EXIT_SUCCESS); + } + foo::spawn(2, 3).unwrap(); + } + + // RTIC requires that unused interrupts are declared in an extern block when + // using software tasks; these free interrupts will be used to dispatch the + // software tasks. + extern "C" { + fn SSI0(); + } +} diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index f230d3956d..cc173830c9 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -20,6 +20,7 @@ mod schedule_body; mod software_tasks; mod spawn; mod spawn_body; +mod spawn_module; mod timer_queue; mod util; diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 300aa996e0..eac0371d3b 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -35,7 +35,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec TokenStream2 { +pub fn codegen( + ctxt: Context, + resources_tick: bool, + app: &App, + analysis: &Analysis, + extra: &Extra, +) -> TokenStream2 { let mut items = vec![]; let mut fields = vec![]; let mut values = vec![]; @@ -318,6 +325,69 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> } )); + // not sure if this is the right way, maybe its backwards, + // that spawn_module should put in in root + + if let Context::SoftwareTask(..) = ctxt { + let spawnee = &app.software_tasks[name]; + let priority = spawnee.args.priority; + let t = util::spawn_t_ident(priority); + let cfgs = &spawnee.cfgs; + let (args, tupled, _untupled, ty) = util::regroup_inputs(&spawnee.inputs); + let args = &args; + let tupled = &tupled; + let fq = util::fq_ident(name); + let rq = util::rq_ident(priority); + let inputs = util::inputs_ident(name); + + eprintln!("app name: {}", app.name); + eprintln!("inputs {}", &inputs); + eprintln!("task name: {}", name); + eprintln!("fq {}", fq); + eprintln!("rq {}", rq); + let app_name = &app.name; + let app_path = quote! {crate::#app_name}; + + let device = extra.device; + let enum_ = util::interrupt_ident(); + let interrupt = &analysis.interrupts.get(&priority); + let pend = { + quote!( + rtic::pend(#device::#enum_::#interrupt); + ) + }; + + eprintln!("pend {}", &pend); + + items.push(quote!( + #(#cfgs)* + pub fn spawn(#(#args,)*) -> Result<(), #ty> { + // #let_instant // do we need it? + use rtic::Mutex as _; + + let input = #tupled; + // TODO: use critical section, now we are unsafe + unsafe { + if let Some(index) = #app_path::#fq.dequeue() { + #app_path::#inputs + .get_unchecked_mut(usize::from(index)) + .as_mut_ptr() + .write(input); + + // #write_instant, do we need? + + #app_path::#rq.enqueue_unchecked((#app_path::#t::#name, index)); + + #pend + + Ok(()) + } else { + Err(input) + } + } + })); + } + if !items.is_empty() { quote!( #[allow(non_snake_case)] diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 4ae37e4e9b..b240d7aa70 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -54,7 +54,7 @@ pub fn codegen( mod_app.push(quote!( /// Queue version of a free-list that keeps track of empty slots in /// the following buffers - static mut #fq: #fq_ty = #fq_expr; + pub static mut #fq: #fq_ty = #fq_expr; )); // Generate a resource proxy if needed @@ -88,7 +88,7 @@ pub fn codegen( mod_app.push(quote!( #uninit /// Buffer that holds the instants associated to the inputs of a task - static mut #instants: + pub static mut #instants: [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = [#(#elems,)*]; )); @@ -99,7 +99,7 @@ pub fn codegen( mod_app.push(quote!( #uninit /// Buffer that holds the inputs of a task - static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = + pub static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = [#(#elems,)*]; )); } @@ -161,6 +161,7 @@ pub fn codegen( Context::SoftwareTask(name), needs_lt, app, + analysis, extra, )); } diff --git a/macros/src/codegen/spawn_module.rs b/macros/src/codegen/spawn_module.rs new file mode 100644 index 0000000000..5d3f465257 --- /dev/null +++ b/macros/src/codegen/spawn_module.rs @@ -0,0 +1,79 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use rtic_syntax::{ast::App, Context}; +use syn::Ident; + +#[allow(unused_imports)] +use crate::{analyze::Analysis, check::Extra, codegen::util}; + +#[allow(dead_code)] +pub fn codegen( + _spawner: Context, + _name: &Ident, + _app: &App, + _analysis: &Analysis, + _extra: &Extra, +) -> TokenStream2 { + // let spawnee = &app.software_tasks[name]; + // let priority = spawnee.args.priority; + + // let write_instant = if app.uses_schedule() { + // let instants = util::instants_ident(name); + + // Some(quote!( + // #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant); + // )) + // } else { + // None + // }; + + // let t = util::spawn_t_ident(priority); + // let fq = util::fq_ident(name); + // let rq = util::rq_ident(priority); + // let (dequeue, enqueue) = if spawner.is_init() { + // ( + // quote!(#fq.dequeue()), + // quote!(#rq.enqueue_unchecked((#t::#name, index));), + // ) + // } else { + // ( + // quote!((#fq { priority }.lock(|fq| fq.split().1.dequeue()))), + // quote!((#rq { priority }.lock(|rq| { + // rq.split().0.enqueue_unchecked((#t::#name, index)) + // }));), + // ) + // }; + + // let device = extra.device; + // let enum_ = util::interrupt_ident(); + // let interrupt = &analysis.interrupts.get(&priority); + // let pend = { + // quote!( + // rtic::pend(#device::#enum_::#interrupt); + // ) + // }; + + // let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs); + // let inputs = util::inputs_ident(name); + quote!( + // unsafe { + // use rtic::Mutex as _; + + // let input = #tupled; + // // // if let Some(index) = #dequeue { + // // // #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input); + + // // // #write_instant + + // // // #enqueue + + // // // #pend + + // // // Ok(()) + // // // } else { + // // // Err(input) + // // // } + // Ok(()) + // } + ) +} From aac97a2109f56784adf59cdeba25beef4f18a13a Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Mon, 5 Oct 2020 22:02:04 +0200 Subject: [PATCH 2/9] spawn POC works, likely unsound, cleanup --- macros/src/codegen.rs | 1 - macros/src/codegen/module.rs | 1 - macros/src/codegen/spawn_module.rs | 79 ------------------------------ 3 files changed, 81 deletions(-) delete mode 100644 macros/src/codegen/spawn_module.rs diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index cc173830c9..f230d3956d 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -20,7 +20,6 @@ mod schedule_body; mod software_tasks; mod spawn; mod spawn_body; -mod spawn_module; mod timer_queue; mod util; diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 7298356a48..bba64bb9ac 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -2,7 +2,6 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::{ast::App, Context}; -// use crate::{analyze::Analysis, check::Extra, codegen::spawn_module, codegen::util}; use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen( diff --git a/macros/src/codegen/spawn_module.rs b/macros/src/codegen/spawn_module.rs deleted file mode 100644 index 5d3f465257..0000000000 --- a/macros/src/codegen/spawn_module.rs +++ /dev/null @@ -1,79 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::{ast::App, Context}; -use syn::Ident; - -#[allow(unused_imports)] -use crate::{analyze::Analysis, check::Extra, codegen::util}; - -#[allow(dead_code)] -pub fn codegen( - _spawner: Context, - _name: &Ident, - _app: &App, - _analysis: &Analysis, - _extra: &Extra, -) -> TokenStream2 { - // let spawnee = &app.software_tasks[name]; - // let priority = spawnee.args.priority; - - // let write_instant = if app.uses_schedule() { - // let instants = util::instants_ident(name); - - // Some(quote!( - // #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant); - // )) - // } else { - // None - // }; - - // let t = util::spawn_t_ident(priority); - // let fq = util::fq_ident(name); - // let rq = util::rq_ident(priority); - // let (dequeue, enqueue) = if spawner.is_init() { - // ( - // quote!(#fq.dequeue()), - // quote!(#rq.enqueue_unchecked((#t::#name, index));), - // ) - // } else { - // ( - // quote!((#fq { priority }.lock(|fq| fq.split().1.dequeue()))), - // quote!((#rq { priority }.lock(|rq| { - // rq.split().0.enqueue_unchecked((#t::#name, index)) - // }));), - // ) - // }; - - // let device = extra.device; - // let enum_ = util::interrupt_ident(); - // let interrupt = &analysis.interrupts.get(&priority); - // let pend = { - // quote!( - // rtic::pend(#device::#enum_::#interrupt); - // ) - // }; - - // let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs); - // let inputs = util::inputs_ident(name); - quote!( - // unsafe { - // use rtic::Mutex as _; - - // let input = #tupled; - // // // if let Some(index) = #dequeue { - // // // #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input); - - // // // #write_instant - - // // // #enqueue - - // // // #pend - - // // // Ok(()) - // // // } else { - // // // Err(input) - // // // } - // Ok(()) - // } - ) -} From 0bc2168cd689f996ab3d7557fd4626bccbd3b954 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Mon, 5 Oct 2020 22:30:38 +0200 Subject: [PATCH 3/9] spawn examples updated --- examples/spawn.rs | 2 +- examples/spawn2.rs | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 examples/spawn2.rs diff --git a/examples/spawn.rs b/examples/spawn.rs index 3ea775940b..62635632e2 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -1,7 +1,7 @@ //! examples/message.rs #![deny(unsafe_code)] -// #![deny(warnings)] +#![deny(warnings)] #![no_main] #![no_std] diff --git a/examples/spawn2.rs b/examples/spawn2.rs new file mode 100644 index 0000000000..07ed53a461 --- /dev/null +++ b/examples/spawn2.rs @@ -0,0 +1,39 @@ +//! examples/message.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use cortex_m_semihosting::{debug, hprintln}; +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965)] +mod app { + #[init(spawn = [foo, foo2])] + fn init(_c: init::Context) { + foo::spawn(1, 2).unwrap(); + } + + #[task()] + fn foo(_c: foo::Context, x: i32, y: u32) { + hprintln!("foo {}, {}", x, y).unwrap(); + if x == 2 { + debug::exit(debug::EXIT_SUCCESS); + } + foo2::spawn(2).unwrap(); + } + + #[task()] + fn foo2(_c: foo2::Context, x: i32) { + hprintln!("foo2 {}", x).unwrap(); + foo::spawn(x, 0).unwrap(); + } + + // RTIC requires that unused interrupts are declared in an extern block when + // using software tasks; these free interrupts will be used to dispatch the + // software tasks. + extern "C" { + fn SSI0(); + } +} From e8b4fa7b32cf044428971f22e01428ff9cccff3c Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 8 Oct 2020 17:33:16 +0200 Subject: [PATCH 4/9] Added critical sections --- macros/src/codegen/module.rs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index bba64bb9ac..1fd3cd4273 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -350,13 +350,6 @@ pub fn codegen( let device = extra.device; let enum_ = util::interrupt_ident(); let interrupt = &analysis.interrupts.get(&priority); - let pend = { - quote!( - rtic::pend(#device::#enum_::#interrupt); - ) - }; - - eprintln!("pend {}", &pend); items.push(quote!( #(#cfgs)* @@ -365,25 +358,26 @@ pub fn codegen( use rtic::Mutex as _; let input = #tupled; - // TODO: use critical section, now we are unsafe - unsafe { - if let Some(index) = #app_path::#fq.dequeue() { + + if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) { + unsafe { #app_path::#inputs .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); - - // #write_instant, do we need? - - #app_path::#rq.enqueue_unchecked((#app_path::#t::#name, index)); - - #pend - - Ok(()) - } else { - Err(input) } + + rtic::export::interrupt::free(|_| { + #app_path::#rq.enqueue_unchecked((#app_path::#t::#name, index)); + }); + + rtic::pend(#device::#enum_::#interrupt); + + Ok(()) + } else { + Err(input) } + })); } From 524273c96a978299b64e51a9cdcc007585a0f170 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 11 Oct 2020 18:38:38 +0200 Subject: [PATCH 5/9] Now with spawn/schedule from anywhere --- examples/schedule.rs | 6 +- examples/spawn.rs | 4 +- examples/spawn2.rs | 10 +- macros/Cargo.toml | 2 +- macros/src/analyze.rs | 1 - macros/src/check.rs | 62 ++++---- macros/src/codegen.rs | 16 +- macros/src/codegen/dispatchers.rs | 20 +-- macros/src/codegen/hardware_tasks.rs | 2 +- macros/src/codegen/module.rs | 216 ++++++++------------------- macros/src/codegen/pre_init.rs | 8 +- macros/src/codegen/schedule.rs | 90 ----------- macros/src/codegen/schedule_body.rs | 59 -------- macros/src/codegen/software_tasks.rs | 87 ++++------- macros/src/codegen/spawn.rs | 121 --------------- macros/src/codegen/spawn_body.rs | 76 ---------- macros/src/codegen/timer_queue.rs | 69 +++------ macros/src/codegen/util.rs | 16 +- macros/src/lib.rs | 1 - 19 files changed, 172 insertions(+), 694 deletions(-) delete mode 100644 macros/src/codegen/schedule.rs delete mode 100644 macros/src/codegen/schedule_body.rs delete mode 100644 macros/src/codegen/spawn.rs delete mode 100644 macros/src/codegen/spawn_body.rs diff --git a/examples/schedule.rs b/examples/schedule.rs index 7e6adc1aa7..fa67a56682 100644 --- a/examples/schedule.rs +++ b/examples/schedule.rs @@ -13,7 +13,7 @@ use rtic::cyccnt::{Instant, U32Ext as _}; // NOTE: does NOT work on QEMU! #[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] mod app { - #[init(schedule = [foo, bar])] + #[init()] fn init(mut cx: init::Context) -> init::LateResources { // Initialize (enable) the monotonic timer (CYCCNT) cx.core.DCB.enable_trace(); @@ -28,10 +28,10 @@ mod app { hprintln!("init @ {:?}", now).unwrap(); // Schedule `foo` to run 8e6 cycles (clock cycles) in the future - cx.schedule.foo(now + 8_000_000.cycles()).unwrap(); + foo::schedule(now + 8_000_000.cycles()).unwrap(); // Schedule `bar` to run 4e6 cycles in the future - cx.schedule.bar(now + 4_000_000.cycles()).unwrap(); + bar::schedule(now + 4_000_000.cycles()).unwrap(); init::LateResources {} } diff --git a/examples/spawn.rs b/examples/spawn.rs index 62635632e2..23fa178848 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -11,8 +11,10 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { #[init(spawn = [foo])] - fn init(_c: init::Context) { + fn init(_c: init::Context) -> init::LateResources { foo::spawn(1, 2).unwrap(); + + init::LateResources {} } #[task()] diff --git a/examples/spawn2.rs b/examples/spawn2.rs index 07ed53a461..2998d16cf8 100644 --- a/examples/spawn2.rs +++ b/examples/spawn2.rs @@ -10,12 +10,14 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [foo, foo2])] - fn init(_c: init::Context) { + #[init] + fn init(_c: init::Context) -> init::LateResources { foo::spawn(1, 2).unwrap(); + + init::LateResources {} } - #[task()] + #[task] fn foo(_c: foo::Context, x: i32, y: u32) { hprintln!("foo {}, {}", x, y).unwrap(); if x == 2 { @@ -24,7 +26,7 @@ mod app { foo2::spawn(2).unwrap(); } - #[task()] + #[task] fn foo2(_c: foo2::Context, x: i32) { hprintln!("foo2 {}", x).unwrap(); foo::spawn(x, 0).unwrap(); diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 610890bbfb..f8a0523ee7 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,5 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.4.0" } +rtic-syntax = { path = "../../rtic-syntax", version = "0.4.0" } diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 38018c8c5d..e0231a2e2d 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -29,7 +29,6 @@ pub fn app(analysis: P, app: &App) -> P { .software_tasks .values() .filter_map(|task| Some(task.args.priority)) - .chain(analysis.timer_queues.first().map(|tq| tq.priority)) .collect::>(); if !priorities.is_empty() { diff --git a/macros/src/check.rs b/macros/src/check.rs index 0e57bb7323..5a1d3aff67 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -19,35 +19,7 @@ impl<'a> Extra<'a> { } } -pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { - // Check that all exceptions are valid; only exceptions with configurable priorities are - // accepted - for (name, task) in &app.hardware_tasks { - let name_s = task.args.binds.to_string(); - match &*name_s { - "SysTick" => { - // If the timer queue is used, then SysTick is unavailable - if !analysis.timer_queues.is_empty() { - return Err(parse::Error::new( - name.span(), - "this exception can't be used because it's being used by the runtime", - )); - } else { - // OK - } - } - - "NonMaskableInt" | "HardFault" => { - return Err(parse::Error::new( - name.span(), - "only exceptions with configurable priority can be used as hardware tasks", - )); - } - - _ => {} - } - } - +pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result> { // Check that external (device-specific) interrupts are not named after known (Cortex-M) // exceptions for name in app.extern_interrupts.keys() { @@ -76,7 +48,6 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { first = Some(name); Some(task.args.priority) }) - .chain(analysis.timer_queues.first().map(|tq| tq.priority)) .collect::>(); let need = priorities.len(); @@ -141,11 +112,32 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { } } - if !&analysis.timer_queues.is_empty() && monotonic.is_none() { - return Err(parse::Error::new( - Span::call_site(), - "a `monotonic` timer must be specified to use the `schedule` API", - )); + // Check that all exceptions are valid; only exceptions with configurable priorities are + // accepted + for (name, task) in &app.hardware_tasks { + let name_s = task.args.binds.to_string(); + match &*name_s { + "SysTick" => { + // If the timer queue is used, then SysTick is unavailable + if monotonic.is_some() { + return Err(parse::Error::new( + name.span(), + "this exception can't be used because it's being used by the runtime", + )); + } else { + // OK + } + } + + "NonMaskableInt" | "HardFault" => { + return Err(parse::Error::new( + name.span(), + "only exceptions with configurable priority can be used as hardware tasks", + )); + } + + _ => {} + } } if let Some(device) = device { diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index f230d3956d..2be265d442 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -15,11 +15,11 @@ mod post_init; mod pre_init; mod resources; mod resources_struct; -mod schedule; -mod schedule_body; +// mod schedule; +// mod schedule_body; mod software_tasks; -mod spawn; -mod spawn_body; +// mod spawn; +// mod spawn_body; mod timer_queue; mod util; @@ -116,11 +116,11 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let mod_app_dispatchers = dispatchers::codegen(app, analysis, extra); - let mod_app_spawn = spawn::codegen(app, analysis, extra); + // let mod_app_spawn = spawn::codegen(app, analysis, extra); let mod_app_timer_queue = timer_queue::codegen(app, analysis, extra); - let mod_app_schedule = schedule::codegen(app, extra); + // let mod_app_schedule = schedule::codegen(app, extra); let user_imports = app.user_imports.clone(); let user_code = app.user_code.clone(); @@ -170,11 +170,11 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { #(#mod_app_dispatchers)* - #(#mod_app_spawn)* + // #(#mod_app_spawn)* #(#mod_app_timer_queue)* - #(#mod_app_schedule)* + // #(#mod_app_schedule)* #(#mains)* } diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index eac0371d3b..bf6986b8d9 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -60,24 +60,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { - priority: &'a rtic::export::Priority, - } - )); - - items.push(util::impl_mutex( - extra, - &[], - false, - &rq, - rq_ty, - ceiling, - quote!(&mut #rq), - )); - } - let arms = channel .tasks .iter() @@ -88,7 +70,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { - if app.uses_schedule() { + if extra.monotonic.is_some() { let m = extra.monotonic(); fields.push(quote!( @@ -67,7 +67,7 @@ pub fn codegen( Context::Idle => {} Context::HardwareTask(..) => { - if app.uses_schedule() { + if extra.monotonic.is_some() { let m = extra.monotonic(); fields.push(quote!( @@ -82,7 +82,7 @@ pub fn codegen( } Context::SoftwareTask(..) => { - if app.uses_schedule() { + if extra.monotonic.is_some() { let m = extra.monotonic(); fields.push(quote!( @@ -132,139 +132,6 @@ pub fn codegen( values.push(quote!(resources: Resources::new(#priority))); } - if ctxt.uses_schedule(app) { - let doc = "Tasks that can be `schedule`-d from this context"; - if ctxt.is_init() { - items.push(quote!( - #[doc = #doc] - #[derive(Clone, Copy)] - pub struct Schedule { - _not_send: core::marker::PhantomData<*mut ()>, - } - )); - - fields.push(quote!( - #[doc = #doc] - pub schedule: Schedule - )); - - values.push(quote!( - schedule: Schedule { _not_send: core::marker::PhantomData } - )); - } else { - lt = Some(quote!('a)); - - items.push(quote!( - #[doc = #doc] - #[derive(Clone, Copy)] - pub struct Schedule<'a> { - priority: &'a rtic::export::Priority, - } - - impl<'a> Schedule<'a> { - #[doc(hidden)] - #[inline(always)] - pub unsafe fn priority(&self) -> &rtic::export::Priority { - &self.priority - } - } - )); - - fields.push(quote!( - #[doc = #doc] - pub schedule: Schedule<'a> - )); - - values.push(quote!( - schedule: Schedule { priority } - )); - } - } - - if ctxt.uses_spawn(app) { - let doc = "Tasks that can be `spawn`-ed from this context"; - if ctxt.is_init() { - fields.push(quote!( - #[doc = #doc] - pub spawn: Spawn - )); - - items.push(quote!( - #[doc = #doc] - #[derive(Clone, Copy)] - pub struct Spawn { - _not_send: core::marker::PhantomData<*mut ()>, - } - )); - - values.push(quote!(spawn: Spawn { _not_send: core::marker::PhantomData })); - } else { - lt = Some(quote!('a)); - - fields.push(quote!( - #[doc = #doc] - pub spawn: Spawn<'a> - )); - - let mut instant_method = None; - if ctxt.is_idle() { - items.push(quote!( - #[doc = #doc] - #[derive(Clone, Copy)] - pub struct Spawn<'a> { - priority: &'a rtic::export::Priority, - } - )); - - values.push(quote!(spawn: Spawn { priority })); - } else { - let instant_field = if app.uses_schedule() { - let m = extra.monotonic(); - - needs_instant = true; - instant_method = Some(quote!( - pub unsafe fn instant(&self) -> <#m as rtic::Monotonic>::Instant { - self.instant - } - )); - Some(quote!(instant: <#m as rtic::Monotonic>::Instant,)) - } else { - None - }; - - items.push(quote!( - /// Tasks that can be spawned from this context - #[derive(Clone, Copy)] - pub struct Spawn<'a> { - #instant_field - priority: &'a rtic::export::Priority, - } - )); - - let _instant = if needs_instant { - Some(quote!(, instant)) - } else { - None - }; - values.push(quote!( - spawn: Spawn { priority #_instant } - )); - } - - items.push(quote!( - impl<'a> Spawn<'a> { - #[doc(hidden)] - #[inline(always)] - pub unsafe fn priority(&self) -> &rtic::export::Priority { - self.priority - } - - #instant_method - } - )); - } - } - if let Context::Init = ctxt { let init = &app.inits.first().unwrap(); let late_resources = util::late_resources_ident(&init.name); @@ -283,7 +150,7 @@ pub fn codegen( }; let core = if ctxt.is_init() { - if app.uses_schedule() { + if extra.monotonic.is_some() { Some(quote!(core: rtic::Peripherals,)) } else { Some(quote!(core: rtic::export::Peripherals,)) @@ -337,11 +204,6 @@ pub fn codegen( let rq = util::rq_ident(priority); let inputs = util::inputs_ident(name); - eprintln!("app name: {}", app.name); - eprintln!("inputs {}", &inputs); - eprintln!("task name: {}", name); - eprintln!("fq {}", fq); - eprintln!("rq {}", rq); let app_name = &app.name; let app_path = quote! {crate::#app_name}; @@ -349,6 +211,7 @@ pub fn codegen( let enum_ = util::interrupt_ident(); let interrupt = &analysis.interrupts.get(&priority); + // Spawn caller items.push(quote!( #(#cfgs)* pub fn spawn(#(#args,)*) -> Result<(), #ty> { @@ -357,26 +220,71 @@ pub fn codegen( let input = #tupled; - if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) { - unsafe { + unsafe { + if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) { #app_path::#inputs .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); + + rtic::export::interrupt::free(|_| { + #app_path::#rq.enqueue_unchecked((#app_path::#t::#name, index)); + }); + + rtic::pend(#device::#enum_::#interrupt); + + Ok(()) + } else { + Err(input) } - - rtic::export::interrupt::free(|_| { - #app_path::#rq.enqueue_unchecked((#app_path::#t::#name, index)); - }); - - rtic::pend(#device::#enum_::#interrupt); - - Ok(()) - } else { - Err(input) } })); + + // Schedule caller + if extra.monotonic.is_some() { + let instants = util::instants_ident(name); + + let tq = util::tq_ident(); + let m = extra.monotonic(); + let t = util::schedule_t_ident(); + + items.push(quote!( + #(#cfgs)* + pub fn schedule( + instant: <#m as rtic::Monotonic>::Instant + #(,#args)* + ) -> Result<(), #ty> { + unsafe { + use rtic::Mutex as _; + + let input = #tupled; + if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) { + #app_path::#inputs + .get_unchecked_mut(usize::from(index)) + .as_mut_ptr() + .write(input); + + #app_path::#instants + .get_unchecked_mut(usize::from(index)) + .as_mut_ptr() + .write(instant); + + let nr = rtic::export::NotReady { + instant, + index, + task: #app_path::#t::#name, + }; + + rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr)); + + Ok(()) + } else { + Err(input) + } + } + })); + } } if !items.is_empty() { diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index 9c5f35ec37..bc87b1df48 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -12,10 +12,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Vec { - let mut items = vec![]; - - let mut seen = HashSet::<_>::new(); - for (scheduler, schedulees) in app.schedule_callers() { - let m = extra.monotonic(); - let instant = quote!(<#m as rtic::Monotonic>::Instant); - - let mut methods = vec![]; - - for name in schedulees { - let schedulee = &app.software_tasks[name]; - let cfgs = &schedulee.cfgs; - let (args, _, untupled, ty) = util::regroup_inputs(&schedulee.inputs); - let args = &args; - - if scheduler.is_init() { - // `init` uses a special `schedule` implementation; it doesn't use the - // `schedule_${name}` functions which are shared by other contexts - - let body = schedule_body::codegen(scheduler, &name, app); - - methods.push(quote!( - #(#cfgs)* - pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> { - #body - } - )); - } else { - let schedule = util::schedule_ident(name); - - if !seen.contains(name) { - // Generate a `schedule_${name}_S${sender}` function - seen.insert(name); - - let body = schedule_body::codegen(scheduler, &name, app); - - items.push(quote!( - #(#cfgs)* - pub unsafe fn #schedule( - priority: &rtic::export::Priority, - instant: #instant - #(,#args)* - ) -> Result<(), #ty> { - #body - } - )); - } - - methods.push(quote!( - #(#cfgs)* - #[inline(always)] - pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> { - unsafe { - #schedule(self.priority(), instant #(,#untupled)*) - } - } - )); - } - } - - let lt = if scheduler.is_init() { - None - } else { - Some(quote!('a)) - }; - - let scheduler = scheduler.ident(app); - debug_assert!(!methods.is_empty()); - items.push(quote!( - impl<#lt> #scheduler::Schedule<#lt> { - #(#methods)* - } - )); - } - - items -} diff --git a/macros/src/codegen/schedule_body.rs b/macros/src/codegen/schedule_body.rs deleted file mode 100644 index 644930d7d7..0000000000 --- a/macros/src/codegen/schedule_body.rs +++ /dev/null @@ -1,59 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::{ast::App, Context}; -use syn::Ident; - -use crate::codegen::util; - -pub fn codegen(scheduler: Context, name: &Ident, app: &App) -> TokenStream2 { - let schedulee = &app.software_tasks[name]; - - let fq = util::fq_ident(name); - let tq = util::tq_ident(); - let (dequeue, enqueue) = if scheduler.is_init() { - (quote!(#fq.dequeue()), quote!(#tq.enqueue_unchecked(nr);)) - } else { - ( - quote!((#fq { priority }).lock(|fq| fq.split().1.dequeue())), - quote!((#tq { priority }).lock(|tq| tq.enqueue_unchecked(nr));), - ) - }; - - let write_instant = if app.uses_schedule() { - let instants = util::instants_ident(name); - - Some(quote!( - #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant); - )) - } else { - None - }; - - let (_, tupled, _, _) = util::regroup_inputs(&schedulee.inputs); - let inputs = util::inputs_ident(name); - let t = util::schedule_t_ident(); - quote!( - unsafe { - use rtic::Mutex as _; - - let input = #tupled; - if let Some(index) = #dequeue { - #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input); - - #write_instant - - let nr = rtic::export::NotReady { - instant, - index, - task: #t::#name, - }; - - #enqueue - - Ok(()) - } else { - Err(input) - } - } - ) -} diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index b240d7aa70..f841a868f9 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -39,71 +39,50 @@ pub fn codegen( let cap_ty = util::capacity_typenum(cap, true); // Create free queues and inputs / instants buffers - if let Some(&ceiling) = analysis.free_queues.get(name) { - let fq = util::fq_ident(name); + let fq = util::fq_ident(name); - let (fq_ty, fq_expr, mk_uninit): (_, _, Box Option<_>>) = { - ( - quote!(rtic::export::SCFQ<#cap_ty>), - quote!(rtic::export::Queue(unsafe { - rtic::export::iQueue::u8_sc() - })), - Box::new(|| util::link_section_uninit(true)), - ) - }; - mod_app.push(quote!( - /// Queue version of a free-list that keeps track of empty slots in - /// the following buffers - pub static mut #fq: #fq_ty = #fq_expr; - )); + let (fq_ty, fq_expr, mk_uninit): (_, _, Box Option<_>>) = { + ( + quote!(rtic::export::SCFQ<#cap_ty>), + quote!(rtic::export::Queue(unsafe { + rtic::export::iQueue::u8_sc() + })), + Box::new(|| util::link_section_uninit(true)), + ) + }; + mod_app.push(quote!( + /// Queue version of a free-list that keeps track of empty slots in + /// the following buffers + pub static mut #fq: #fq_ty = #fq_expr; + )); - // Generate a resource proxy if needed - if let Some(ceiling) = ceiling { - mod_app.push(quote!( - struct #fq<'a> { - priority: &'a rtic::export::Priority, - } - )); + let ref elems = (0..cap) + .map(|_| quote!(core::mem::MaybeUninit::uninit())) + .collect::>(); - mod_app.push(util::impl_mutex( - extra, - &[], - false, - &fq, - fq_ty, - ceiling, - quote!(&mut #fq), - )); - } - - let ref elems = (0..cap) - .map(|_| quote!(core::mem::MaybeUninit::uninit())) - .collect::>(); - - if app.uses_schedule() { - let m = extra.monotonic(); - let instants = util::instants_ident(name); - - let uninit = mk_uninit(); - mod_app.push(quote!( - #uninit - /// Buffer that holds the instants associated to the inputs of a task - pub static mut #instants: - [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = - [#(#elems,)*]; - )); - } + if extra.monotonic.is_some() { + let m = extra.monotonic(); + let instants = util::instants_ident(name); let uninit = mk_uninit(); - let inputs = util::inputs_ident(name); mod_app.push(quote!( #uninit - /// Buffer that holds the inputs of a task - pub static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = + /// Buffer that holds the instants associated to the inputs of a task + pub static mut #instants: + [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = [#(#elems,)*]; )); } + let uninit = mk_uninit(); + let inputs_ident = util::inputs_ident(name); + mod_app.push(quote!( + #uninit + /// Buffer that holds the inputs of a task + pub static mut #inputs_ident: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = + [#(#elems,)*]; + )); + // `${task}Resources` let mut needs_lt = false; if !task.args.resources.is_empty() { diff --git a/macros/src/codegen/spawn.rs b/macros/src/codegen/spawn.rs deleted file mode 100644 index da2815160b..0000000000 --- a/macros/src/codegen/spawn.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::collections::HashSet; - -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::ast::App; - -use crate::{ - analyze::Analysis, - check::Extra, - codegen::{spawn_body, util}, -}; - -/// Generates all `${ctxt}::Spawn` methods -pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { - let mut items = vec![]; - - let mut seen = HashSet::<_>::new(); - for (spawner, spawnees) in app.spawn_callers() { - let mut methods = vec![]; - - for name in spawnees { - let spawnee = &app.software_tasks[name]; - let cfgs = &spawnee.cfgs; - let (args, _, untupled, ty) = util::regroup_inputs(&spawnee.inputs); - let args = &args; - - if spawner.is_init() { - // `init` uses a special spawn implementation; it doesn't use the `spawn_${name}` - // functions which are shared by other contexts - - let body = spawn_body::codegen(spawner, &name, app, analysis, extra); - - let let_instant = if app.uses_schedule() { - let m = extra.monotonic(); - - Some(quote!(let instant = unsafe { <#m as rtic::Monotonic>::zero() };)) - } else { - None - }; - - methods.push(quote!( - #(#cfgs)* - pub fn #name(&self #(,#args)*) -> Result<(), #ty> { - #let_instant - #body - } - )); - } else { - let spawn = util::spawn_ident(name); - - if !seen.contains(name) { - // Generate a `spawn_${name}_S${sender}` function - seen.insert(name); - - let instant = if app.uses_schedule() { - let m = extra.monotonic(); - - Some(quote!(, instant: <#m as rtic::Monotonic>::Instant)) - } else { - None - }; - - let body = spawn_body::codegen(spawner, &name, app, analysis, extra); - - items.push(quote!( - #(#cfgs)* - unsafe fn #spawn( - priority: &rtic::export::Priority - #instant - #(,#args)* - ) -> Result<(), #ty> { - #body - } - )); - } - - let (let_instant, instant) = if app.uses_schedule() { - let m = extra.monotonic(); - - ( - Some(if spawner.is_idle() { - quote!(let instant = <#m as rtic::Monotonic>::now();) - } else { - quote!(let instant = self.instant();) - }), - Some(quote!(, instant)), - ) - } else { - (None, None) - }; - - methods.push(quote!( - #(#cfgs)* - #[inline(always)] - pub fn #name(&self #(,#args)*) -> Result<(), #ty> { - unsafe { - #let_instant - #spawn(self.priority() #instant #(,#untupled)*) - } - } - )); - } - } - - let lt = if spawner.is_init() { - None - } else { - Some(quote!('a)) - }; - - let spawner = spawner.ident(app); - debug_assert!(!methods.is_empty()); - items.push(quote!( - impl<#lt> #spawner::Spawn<#lt> { - #(#methods)* - } - )); - } - - items -} diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs deleted file mode 100644 index 4ecd075767..0000000000 --- a/macros/src/codegen/spawn_body.rs +++ /dev/null @@ -1,76 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::{ast::App, Context}; -use syn::Ident; - -use crate::{analyze::Analysis, check::Extra, codegen::util}; - -pub fn codegen( - spawner: Context, - name: &Ident, - app: &App, - analysis: &Analysis, - extra: &Extra, -) -> TokenStream2 { - let spawnee = &app.software_tasks[name]; - let priority = spawnee.args.priority; - - let write_instant = if app.uses_schedule() { - let instants = util::instants_ident(name); - - Some(quote!( - #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant); - )) - } else { - None - }; - - let t = util::spawn_t_ident(priority); - let fq = util::fq_ident(name); - let rq = util::rq_ident(priority); - let (dequeue, enqueue) = if spawner.is_init() { - ( - quote!(#fq.dequeue()), - quote!(#rq.enqueue_unchecked((#t::#name, index));), - ) - } else { - ( - quote!((#fq { priority }.lock(|fq| fq.split().1.dequeue()))), - quote!((#rq { priority }.lock(|rq| { - rq.split().0.enqueue_unchecked((#t::#name, index)) - }));), - ) - }; - - let device = extra.device; - let enum_ = util::interrupt_ident(); - let interrupt = &analysis.interrupts.get(&priority); - let pend = { - quote!( - rtic::pend(#device::#enum_::#interrupt); - ) - }; - - let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs); - let inputs = util::inputs_ident(name); - quote!( - unsafe { - use rtic::Mutex as _; - - let input = #tupled; - if let Some(index) = #dequeue { - #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input); - - #write_instant - - #enqueue - - #pend - - Ok(()) - } else { - Err(input) - } - } - ) -} diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index 030158e205..e7d710c6f4 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -8,16 +8,16 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { let mut items = vec![]; - if let Some(timer_queue) = &analysis.timer_queues.first() { + if extra.monotonic.is_some() { let t = util::schedule_t_ident(); // Enumeration of `schedule`-able tasks { - let variants = timer_queue - .tasks + let variants = app + .software_tasks .iter() - .map(|name| { - let cfgs = &app.software_tasks[name].cfgs; + .map(|(name, task)| { + let cfgs = &task.cfgs; quote!( #(#cfgs)* @@ -31,7 +31,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec); items.push(quote!( #[doc = #doc] - static mut #tq: #tq_ty = rtic::export::TimerQueue( + pub static mut #tq: #tq_ty = rtic::export::TimerQueue( rtic::export::BinaryHeap( rtic::export::iBinaryHeap::new() ) ); - - struct #tq<'a> { - priority: &'a rtic::export::Priority, - } - )); - - items.push(util::impl_mutex( - extra, - &[], - false, - &tq, - tq_ty, - timer_queue.ceiling, - quote!(&mut #tq), )); } // Timer queue handler { let device = extra.device; - let arms = timer_queue - .tasks + let arms = app + .software_tasks .iter() - .map(|name| { - let task = &app.software_tasks[name]; - + .map(|(name, task)| { let cfgs = &task.cfgs; let priority = task.args.priority; let rq = util::rq_ident(priority); @@ -95,9 +84,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { - (#rq { priority: &rtic::export::Priority::new(PRIORITY) }).lock(|rq| { - rq.split().0.enqueue_unchecked((#rqt::#name, index)) - }); + rtic::export::interrupt::free(|_| #rq.split().0.enqueue_unchecked((#rqt::#name, index))); #pend } @@ -105,30 +92,18 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec>(); - let priority = timer_queue.priority; let sys_tick = util::suffixed("SysTick"); items.push(quote!( #[no_mangle] unsafe fn #sys_tick() { use rtic::Mutex as _; - /// The priority of this handler - const PRIORITY: u8 = #priority; - - rtic::export::run(PRIORITY, || { - while let Some((task, index)) = (#tq { - // NOTE dynamic priority is always the static priority at this point - priority: &rtic::export::Priority::new(PRIORITY), - }) - // NOTE `inline(always)` produces faster and smaller code - .lock(#[inline(always)] - |tq| tq.dequeue()) - { - match task { - #(#arms)* - } + while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue()) + { + match task { + #(#arms)* } - }); + } } )); } diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 2f9f3cce88..64da009694 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -207,23 +207,9 @@ pub fn rq_ident(priority: u8) -> Ident { Ident::new(&format!("P{}_RQ", priority), Span::call_site()) } -/// Generates an identifier for a "schedule" function -/// -/// The methods of the `Schedule` structs invoke these functions. -pub fn schedule_ident(name: &Ident) -> Ident { - Ident::new(&format!("schedule_{}", name.to_string()), Span::call_site()) -} - /// Generates an identifier for the `enum` of `schedule`-able tasks pub fn schedule_t_ident() -> Ident { - Ident::new(&format!("T"), Span::call_site()) -} - -/// Generates an identifier for a "spawn" function -/// -/// The methods of the `Spawn` structs invoke these functions. -pub fn spawn_ident(name: &Ident) -> Ident { - Ident::new(&format!("spawn_{}", name.to_string()), Span::call_site()) + Ident::new(&format!("SCHED_T"), Span::call_site()) } /// Generates an identifier for the `enum` of `spawn`-able tasks diff --git a/macros/src/lib.rs b/macros/src/lib.rs index e659559e9b..b39cf0b830 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -207,7 +207,6 @@ pub fn app(args: TokenStream, input: TokenStream) -> TokenStream { settings.optimize_priorities = true; settings.parse_binds = true; settings.parse_extern_interrupt = true; - settings.parse_schedule = true; let (app, analysis) = match rtic_syntax::parse(args, input, settings) { Err(e) => return e.to_compile_error().into(), From 5b8e6a22ab68e316e11641dedf5b39e20878c7b7 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 11 Oct 2020 19:41:57 +0200 Subject: [PATCH 6/9] Fixing examples and tests, modules now import user imports correctly Fmt Correct syntax crate UI test fix Fix build script Cleanup More cleanup --- .github/workflows/build.yml | 1 - examples/baseline.rs | 10 ++-- examples/capacity.rs | 14 +++--- examples/cfg.rs | 12 ++--- examples/double_schedule.rs | 14 +++--- examples/message.rs | 24 +++++----- examples/not-send.rs | 68 ---------------------------- examples/periodic.rs | 8 ++-- examples/pool.rs | 8 ++-- examples/ramfunc.rs | 12 ++--- examples/spawn.rs | 2 +- examples/t-cfg.rs | 4 +- examples/t-schedule.rs | 42 ++++++++--------- examples/t-spawn.rs | 50 ++++++++++---------- examples/t-stask-main.rs | 6 +-- examples/task.rs | 14 +++--- examples/types.rs | 19 ++------ macros/Cargo.toml | 2 +- macros/src/codegen.rs | 19 ++------ macros/src/codegen/hardware_tasks.rs | 4 +- macros/src/codegen/idle.rs | 9 +++- macros/src/codegen/module.rs | 21 ++++----- macros/src/codegen/pre_init.rs | 6 +-- macros/src/codegen/software_tasks.rs | 3 +- macros/src/codegen/timer_queue.rs | 3 +- ui/single/exception-systick-used.rs | 5 +- ui/single/locals-cfg.stderr | 8 ++-- ui/single/resources-cfg.stderr | 4 +- 28 files changed, 147 insertions(+), 245 deletions(-) delete mode 100644 examples/not-send.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8da98678e1..def72c95a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -251,7 +251,6 @@ jobs: capacity types - not-send not-sync shared-with-init diff --git a/examples/baseline.rs b/examples/baseline.rs index 3ab40dbb32..0b7e3ea0dd 100644 --- a/examples/baseline.rs +++ b/examples/baseline.rs @@ -12,19 +12,19 @@ use panic_semihosting as _; // NOTE: does NOT properly work on QEMU #[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] mod app { - #[init(spawn = [foo])] + #[init] fn init(cx: init::Context) -> init::LateResources { // omitted: initialization of `CYCCNT` hprintln!("init(baseline = {:?})", cx.start).unwrap(); // `foo` inherits the baseline of `init`: `Instant(0)` - cx.spawn.foo().unwrap(); + foo::spawn().unwrap(); init::LateResources {} } - #[task(schedule = [foo])] + #[task] fn foo(cx: foo::Context) { static mut ONCE: bool = true; @@ -39,12 +39,12 @@ mod app { } } - #[task(binds = UART0, spawn = [foo])] + #[task(binds = UART0)] fn uart0(cx: uart0::Context) { hprintln!("UART0(baseline = {:?})", cx.start).unwrap(); // `foo` inherits the baseline of `UART0`: its `start` time - cx.spawn.foo().unwrap(); + foo::spawn().unwrap(); } // RTIC requires that unused interrupts are declared in an extern block when diff --git a/examples/capacity.rs b/examples/capacity.rs index ba8b15b087..f903acbc86 100644 --- a/examples/capacity.rs +++ b/examples/capacity.rs @@ -18,14 +18,14 @@ mod app { init::LateResources {} } - #[task(binds = UART0, spawn = [foo, bar])] - fn uart0(c: uart0::Context) { - c.spawn.foo(0).unwrap(); - c.spawn.foo(1).unwrap(); - c.spawn.foo(2).unwrap(); - c.spawn.foo(3).unwrap(); + #[task(binds = UART0)] + fn uart0(_: uart0::Context) { + foo::spawn(0).unwrap(); + foo::spawn(1).unwrap(); + foo::spawn(2).unwrap(); + foo::spawn(3).unwrap(); - c.spawn.bar().unwrap(); + bar::spawn().unwrap(); } #[task(capacity = 4)] diff --git a/examples/cfg.rs b/examples/cfg.rs index d49f54c7ef..c8892eafde 100644 --- a/examples/cfg.rs +++ b/examples/cfg.rs @@ -19,10 +19,10 @@ mod app { count: u32, } - #[init(spawn = [foo])] - fn init(cx: init::Context) -> init::LateResources { - cx.spawn.foo().unwrap(); - cx.spawn.foo().unwrap(); + #[init] + fn init(_: init::Context) -> init::LateResources { + foo::spawn().unwrap(); + foo::spawn().unwrap(); init::LateResources {} } @@ -36,13 +36,13 @@ mod app { } } - #[task(capacity = 2, resources = [count], spawn = [log])] + #[task(capacity = 2, resources = [count])] fn foo(_cx: foo::Context) { #[cfg(debug_assertions)] { *_cx.resources.count += 1; - _cx.spawn.log(*_cx.resources.count).unwrap(); + log::spawn(*_cx.resources.count).unwrap(); } // this wouldn't compile in `release` mode diff --git a/examples/double_schedule.rs b/examples/double_schedule.rs index b1b78b80f6..d242c57e4b 100644 --- a/examples/double_schedule.rs +++ b/examples/double_schedule.rs @@ -16,21 +16,21 @@ mod app { nothing: (), } - #[init(spawn = [task1])] - fn init(cx: init::Context) -> init::LateResources { - cx.spawn.task1().ok(); + #[init] + fn init(_: init::Context) -> init::LateResources { + task1::spawn().ok(); init::LateResources { nothing: () } } - #[task(schedule = [task2])] + #[task] fn task1(_cx: task1::Context) { - _cx.schedule.task2(_cx.scheduled + 100.cycles()).ok(); + task2::schedule(_cx.scheduled + 100.cycles()).ok(); } - #[task(schedule = [task1])] + #[task] fn task2(_cx: task2::Context) { - _cx.schedule.task1(_cx.scheduled + 100.cycles()).ok(); + task1::schedule(_cx.scheduled + 100.cycles()).ok(); } extern "C" { diff --git a/examples/message.rs b/examples/message.rs index f9736728fa..5ff6288af9 100644 --- a/examples/message.rs +++ b/examples/message.rs @@ -10,39 +10,39 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [foo])] - fn init(c: init::Context) -> init::LateResources { - c.spawn.foo(/* no message */).unwrap(); + #[init] + fn init(_: init::Context) -> init::LateResources { + foo::spawn(/* no message */).unwrap(); init::LateResources {} } - #[task(spawn = [bar])] - fn foo(c: foo::Context) { + #[task] + fn foo(_: foo::Context) { static mut COUNT: u32 = 0; hprintln!("foo").unwrap(); - c.spawn.bar(*COUNT).unwrap(); + bar::spawn(*COUNT).unwrap(); *COUNT += 1; } - #[task(spawn = [baz])] - fn bar(c: bar::Context, x: u32) { + #[task] + fn bar(_: bar::Context, x: u32) { hprintln!("bar({})", x).unwrap(); - c.spawn.baz(x + 1, x + 2).unwrap(); + baz::spawn(x + 1, x + 2).unwrap(); } - #[task(spawn = [foo])] - fn baz(c: baz::Context, x: u32, y: u32) { + #[task] + fn baz(_: baz::Context, x: u32, y: u32) { hprintln!("baz({}, {})", x, y).unwrap(); if x + y > 4 { debug::exit(debug::EXIT_SUCCESS); } - c.spawn.foo().unwrap(); + foo::spawn().unwrap(); } // RTIC requires that unused interrupts are declared in an extern block when diff --git a/examples/not-send.rs b/examples/not-send.rs deleted file mode 100644 index 18071fc514..0000000000 --- a/examples/not-send.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! `examples/not-send.rs` - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use core::marker::PhantomData; - -use cortex_m_semihosting::debug; -use panic_halt as _; -use rtic::app; - -pub struct NotSend { - _0: PhantomData<*const ()>, -} - -#[app(device = lm3s6965)] -mod app { - use super::NotSend; - - #[resources] - struct Resources { - #[init(None)] - shared: Option, - } - - #[init(spawn = [baz, quux])] - fn init(c: init::Context) -> init::LateResources { - c.spawn.baz().unwrap(); - c.spawn.quux().unwrap(); - - init::LateResources {} - } - - #[task(spawn = [bar])] - fn foo(c: foo::Context) { - // scenario 1: message passed to task that runs at the same priority - c.spawn.bar(NotSend { _0: PhantomData }).ok(); - } - - #[task] - fn bar(_: bar::Context, _x: NotSend) { - // scenario 1 - } - - #[task(priority = 2, resources = [shared])] - fn baz(c: baz::Context) { - // scenario 2: resource shared between tasks that run at the same priority - *c.resources.shared = Some(NotSend { _0: PhantomData }); - } - - #[task(priority = 2, resources = [shared])] - fn quux(c: quux::Context) { - // scenario 2 - let _not_send = c.resources.shared.take().unwrap(); - - debug::exit(debug::EXIT_SUCCESS); - } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } -} diff --git a/examples/periodic.rs b/examples/periodic.rs index d3aedd3207..95cd14515e 100644 --- a/examples/periodic.rs +++ b/examples/periodic.rs @@ -15,21 +15,21 @@ const PERIOD: u32 = 8_000_000; #[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] mod app { - #[init(schedule = [foo])] + #[init] fn init(cx: init::Context) -> init::LateResources { // omitted: initialization of `CYCCNT` - cx.schedule.foo(cx.start + PERIOD.cycles()).unwrap(); + foo::schedule(cx.start + PERIOD.cycles()).unwrap(); init::LateResources {} } - #[task(schedule = [foo])] + #[task] fn foo(cx: foo::Context) { let now = Instant::now(); hprintln!("foo(scheduled = {:?}, now = {:?})", cx.scheduled, now).unwrap(); - cx.schedule.foo(cx.scheduled + PERIOD.cycles()).unwrap(); + foo::schedule(cx.scheduled + PERIOD.cycles()).unwrap(); } // RTIC requires that unused interrupts are declared in an extern block when diff --git a/examples/pool.rs b/examples/pool.rs index cdbabca7b3..2ad9984129 100644 --- a/examples/pool.rs +++ b/examples/pool.rs @@ -36,16 +36,16 @@ mod app { init::LateResources {} } - #[task(binds = I2C0, priority = 2, spawn = [foo, bar])] - fn i2c0(c: i2c0::Context) { + #[task(binds = I2C0, priority = 2)] + fn i2c0(_: i2c0::Context) { // claim a memory block, leave it uninitialized and .. let x = P::alloc().unwrap().freeze(); // .. send it to the `foo` task - c.spawn.foo(x).ok().unwrap(); + foo::spawn(x).ok().unwrap(); // send another block to the task `bar` - c.spawn.bar(P::alloc().unwrap().freeze()).ok().unwrap(); + bar::spawn(P::alloc().unwrap().freeze()).ok().unwrap(); } #[task] diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs index 5ff167a32f..84d633dd37 100644 --- a/examples/ramfunc.rs +++ b/examples/ramfunc.rs @@ -10,9 +10,9 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [bar])] - fn init(c: init::Context) -> init::LateResources { - c.spawn.bar().unwrap(); + #[init] + fn init(_: init::Context) -> init::LateResources { + foo::spawn().unwrap(); init::LateResources {} } @@ -28,9 +28,9 @@ mod app { // run this task from RAM #[inline(never)] #[link_section = ".data.bar"] - #[task(priority = 2, spawn = [foo])] - fn bar(c: bar::Context) { - c.spawn.foo().unwrap(); + #[task(priority = 2)] + fn bar(_: bar::Context) { + foo::spawn().unwrap(); } extern "C" { diff --git a/examples/spawn.rs b/examples/spawn.rs index 23fa178848..0720bf9540 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -10,7 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [foo])] + #[init] fn init(_c: init::Context) -> init::LateResources { foo::spawn(1, 2).unwrap(); diff --git a/examples/t-cfg.rs b/examples/t-cfg.rs index 3da20d4ee1..7076f5d71f 100644 --- a/examples/t-cfg.rs +++ b/examples/t-cfg.rs @@ -32,13 +32,13 @@ mod app { } } - #[task(resources = [foo], schedule = [quux], spawn = [quux])] + #[task(resources = [foo])] fn foo(_: foo::Context) { #[cfg(never)] static mut BAR: u32 = 0; } - #[task(priority = 3, resources = [foo], schedule = [quux], spawn = [quux])] + #[task(priority = 3, resources = [foo])] fn bar(_: bar::Context) { #[cfg(never)] static mut BAR: u32 = 0; diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs index d5a6d3ff32..7c2c420caa 100644 --- a/examples/t-schedule.rs +++ b/examples/t-schedule.rs @@ -10,45 +10,45 @@ use rtic::cyccnt::{Instant, U32Ext as _}; #[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] mod app { - #[init(schedule = [foo, bar, baz])] + #[init] fn init(c: init::Context) -> init::LateResources { - let _: Result<(), ()> = c.schedule.foo(c.start + 10.cycles()); - let _: Result<(), u32> = c.schedule.bar(c.start + 20.cycles(), 0); - let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 30.cycles(), 0, 1); + let _: Result<(), ()> = foo::schedule(c.start + 10.cycles()); + let _: Result<(), u32> = bar::schedule(c.start + 20.cycles(), 0); + let _: Result<(), (u32, u32)> = baz::schedule(c.start + 30.cycles(), 0, 1); init::LateResources {} } - #[idle(schedule = [foo, bar, baz])] - fn idle(c: idle::Context) -> ! { - let _: Result<(), ()> = c.schedule.foo(Instant::now() + 40.cycles()); - let _: Result<(), u32> = c.schedule.bar(Instant::now() + 50.cycles(), 0); - let _: Result<(), (u32, u32)> = c.schedule.baz(Instant::now() + 60.cycles(), 0, 1); + #[idle] + fn idle(_: idle::Context) -> ! { + let _: Result<(), ()> = foo::schedule(Instant::now() + 40.cycles()); + let _: Result<(), u32> = bar::schedule(Instant::now() + 50.cycles(), 0); + let _: Result<(), (u32, u32)> = baz::schedule(Instant::now() + 60.cycles(), 0, 1); loop { cortex_m::asm::nop(); } } - #[task(binds = SVCall, schedule = [foo, bar, baz])] + #[task(binds = SVCall)] fn svcall(c: svcall::Context) { - let _: Result<(), ()> = c.schedule.foo(c.start + 70.cycles()); - let _: Result<(), u32> = c.schedule.bar(c.start + 80.cycles(), 0); - let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 90.cycles(), 0, 1); + let _: Result<(), ()> = foo::schedule(c.start + 70.cycles()); + let _: Result<(), u32> = bar::schedule(c.start + 80.cycles(), 0); + let _: Result<(), (u32, u32)> = baz::schedule(c.start + 90.cycles(), 0, 1); } - #[task(binds = UART0, schedule = [foo, bar, baz])] + #[task(binds = UART0)] fn uart0(c: uart0::Context) { - let _: Result<(), ()> = c.schedule.foo(c.start + 100.cycles()); - let _: Result<(), u32> = c.schedule.bar(c.start + 110.cycles(), 0); - let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 120.cycles(), 0, 1); + let _: Result<(), ()> = foo::schedule(c.start + 100.cycles()); + let _: Result<(), u32> = bar::schedule(c.start + 110.cycles(), 0); + let _: Result<(), (u32, u32)> = baz::schedule(c.start + 120.cycles(), 0, 1); } - #[task(schedule = [foo, bar, baz])] + #[task] fn foo(c: foo::Context) { - let _: Result<(), ()> = c.schedule.foo(c.scheduled + 130.cycles()); - let _: Result<(), u32> = c.schedule.bar(c.scheduled + 140.cycles(), 0); - let _: Result<(), (u32, u32)> = c.schedule.baz(c.scheduled + 150.cycles(), 0, 1); + let _: Result<(), ()> = foo::schedule(c.scheduled + 130.cycles()); + let _: Result<(), u32> = bar::schedule(c.scheduled + 140.cycles(), 0); + let _: Result<(), (u32, u32)> = baz::schedule(c.scheduled + 150.cycles(), 0, 1); } #[task] diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs index efb748bc14..cf850e46e7 100644 --- a/examples/t-spawn.rs +++ b/examples/t-spawn.rs @@ -9,45 +9,45 @@ use panic_halt as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [foo, bar, baz])] - fn init(c: init::Context) -> init::LateResources { - let _: Result<(), ()> = c.spawn.foo(); - let _: Result<(), u32> = c.spawn.bar(0); - let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1); + #[init] + fn init(_: init::Context) -> init::LateResources { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); init::LateResources {} } - #[idle(spawn = [foo, bar, baz])] - fn idle(c: idle::Context) -> ! { - let _: Result<(), ()> = c.spawn.foo(); - let _: Result<(), u32> = c.spawn.bar(0); - let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1); + #[idle] + fn idle(_: idle::Context) -> ! { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); loop { cortex_m::asm::nop(); } } - #[task(binds = SVCall, spawn = [foo, bar, baz])] - fn svcall(c: svcall::Context) { - let _: Result<(), ()> = c.spawn.foo(); - let _: Result<(), u32> = c.spawn.bar(0); - let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1); + #[task(binds = SVCall)] + fn svcall(_: svcall::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); } - #[task(binds = UART0, spawn = [foo, bar, baz])] - fn uart0(c: uart0::Context) { - let _: Result<(), ()> = c.spawn.foo(); - let _: Result<(), u32> = c.spawn.bar(0); - let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1); + #[task(binds = UART0)] + fn uart0(_: uart0::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); } - #[task(spawn = [foo, bar, baz])] - fn foo(c: foo::Context) { - let _: Result<(), ()> = c.spawn.foo(); - let _: Result<(), u32> = c.spawn.bar(0); - let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1); + #[task] + fn foo(_: foo::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); } #[task] diff --git a/examples/t-stask-main.rs b/examples/t-stask-main.rs index 74335c18a9..3337c7d383 100644 --- a/examples/t-stask-main.rs +++ b/examples/t-stask-main.rs @@ -8,9 +8,9 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [taskmain])] - fn init(cx: init::Context) -> init::LateResources { - cx.spawn.taskmain().ok(); + #[init] + fn init(_: init::Context) -> init::LateResources { + taskmain::spawn().ok(); init::LateResources {} } diff --git a/examples/task.rs b/examples/task.rs index 80a9c4316d..f3d916f30d 100644 --- a/examples/task.rs +++ b/examples/task.rs @@ -10,27 +10,27 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965)] mod app { - #[init(spawn = [foo])] - fn init(c: init::Context) -> init::LateResources { - c.spawn.foo().unwrap(); + #[init] + fn init(_: init::Context) -> init::LateResources { + foo::spawn().unwrap(); init::LateResources {} } - #[task(spawn = [bar, baz])] - fn foo(c: foo::Context) { + #[task] + fn foo(_: foo::Context) { hprintln!("foo - start").unwrap(); // spawns `bar` onto the task scheduler // `foo` and `bar` have the same priority so `bar` will not run until // after `foo` terminates - c.spawn.bar().unwrap(); + bar::spawn().unwrap(); hprintln!("foo - middle").unwrap(); // spawns `baz` onto the task scheduler // `baz` has higher priority than `foo` so it immediately preempts `foo` - c.spawn.baz().unwrap(); + baz::spawn().unwrap(); hprintln!("foo - end").unwrap(); } diff --git a/examples/types.rs b/examples/types.rs index 251d004c4a..b55a98c660 100644 --- a/examples/types.rs +++ b/examples/types.rs @@ -17,44 +17,35 @@ mod app { shared: u32, } - #[init(schedule = [foo], spawn = [foo])] + #[init] fn init(cx: init::Context) -> init::LateResources { let _: cyccnt::Instant = cx.start; let _: rtic::Peripherals = cx.core; let _: lm3s6965::Peripherals = cx.device; - let _: init::Schedule = cx.schedule; - let _: init::Spawn = cx.spawn; debug::exit(debug::EXIT_SUCCESS); init::LateResources {} } - #[idle(schedule = [foo], spawn = [foo])] - fn idle(cx: idle::Context) -> ! { - let _: idle::Schedule = cx.schedule; - let _: idle::Spawn = cx.spawn; - + #[idle] + fn idle(_: idle::Context) -> ! { loop { cortex_m::asm::nop(); } } - #[task(binds = UART0, resources = [shared], schedule = [foo], spawn = [foo])] + #[task(binds = UART0, resources = [shared])] fn uart0(cx: uart0::Context) { let _: cyccnt::Instant = cx.start; let _: resources::shared = cx.resources.shared; - let _: uart0::Schedule = cx.schedule; - let _: uart0::Spawn = cx.spawn; } - #[task(priority = 2, resources = [shared], schedule = [foo], spawn = [foo])] + #[task(priority = 2, resources = [shared])] fn foo(cx: foo::Context) { let _: cyccnt::Instant = cx.scheduled; let _: &mut u32 = cx.resources.shared; let _: foo::Resources = cx.resources; - let _: foo::Schedule = cx.schedule; - let _: foo::Spawn = cx.spawn; } // RTIC requires that unused interrupts are declared in an extern block when diff --git a/macros/Cargo.toml b/macros/Cargo.toml index f8a0523ee7..1413c6f370 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,5 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = { path = "../../rtic-syntax", version = "0.4.0" } +rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "no_spawn_no_schedule", version = "0.4.0" } diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 2be265d442..9ea6165599 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -15,11 +15,7 @@ mod post_init; mod pre_init; mod resources; mod resources_struct; -// mod schedule; -// mod schedule_body; mod software_tasks; -// mod spawn; -// mod spawn_body; mod timer_queue; mod util; @@ -115,17 +111,12 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { ) = software_tasks::codegen(app, analysis, extra); let mod_app_dispatchers = dispatchers::codegen(app, analysis, extra); - - // let mod_app_spawn = spawn::codegen(app, analysis, extra); - let mod_app_timer_queue = timer_queue::codegen(app, analysis, extra); - - // let mod_app_schedule = schedule::codegen(app, extra); - - let user_imports = app.user_imports.clone(); - let user_code = app.user_code.clone(); + let user_imports = &app.user_imports; + let user_code = &app.user_code; let name = &app.name; let device = extra.device; + quote!( #(#user)* @@ -170,12 +161,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { #(#mod_app_dispatchers)* - // #(#mod_app_spawn)* - #(#mod_app_timer_queue)* - // #(#mod_app_schedule)* - #(#mains)* } ) diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index d8c228e54c..ebfa69b9d0 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -32,9 +32,7 @@ pub fn codegen( let mut hardware_tasks_imports = vec![]; for (name, task) in &app.hardware_tasks { - let (let_instant, instant) = if extra.monotonic.is_some() { - let m = extra.monotonic(); - + let (let_instant, instant) = if let Some(m) = extra.monotonic { ( Some(quote!(let instant = <#m as rtic::Monotonic>::now();)), Some(quote!(, instant)), diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs index 78fac96b10..5e73329f06 100644 --- a/macros/src/codegen/idle.rs +++ b/macros/src/codegen/idle.rs @@ -62,8 +62,13 @@ pub fn codegen( root_idle.push(locals); } - root_idle.push(module::codegen(Context::Idle, needs_lt, app,analysis, extra)); - + root_idle.push(module::codegen( + Context::Idle, + needs_lt, + app, + analysis, + extra, + )); let attrs = &idle.attrs; let context = &idle.context; diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 979c63caba..e3b0ed9b98 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -21,9 +21,7 @@ pub fn codegen( let mut lt = None; match ctxt { Context::Init => { - if extra.monotonic.is_some() { - let m = extra.monotonic(); - + if let Some(m) = extra.monotonic { fields.push(quote!( /// System start time = `Instant(0 /* cycles */)` pub start: <#m as rtic::Monotonic>::Instant @@ -67,9 +65,7 @@ pub fn codegen( Context::Idle => {} Context::HardwareTask(..) => { - if extra.monotonic.is_some() { - let m = extra.monotonic(); - + if let Some(m) = extra.monotonic { fields.push(quote!( /// Time at which this handler started executing pub start: <#m as rtic::Monotonic>::Instant @@ -82,9 +78,7 @@ pub fn codegen( } Context::SoftwareTask(..) => { - if extra.monotonic.is_some() { - let m = extra.monotonic(); - + if let Some(m) = extra.monotonic { fields.push(quote!( /// The time at which this task was scheduled to run pub scheduled: <#m as rtic::Monotonic>::Instant @@ -242,11 +236,10 @@ pub fn codegen( })); // Schedule caller - if extra.monotonic.is_some() { + if let Some(m) = extra.monotonic { let instants = util::instants_ident(name); let tq = util::tq_ident(); - let m = extra.monotonic(); let t = util::schedule_t_ident(); items.push(quote!( @@ -288,10 +281,16 @@ pub fn codegen( } if !items.is_empty() { + let user_imports = &app.user_imports; + quote!( #[allow(non_snake_case)] #[doc = #doc] pub mod #name { + #( + #[allow(unused_imports)] + #user_imports + )* #(#items)* } ) diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index bc87b1df48..02afdf95ae 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -12,12 +12,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec>(); - if extra.monotonic.is_some() { - let m = extra.monotonic(); + if let Some(m) = extra.monotonic { let instants = util::instants_ident(name); let uninit = mk_uninit(); diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index e7d710c6f4..ae864364f0 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -8,7 +8,7 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { let mut items = vec![]; - if extra.monotonic.is_some() { + if let Some(m) = extra.monotonic { let t = util::schedule_t_ident(); // Enumeration of `schedule`-able tasks @@ -42,7 +42,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec` --> $DIR/resources-cfg.rs:47:21 From da76894d752d1a8633ad5b7ad2c3c2ee2871ee84 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 15 Oct 2020 17:56:29 +0200 Subject: [PATCH 7/9] Updated syntax crate --- macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 1413c6f370..7c52124c46 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,5 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "no_spawn_no_schedule", version = "0.4.0" } +rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "no_spawn_no_schedule", version = "0.5.0-alpha.0" } From b5779d834e2ecd97970c0915f2edd0c8030c693d Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 15 Oct 2020 18:06:03 +0200 Subject: [PATCH 8/9] Fix comments in examples --- examples/spawn.rs | 2 +- examples/spawn2.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/spawn.rs b/examples/spawn.rs index 0720bf9540..041018ab0b 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -1,4 +1,4 @@ -//! examples/message.rs +//! examples/spawn.rs #![deny(unsafe_code)] #![deny(warnings)] diff --git a/examples/spawn2.rs b/examples/spawn2.rs index 2998d16cf8..b50a3ee671 100644 --- a/examples/spawn2.rs +++ b/examples/spawn2.rs @@ -1,4 +1,4 @@ -//! examples/message.rs +//! examples/spawn2.rs #![deny(unsafe_code)] #![deny(warnings)] From c5b5ea60e826a7b95bd04055a722ecdc332df1d0 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 15 Oct 2020 18:12:39 +0200 Subject: [PATCH 9/9] Use master branch on syntax --- macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 7c52124c46..91f057b6d9 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,5 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "no_spawn_no_schedule", version = "0.5.0-alpha.0" } +rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.5.0-alpha.0" }