rtic/macros/src/codegen.rs

147 lines
3.4 KiB
Rust
Raw Normal View History

use proc_macro2::TokenStream as TokenStream2;
2018-11-03 17:02:41 +01:00
use quote::quote;
use rtfm_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra};
mod assertions;
mod dispatchers;
mod hardware_tasks;
mod idle;
mod init;
mod locals;
mod module;
mod post_init;
mod pre_init;
mod resources;
mod resources_struct;
mod schedule;
mod schedule_body;
mod software_tasks;
mod spawn;
mod spawn_body;
mod timer_queue;
mod util;
// TODO document the syntax here or in `rtfm-syntax`
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let mut const_app = vec![];
let mut mains = vec![];
let mut root = vec![];
let mut user = vec![];
2018-11-03 17:02:41 +01:00
// generate a `main` function for each core
for core in 0..app.args.cores {
let assertion_stmts = assertions::codegen(core, analysis);
2018-11-03 17:02:41 +01:00
let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra);
2018-11-03 17:02:41 +01:00
let (const_app_init, root_init, user_init, call_init) =
init::codegen(core, app, analysis, extra);
2018-11-03 17:02:41 +01:00
let (const_app_post_init, post_init_stmts) = post_init::codegen(core, analysis, extra);
2018-11-03 17:02:41 +01:00
let (const_app_idle, root_idle, user_idle, call_idle) =
idle::codegen(core, app, analysis, extra);
2018-11-03 17:02:41 +01:00
user.push(quote!(
#user_init
2018-11-03 17:02:41 +01:00
#user_idle
));
2018-11-03 17:02:41 +01:00
root.push(quote!(
#(#root_init)*
2018-11-03 17:02:41 +01:00
#(#root_idle)*
));
2018-11-03 17:02:41 +01:00
const_app.push(quote!(
#(#const_app_pre_init)*
2018-11-03 17:02:41 +01:00
#const_app_init
2018-11-03 17:02:41 +01:00
#(#const_app_post_init)*
#const_app_idle
));
let cfg_core = util::cfg_core(core, app.args.cores);
2019-06-18 10:31:31 +02:00
let main = util::suffixed("main", core);
mains.push(quote!(
#[no_mangle]
#cfg_core
2019-06-18 10:31:31 +02:00
unsafe extern "C" fn #main() -> ! {
#(#assertion_stmts)*
#(#pre_init_stmts)*
#call_init
#(#post_init_stmts)*
#call_idle
}
));
}
let (const_app_resources, mod_resources) = resources::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let (const_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
hardware_tasks::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let (const_app_software_tasks, root_software_tasks, user_software_tasks) =
software_tasks::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let const_app_dispatchers = dispatchers::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let const_app_spawn = spawn::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let const_app_timer_queue = timer_queue::codegen(app, analysis, extra);
2018-11-03 17:02:41 +01:00
let const_app_schedule = schedule::codegen(app, extra);
2018-11-03 17:02:41 +01:00
let name = &app.name;
let device = extra.device;
quote!(
#(#user)*
#(#user_hardware_tasks)*
2019-02-16 00:22:00 +01:00
#(#user_software_tasks)*
#(#root)*
2018-11-03 17:02:41 +01:00
#(#mod_resources)*
2018-11-03 17:02:41 +01:00
#(#root_hardware_tasks)*
2018-11-03 17:02:41 +01:00
#(#root_software_tasks)*
/// Implementation details
// the user can't access the items within this `const` item
const #name: () = {
/// Always include the device crate which contains the vector table
use #device as _;
2019-02-15 19:52:25 +01:00
#(#const_app)*
2018-11-03 17:02:41 +01:00
#(#const_app_resources)*
2018-11-03 17:02:41 +01:00
#(#const_app_hardware_tasks)*
#(#const_app_software_tasks)*
2018-11-03 17:02:41 +01:00
#(#const_app_dispatchers)*
2018-11-03 17:02:41 +01:00
#(#const_app_spawn)*
2018-11-03 17:02:41 +01:00
#(#const_app_timer_queue)*
#(#const_app_schedule)*
2018-11-03 17:02:41 +01:00
#(#mains)*
2019-02-15 19:52:25 +01:00
};
2018-11-03 17:02:41 +01:00
)
}