cortex_m_rtic_macros/
codegen.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3use rtic_syntax::ast::App;
4
5use crate::{analyze::Analysis, check::Extra};
6
7mod assertions;
8mod dispatchers;
9mod hardware_tasks;
10mod idle;
11mod init;
12mod local_resources;
13mod local_resources_struct;
14mod module;
15mod post_init;
16mod pre_init;
17mod shared_resources;
18mod shared_resources_struct;
19mod software_tasks;
20mod timer_queue;
21mod util;
22
23#[allow(clippy::too_many_lines)]
24pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
25    let mut mod_app = vec![];
26    let mut mains = vec![];
27    let mut root = vec![];
28    let mut user = vec![];
29
30    // Generate the `main` function
31    let assertion_stmts = assertions::codegen(app, analysis, extra);
32
33    let pre_init_stmts = pre_init::codegen(app, analysis, extra);
34
35    let (mod_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
36
37    let post_init_stmts = post_init::codegen(app, analysis);
38
39    let (mod_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
40
41    user.push(quote!(
42        #user_init
43
44        #user_idle
45    ));
46
47    root.push(quote!(
48        #(#root_init)*
49
50        #(#root_idle)*
51    ));
52
53    mod_app.push(quote!(
54        #mod_app_init
55
56        #(#mod_app_idle)*
57    ));
58
59    let main = util::suffixed("main");
60    mains.push(quote!(
61        #[doc(hidden)]
62        mod rtic_ext {
63            use super::*;
64            #[no_mangle]
65            unsafe extern "C" fn #main() -> ! {
66                #(#assertion_stmts)*
67
68                #(#pre_init_stmts)*
69
70                #[inline(never)]
71                fn __rtic_init_resources<F>(f: F) where F: FnOnce() {
72                    f();
73                }
74
75                // Wrap late_init_stmts in a function to ensure that stack space is reclaimed.
76                __rtic_init_resources(||{
77                    #call_init
78
79                    #(#post_init_stmts)*
80                });
81
82                #call_idle
83            }
84        }
85    ));
86
87    let (mod_app_shared_resources, mod_shared_resources) =
88        shared_resources::codegen(app, analysis, extra);
89    let (mod_app_local_resources, mod_local_resources) =
90        local_resources::codegen(app, analysis, extra);
91
92    let (mod_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
93        hardware_tasks::codegen(app, analysis, extra);
94
95    let (mod_app_software_tasks, root_software_tasks, user_software_tasks) =
96        software_tasks::codegen(app, analysis, extra);
97
98    let mod_app_dispatchers = dispatchers::codegen(app, analysis, extra);
99    let mod_app_timer_queue = timer_queue::codegen(app, analysis, extra);
100    let user_imports = &app.user_imports;
101    let user_code = &app.user_code;
102    let name = &app.name;
103    let device = &extra.device;
104
105    let monotonic_parts: Vec<_> = app
106        .monotonics
107        .iter()
108        .map(|(_, monotonic)| {
109            let name = &monotonic.ident;
110            let name_str = &name.to_string();
111            let cfgs = &monotonic.cfgs;
112            let ident = util::monotonic_ident(name_str);
113            let doc = &format!(
114                "This module holds the static implementation for `{}::now()`",
115                name_str
116            );
117
118            let default_monotonic = if monotonic.args.default {
119                quote!(
120                #(#cfgs)*
121                pub use #name::now;
122                )
123            } else {
124                quote!()
125            };
126
127            quote! {
128                #default_monotonic
129
130                #[doc = #doc]
131                #[allow(non_snake_case)]
132                #(#cfgs)*
133                pub mod #name {
134
135                    /// Read the current time from this monotonic
136                    pub fn now() -> <super::super::#name as rtic::Monotonic>::Instant {
137                        rtic::export::interrupt::free(|_| {
138                            use rtic::Monotonic as _;
139                            if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } {
140                                m.now()
141                            } else {
142                                <super::super::#name as rtic::Monotonic>::zero()
143                            }
144                        })
145                    }
146                }
147            }
148        })
149        .collect();
150
151    let monotonics = if monotonic_parts.is_empty() {
152        quote!()
153    } else {
154        quote!(
155            pub use rtic::Monotonic as _;
156
157            /// Holds static methods for each monotonic.
158            pub mod monotonics {
159                #(#monotonic_parts)*
160            }
161        )
162    };
163    let rt_err = util::rt_err_ident();
164
165    quote!(
166        /// The RTIC application module
167        pub mod #name {
168            /// Always include the device crate which contains the vector table
169            use #device as #rt_err;
170
171            #monotonics
172
173            #(#user_imports)*
174
175            /// User code from within the module
176            #(#user_code)*
177            /// User code end
178
179            #(#user)*
180
181            #(#user_hardware_tasks)*
182
183            #(#user_software_tasks)*
184
185            #(#root)*
186
187            #mod_shared_resources
188
189            #mod_local_resources
190
191            #(#root_hardware_tasks)*
192
193            #(#root_software_tasks)*
194
195            /// App module
196            #(#mod_app)*
197
198            #(#mod_app_shared_resources)*
199
200            #(#mod_app_local_resources)*
201
202            #(#mod_app_hardware_tasks)*
203
204            #(#mod_app_software_tasks)*
205
206            #(#mod_app_dispatchers)*
207
208            #(#mod_app_timer_queue)*
209
210            #(#mains)*
211        }
212    )
213}