diff options
Diffstat (limited to 'macros/src/codegen')
-rw-r--r-- | macros/src/codegen/dispatchers.rs | 24 | ||||
-rw-r--r-- | macros/src/codegen/hardware_tasks.rs | 5 | ||||
-rw-r--r-- | macros/src/codegen/idle.rs | 8 | ||||
-rw-r--r-- | macros/src/codegen/init.rs | 8 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 260 | ||||
-rw-r--r-- | macros/src/codegen/pre_init.rs | 10 | ||||
-rw-r--r-- | macros/src/codegen/schedule.rs | 90 | ||||
-rw-r--r-- | macros/src/codegen/schedule_body.rs | 59 | ||||
-rw-r--r-- | macros/src/codegen/software_tasks.rs | 89 | ||||
-rw-r--r-- | macros/src/codegen/spawn.rs | 121 | ||||
-rw-r--r-- | macros/src/codegen/spawn_body.rs | 75 | ||||
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 70 | ||||
-rw-r--r-- | macros/src/codegen/util.rs | 16 |
13 files changed, 194 insertions, 641 deletions
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 300aa996..bf6986b8 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<TokenStream #[allow(non_camel_case_types)] #[derive(Clone, Copy)] #[doc = #doc] - enum #t { + pub enum #t { #(#variants,)* } )); @@ -57,27 +57,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream ); items.push(quote!( #[doc = #doc] - static mut #rq: #rq_ty = #rq_expr; + pub static mut #rq: #rq_ty = #rq_expr; )); - if let Some(ceiling) = channel.ceiling { - items.push(quote!( - struct #rq<'a> { - 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<TokenStream let inputs = util::inputs_ident(name); let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs); - let (let_instant, instant) = if app.uses_schedule() { + let (let_instant, instant) = if extra.monotonic.is_some() { let instants = util::instants_ident(name); ( diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index 25f1df41..ebfa69b9 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 app.uses_schedule() { - 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)), @@ -97,6 +95,7 @@ pub fn codegen( Context::HardwareTask(name), needs_lt, app, + analysis, extra, )); diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs index 2e2932d7..5e73329f 100644 --- a/macros/src/codegen/idle.rs +++ b/macros/src/codegen/idle.rs @@ -62,7 +62,13 @@ pub fn codegen( root_idle.push(locals); } - root_idle.push(module::codegen(Context::Idle, needs_lt, app, 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/init.rs b/macros/src/codegen/init.rs index 8942439b..465a927d 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -116,7 +116,13 @@ pub fn codegen( quote!(let late = crate::#name(#(#locals_new,)* #name::Context::new(core.into()));), ); - root_init.push(module::codegen(Context::Init, needs_lt, app, extra)); + root_init.push(module::codegen( + Context::Init, + needs_lt, + app, + analysis, + extra, + )); (mod_app, root_init, user_init, user_init_imports, call_init) } else { diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 3d90cbd3..e3b0ed9b 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -2,9 +2,15 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::{ast::App, Context}; -use crate::{check::Extra, codegen::util}; - -pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> TokenStream2 { +use crate::{analyze::Analysis, check::Extra, codegen::util}; + +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![]; @@ -15,9 +21,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> 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 @@ -61,9 +65,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> Context::Idle => {} Context::HardwareTask(..) => { - if app.uses_schedule() { - 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 @@ -76,9 +78,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> } Context::SoftwareTask(..) => { - if app.uses_schedule() { - 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 @@ -126,139 +126,6 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> 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); @@ -316,11 +183,114 @@ 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); + + 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); + + // Spawn caller + items.push(quote!( + #(#cfgs)* + pub fn spawn(#(#args,)*) -> Result<(), #ty> { + // #let_instant // do we need it? + use rtic::Mutex as _; + + let input = #tupled; + + 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) + } + } + + })); + + // Schedule caller + if let Some(m) = extra.monotonic { + let instants = util::instants_ident(name); + + let tq = util::tq_ident(); + 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() { + 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 2aaf9ebd..17c9c2f4 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<TokenStream stmts.push(quote!(rtic::export::interrupt::disable();)); // Populate the FreeQueue - for fq in &analysis.free_queues { - // Get the task name - let name = fq.0; - let task = &app.software_tasks[name]; + for (name, task) in &app.software_tasks { let cap = task.args.capacity; - let fq_ident = util::fq_ident(name); stmts.push(quote!( @@ -81,8 +77,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream } // Initialize the SysTick if there exist a TimerQueue - if let Some(tq) = analysis.timer_queues.first() { - let priority = tq.priority; + if extra.monotonic.is_some() { + let priority = analysis.channels.keys().max().unwrap(); // Compile time assert that this priority is supported by the device stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];)); diff --git a/macros/src/codegen/schedule.rs b/macros/src/codegen/schedule.rs deleted file mode 100644 index 5a887496..00000000 --- a/macros/src/codegen/schedule.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::collections::HashSet; - -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::ast::App; - -use crate::{ - check::Extra, - codegen::{schedule_body, util}, -}; - -/// Generates all `${ctxt}::Schedule` methods -pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> { - 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 644930d7..00000000 --- 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 4ae37e4e..9918dea1 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -39,71 +39,49 @@ 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_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> 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 - static mut #fq: #fq_ty = #fq_expr; - )); + let fq = util::fq_ident(name); + + let (fq_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> 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, - } - )); - - 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::<Vec<_>>(); - let ref elems = (0..cap) - .map(|_| quote!(core::mem::MaybeUninit::uninit())) - .collect::<Vec<_>>(); - - 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 - static mut #instants: - [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = - [#(#elems,)*]; - )); - } + if let Some(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 - 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() { @@ -161,6 +139,7 @@ pub fn codegen( Context::SoftwareTask(name), needs_lt, app, + analysis, extra, )); } diff --git a/macros/src/codegen/spawn.rs b/macros/src/codegen/spawn.rs deleted file mode 100644 index da281516..00000000 --- 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<TokenStream2> { - 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 f29393a6..00000000 --- a/macros/src/codegen/spawn_body.rs +++ /dev/null @@ -1,75 +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 enum_ = util::interrupt_ident(); - let interrupt = &analysis.interrupts.get(&priority); - let pend = { - quote!( - rtic::pend(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#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 0abbf49d..c898a7fd 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<TokenStream2> { let mut items = vec![]; - if let Some(timer_queue) = &analysis.timer_queues.first() { + if let Some(m) = extra.monotonic { 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<TokenStream #[doc = #doc] #[allow(non_camel_case_types)] #[derive(Clone, Copy)] - enum #t { + pub enum #t { #(#variants,)* } )); @@ -42,42 +42,30 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream // Static variable and resource proxy { let doc = format!("Timer queue"); - let m = extra.monotonic(); - let n = util::capacity_typenum(timer_queue.capacity, false); + let cap = app + .software_tasks + .iter() + .map(|(_name, task)| task.args.capacity) + .sum(); + let n = util::capacity_typenum(cap, false); let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>); 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 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); @@ -94,9 +82,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream quote!( #(#cfgs)* #t::#name => { - (#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 } @@ -104,30 +90,18 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream }) .collect::<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 41ee3ca7..f04ccb23 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 |