cortex_m_rtic_macros/codegen/
dispatchers.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use rtic_syntax::ast::App;
4
5use crate::{analyze::Analysis, check::Extra, codegen::util};
6
7/// Generates task dispatchers
8pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
9    let mut items = vec![];
10
11    let interrupts = &analysis.interrupts;
12
13    for (&level, channel) in &analysis.channels {
14        let mut stmts = vec![];
15
16        let variants = channel
17            .tasks
18            .iter()
19            .map(|name| {
20                let cfgs = &app.software_tasks[name].cfgs;
21
22                quote!(
23                    #(#cfgs)*
24                    #name
25                )
26            })
27            .collect::<Vec<_>>();
28
29        // For future use
30        // let doc = format!(
31        //     "Software tasks to be dispatched at priority level {}",
32        //     level,
33        // );
34        let t = util::spawn_t_ident(level);
35        items.push(quote!(
36            #[allow(non_snake_case)]
37            #[allow(non_camel_case_types)]
38            #[derive(Clone, Copy)]
39            // #[doc = #doc]
40            #[doc(hidden)]
41            pub enum #t {
42                #(#variants,)*
43            }
44        ));
45
46        let n = util::capacity_literal(channel.capacity as usize + 1);
47        let rq = util::rq_ident(level);
48        let (rq_ty, rq_expr) = {
49            (
50                quote!(rtic::export::SCRQ<#t, #n>),
51                quote!(rtic::export::Queue::new()),
52            )
53        };
54
55        // For future use
56        // let doc = format!(
57        //     "Queue of tasks ready to be dispatched at priority level {}",
58        //     level
59        // );
60        items.push(quote!(
61            #[doc(hidden)]
62            #[allow(non_camel_case_types)]
63            #[allow(non_upper_case_globals)]
64            static #rq: rtic::RacyCell<#rq_ty> = rtic::RacyCell::new(#rq_expr);
65        ));
66
67        let arms = channel
68            .tasks
69            .iter()
70            .map(|name| {
71                let task = &app.software_tasks[name];
72                let cfgs = &task.cfgs;
73                let fq = util::fq_ident(name);
74                let inputs = util::inputs_ident(name);
75                let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
76
77                quote!(
78                    #(#cfgs)*
79                    #t::#name => {
80                        let #tupled =
81                            (&*#inputs
82                            .get())
83                            .get_unchecked(usize::from(index))
84                            .as_ptr()
85                            .read();
86                        (&mut *#fq.get_mut()).split().0.enqueue_unchecked(index);
87                        let priority = &rtic::export::Priority::new(PRIORITY);
88                        #name(
89                            #name::Context::new(priority)
90                            #(,#pats)*
91                        )
92                    }
93                )
94            })
95            .collect::<Vec<_>>();
96
97        stmts.push(quote!(
98            while let Some((task, index)) = (&mut *#rq.get_mut()).split().1.dequeue() {
99                match task {
100                    #(#arms)*
101                }
102            }
103        ));
104
105        let doc = format!("Interrupt handler to dispatch tasks at priority {}", level);
106        let interrupt = util::suffixed(&interrupts[&level].0.to_string());
107        let attribute = &interrupts[&level].1.attrs;
108        items.push(quote!(
109            #[allow(non_snake_case)]
110            #[doc = #doc]
111            #[no_mangle]
112            #(#attribute)*
113            unsafe fn #interrupt() {
114                /// The priority of this interrupt handler
115                const PRIORITY: u8 = #level;
116
117                rtic::export::run(PRIORITY, || {
118                    #(#stmts)*
119                });
120            }
121        ));
122    }
123
124    items
125}