diff options
Diffstat (limited to 'rtic/macros/src/codegen/async_dispatchers.rs')
-rw-r--r-- | rtic/macros/src/codegen/async_dispatchers.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/rtic/macros/src/codegen/async_dispatchers.rs b/rtic/macros/src/codegen/async_dispatchers.rs new file mode 100644 index 00000000..a12ad325 --- /dev/null +++ b/rtic/macros/src/codegen/async_dispatchers.rs @@ -0,0 +1,89 @@ +use crate::syntax::ast::App; +use crate::{analyze::Analysis, codegen::util}; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +/// Generates task dispatchers +pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { + let mut items = vec![]; + + let interrupts = &analysis.interrupts; + + // Generate executor definition and priority in global scope + for (name, _) in app.software_tasks.iter() { + let type_name = util::internal_task_ident(name, "F"); + let exec_name = util::internal_task_ident(name, "EXEC"); + + items.push(quote!( + #[allow(non_camel_case_types)] + type #type_name = impl core::future::Future; + #[allow(non_upper_case_globals)] + static #exec_name: rtic::export::executor::AsyncTaskExecutor<#type_name> = + rtic::export::executor::AsyncTaskExecutor::new(); + )); + } + + for (&level, channel) in &analysis.channels { + let mut stmts = vec![]; + + let dispatcher_name = if level > 0 { + util::suffixed(&interrupts.get(&level).expect("UNREACHABLE").0.to_string()) + } else { + util::zero_prio_dispatcher_ident() + }; + + let pend_interrupt = if level > 0 { + let device = &app.args.device; + let enum_ = util::interrupt_ident(); + + quote!(rtic::pend(#device::#enum_::#dispatcher_name);) + } else { + // For 0 priority tasks we don't need to pend anything + quote!() + }; + + for name in channel.tasks.iter() { + let exec_name = util::internal_task_ident(name, "EXEC"); + // TODO: Fix cfg + // let task = &app.software_tasks[name]; + // let cfgs = &task.cfgs; + + stmts.push(quote!( + #exec_name.poll(|| { + #exec_name.set_pending(); + #pend_interrupt + }); + )); + } + + if level > 0 { + let doc = format!("Interrupt handler to dispatch async tasks at priority {level}"); + let attribute = &interrupts.get(&level).expect("UNREACHABLE").1.attrs; + items.push(quote!( + #[allow(non_snake_case)] + #[doc = #doc] + #[no_mangle] + #(#attribute)* + unsafe fn #dispatcher_name() { + /// The priority of this interrupt handler + const PRIORITY: u8 = #level; + + rtic::export::run(PRIORITY, || { + #(#stmts)* + }); + } + )); + } else { + items.push(quote!( + #[allow(non_snake_case)] + unsafe fn #dispatcher_name() -> ! { + loop { + #(#stmts)* + } + } + )); + } + } + + quote!(#(#items)*) +} |