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 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 __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 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 pub mod monotonics {
159 #(#monotonic_parts)*
160 }
161 )
162 };
163 let rt_err = util::rt_err_ident();
164
165 quote!(
166 pub mod #name {
168 use #device as #rt_err;
170
171 #monotonics
172
173 #(#user_imports)*
174
175 #(#user_code)*
177 #(#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 #(#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}