diff options
Diffstat (limited to 'macros/src/codegen/dispatchers.rs')
-rw-r--r-- | macros/src/codegen/dispatchers.rs | 294 |
1 files changed, 132 insertions, 162 deletions
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 60b8626e..fdeb6155 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -8,181 +8,151 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> { let mut items = vec![]; - for (&receiver, dispatchers) in &analysis.channels { - let interrupts = &analysis.interrupts[&receiver]; + let interrupts = &analysis.interrupts; + + for (&level, channel) in &analysis.channels { + let mut stmts = vec![]; + + let variants = channel + .tasks + .iter() + .map(|name| { + let cfgs = &app.software_tasks[name].cfgs; + + quote!( + #(#cfgs)* + #name + ) + }) + .collect::<Vec<_>>(); + + let doc = format!( + "Software tasks to be dispatched at priority level {}", + level, + ); + let t = util::spawn_t_ident(level); + items.push(quote!( + #[allow(non_camel_case_types)] + #[derive(Clone, Copy)] + #[doc = #doc] + enum #t { + #(#variants,)* + } + )); + + let n = util::capacity_typenum(channel.capacity, true); + let rq = util::rq_ident(level); + let (rq_ty, rq_expr, section) = { + ( + quote!(rtic::export::SCRQ<#t, #n>), + quote!(rtic::export::Queue(unsafe { + rtic::export::iQueue::u8_sc() + })), + util::link_section("bss"), + ) + }; + + let doc = format!( + "Queue of tasks ready to be dispatched at priority level {}", + level + ); + items.push(quote!( + #[doc = #doc] + #section + static mut #rq: #rq_ty = #rq_expr; + )); + + if let Some(ceiling) = channel.ceiling { + items.push(quote!( + struct #rq<'a> { + priority: &'a rtic::export::Priority, + } + )); - for (&level, channels) in dispatchers { - let mut stmts = vec![]; + items.push(util::impl_mutex( + extra, + &[], + false, + &rq, + rq_ty, + ceiling, + quote!(&mut #rq), + )); + } - for (&sender, channel) in channels { - let cfg_sender = util::cfg_core(sender, app.args.cores); + let arms = channel + .tasks + .iter() + .map(|name| { + let task = &app.software_tasks[name]; + let cfgs = &task.cfgs; + let fq = util::fq_ident(name); + let inputs = util::inputs_ident(name); + let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs); - let variants = channel - .tasks - .iter() - .map(|name| { - let cfgs = &app.software_tasks[name].cfgs; + let (let_instant, instant) = if app.uses_schedule() { + let instants = util::instants_ident(name); - quote!( - #(#cfgs)* - #name - ) - }) - .collect::<Vec<_>>(); - - let doc = format!( - "Software tasks spawned from core #{} to be dispatched at priority level {} by core #{}", - sender, level, receiver, - ); - let t = util::spawn_t_ident(receiver, level, sender); - items.push(quote!( - #[allow(non_camel_case_types)] - #[derive(Clone, Copy)] - #[doc = #doc] - enum #t { - #(#variants,)* - } - )); - - let n = util::capacity_typenum(channel.capacity, true); - let rq = util::rq_ident(receiver, level, sender); - let (rq_attr, rq_ty, rq_expr, section) = if sender == receiver { ( - cfg_sender.clone(), - quote!(rtic::export::SCRQ<#t, #n>), - quote!(rtic::export::Queue(unsafe { - rtic::export::iQueue::u8_sc() - })), - util::link_section("bss", sender), + quote!( + let instant = + #instants.get_unchecked(usize::from(index)).as_ptr().read(); + ), + quote!(, instant), ) } else { - let shared = if cfg!(feature = "heterogeneous") { - Some(quote!(#[rtic::export::shared])) - } else { - None - }; - - ( - shared, - quote!(rtic::export::MCRQ<#t, #n>), - quote!(rtic::export::Queue(rtic::export::iQueue::u8())), - None, - ) + (quote!(), quote!()) }; - let doc = format!( - "Queue of tasks sent by core #{} ready to be dispatched by core #{} at priority level {}", - sender, - receiver, - level - ); - items.push(quote!( - #[doc = #doc] - #rq_attr - #section - static mut #rq: #rq_ty = #rq_expr; - )); - - if let Some(ceiling) = channel.ceiling { - items.push(quote!( - #cfg_sender - struct #rq<'a> { - priority: &'a rtic::export::Priority, - } - )); - - items.push(util::impl_mutex( - extra, - &[], - cfg_sender.as_ref(), - false, - &rq, - rq_ty, - ceiling, - quote!(&mut #rq), - )); - } - - let arms = channel - .tasks - .iter() - .map(|name| { - let task = &app.software_tasks[name]; - let cfgs = &task.cfgs; - let fq = util::fq_ident(name, sender); - let inputs = util::inputs_ident(name, sender); - let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs); - - let (let_instant, instant) = if app.uses_schedule(receiver) { - let instants = util::instants_ident(name, sender); - - ( - quote!( - let instant = - #instants.get_unchecked(usize::from(index)).as_ptr().read(); - ), - quote!(, instant), - ) - } else { - (quote!(), quote!()) - }; - - let locals_new = if task.locals.is_empty() { - quote!() - } else { - quote!(#name::Locals::new(),) - }; + let locals_new = if task.locals.is_empty() { + quote!() + } else { + quote!(#name::Locals::new(),) + }; - quote!( - #(#cfgs)* - #t::#name => { - let #tupled = - #inputs.get_unchecked(usize::from(index)).as_ptr().read(); - #let_instant - #fq.split().0.enqueue_unchecked(index); - let priority = &rtic::export::Priority::new(PRIORITY); - crate::#name( - #locals_new - #name::Context::new(priority #instant) - #(,#pats)* - ) - } + quote!( + #(#cfgs)* + #t::#name => { + let #tupled = + #inputs.get_unchecked(usize::from(index)).as_ptr().read(); + #let_instant + #fq.split().0.enqueue_unchecked(index); + let priority = &rtic::export::Priority::new(PRIORITY); + crate::#name( + #locals_new + #name::Context::new(priority #instant) + #(,#pats)* ) - }) - .collect::<Vec<_>>(); - - stmts.push(quote!( - while let Some((task, index)) = #rq.split().1.dequeue() { - match task { - #(#arms)* - } } - )); - } - - let doc = format!( - "Interrupt handler used by core #{} to dispatch tasks at priority {}", - receiver, level - ); - let cfg_receiver = util::cfg_core(receiver, app.args.cores); - let section = util::link_section("text", receiver); - let interrupt = util::suffixed(&interrupts[&level].to_string(), receiver); - items.push(quote!( - #[allow(non_snake_case)] - #[doc = #doc] - #[no_mangle] - #cfg_receiver - #section - unsafe fn #interrupt() { - /// The priority of this interrupt handler - const PRIORITY: u8 = #level; - - rtic::export::run(PRIORITY, || { - #(#stmts)* - }); + ) + }) + .collect::<Vec<_>>(); + + stmts.push(quote!( + while let Some((task, index)) = #rq.split().1.dequeue() { + match task { + #(#arms)* } - )); - } + } + )); + + let doc = format!("Interrupt handler to dispatch tasks at priority {}", level); + let section = util::link_section("text"); + let interrupt = util::suffixed(&interrupts[&level].to_string()); + items.push(quote!( + #[allow(non_snake_case)] + #[doc = #doc] + #[no_mangle] + #section + unsafe fn #interrupt() { + /// The priority of this interrupt handler + const PRIORITY: u8 = #level; + + rtic::export::run(PRIORITY, || { + #(#stmts)* + }); + } + )); } items |