aboutsummaryrefslogtreecommitdiff
path: root/rtic/macros/src/codegen/async_dispatchers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rtic/macros/src/codegen/async_dispatchers.rs')
-rw-r--r--rtic/macros/src/codegen/async_dispatchers.rs89
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)*)
+}