rtic_macros/codegen/
hardware_tasks.rs

1use crate::syntax::{ast::App, Context};
2use crate::{
3    analyze::Analysis,
4    codegen::{
5        bindings::{interrupt_entry, interrupt_exit, handler_config},
6        local_resources_struct, module, shared_resources_struct,
7    },
8};
9use proc_macro2::TokenStream as TokenStream2;
10use quote::quote;
11
12/// Generate support code for hardware tasks (`#[exception]`s and `#[interrupt]`s)
13pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
14    let mut mod_app = vec![];
15    let mut root = vec![];
16    let mut user_tasks = vec![];
17
18    for (name, task) in &app.hardware_tasks {
19        let symbol = task.args.binds.clone();
20        let priority = task.args.priority;
21        let cfgs = &task.cfgs;
22        let attrs = &task.attrs;
23        let entry_stmts = interrupt_entry(app, analysis);
24        let exit_stmts = interrupt_exit(app, analysis);
25        let config = handler_config(app, analysis, symbol.clone());
26
27        mod_app.push(quote!(
28            #[allow(non_snake_case)]
29            #[no_mangle]
30            #(#attrs)*
31            #(#cfgs)*
32            #(#config)*
33            unsafe fn #symbol() {
34                #(#entry_stmts)*
35
36                const PRIORITY: u8 = #priority;
37
38                rtic::export::run(PRIORITY, || {
39                    #name(
40                        #name::Context::new()
41                    )
42                });
43
44                #(#exit_stmts)*
45            }
46        ));
47
48        // `${task}Locals`
49        if !task.args.local_resources.is_empty() {
50            let (item, constructor) =
51                local_resources_struct::codegen(Context::HardwareTask(name), app);
52
53            root.push(item);
54
55            mod_app.push(constructor);
56        }
57
58        // `${task}Resources`
59        if !task.args.shared_resources.is_empty() {
60            let (item, constructor) =
61                shared_resources_struct::codegen(Context::HardwareTask(name), app);
62
63            root.push(item);
64
65            mod_app.push(constructor);
66        }
67
68        // Module generation...
69
70        root.push(module::codegen(Context::HardwareTask(name), app, analysis));
71
72        // End module generation
73
74        if !task.is_extern {
75            let attrs = &task.attrs;
76            let context = &task.context;
77            let stmts = &task.stmts;
78            user_tasks.push(quote!(
79                #(#attrs)*
80                #[allow(non_snake_case)]
81                fn #name(#context: #name::Context) {
82                    use rtic::Mutex as _;
83                    use rtic::mutex::prelude::*;
84
85                    #(#stmts)*
86                }
87            ));
88        }
89    }
90
91    quote!(
92        #(#mod_app)*
93
94        #(#root)*
95
96        #(#user_tasks)*
97    )
98}