rtic_macros/codegen/
async_dispatchers.rs
1use crate::syntax::ast::App;
2use crate::{
3 analyze::Analysis,
4 codegen::{
5 bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit, interrupt_mod},
6 util,
7 },
8};
9use proc_macro2::TokenStream as TokenStream2;
10use quote::quote;
11
12pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
14 let mut items = vec![];
15
16 let interrupts = &analysis.interrupts;
17
18 for (name, _) in app.software_tasks.iter() {
20 let exec_name = util::internal_task_ident(name, "EXEC");
21
22 items.push(quote!(
23 #[allow(non_upper_case_globals)]
24 static #exec_name: rtic::export::executor::AsyncTaskExecutorPtr =
25 rtic::export::executor::AsyncTaskExecutorPtr::new();
26 ));
27 }
28
29 for (&level, channel) in &analysis.channels {
30 let mut stmts = vec![];
31
32 let dispatcher_name = if level > 0 {
33 util::suffixed(&interrupts.get(&level).expect("UNREACHABLE").0.to_string())
34 } else {
35 util::zero_prio_dispatcher_ident()
36 };
37
38 let pend_interrupt = if level > 0 {
39 let int_mod = interrupt_mod(app);
40
41 quote!(rtic::export::pend(#int_mod::#dispatcher_name);)
42 } else {
43 quote!()
45 };
46
47 for name in channel.tasks.iter() {
48 let exec_name = util::internal_task_ident(name, "EXEC");
49 let from_ptr_n_args =
50 util::from_ptr_n_args_ident(app.software_tasks[name].inputs.len());
51
52 stmts.push(quote!(
57 let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name);
58 exec.poll(|| {
59 let exec = rtic::export::executor::AsyncTaskExecutor::#from_ptr_n_args(#name, &#exec_name);
60 exec.set_pending();
61 #pend_interrupt
62 });
63 ));
64 }
65
66 if level > 0 {
67 let doc = format!("Interrupt handler to dispatch async tasks at priority {level}");
68 let attribute = &interrupts.get(&level).expect("UNREACHABLE").1.attrs;
69 let entry_stmts = interrupt_entry(app, analysis);
70 let exit_stmts = interrupt_exit(app, analysis);
71 let async_entry_stmts = async_entry(app, analysis, dispatcher_name.clone());
72 let config = handler_config(app, analysis, dispatcher_name.clone());
73 items.push(quote!(
74 #[allow(non_snake_case)]
75 #[doc = #doc]
76 #[no_mangle]
77 #(#attribute)*
78 #(#config)*
79 unsafe fn #dispatcher_name() {
80 #(#entry_stmts)*
81 #(#async_entry_stmts)*
82
83 const PRIORITY: u8 = #level;
85
86 rtic::export::run(PRIORITY, || {
87 #(#stmts)*
88 });
89
90 #(#exit_stmts)*
91 }
92 ));
93 } else {
94 items.push(quote!(
95 #[allow(non_snake_case)]
96 unsafe fn #dispatcher_name() -> ! {
97 loop {
98 #(#stmts)*
99 }
100 }
101 ));
102 }
103 }
104
105 quote!(#(#items)*)
106}