2019-06-13 23:56:59 +02:00
|
|
|
use proc_macro2::TokenStream as TokenStream2;
|
2018-11-03 17:02:41 +01:00
|
|
|
use quote::quote;
|
2020-06-11 19:18:29 +02:00
|
|
|
use rtic_syntax::ast::App;
|
2019-06-13 23:56:59 +02:00
|
|
|
|
|
|
|
use crate::{analyze::Analysis, check::Extra};
|
|
|
|
|
|
|
|
mod assertions;
|
|
|
|
mod dispatchers;
|
|
|
|
mod hardware_tasks;
|
|
|
|
mod idle;
|
|
|
|
mod init;
|
2021-07-05 21:40:01 +02:00
|
|
|
mod local_resources;
|
|
|
|
mod local_resources_struct;
|
2019-06-13 23:56:59 +02:00
|
|
|
mod module;
|
|
|
|
mod post_init;
|
|
|
|
mod pre_init;
|
2021-07-07 21:03:56 +02:00
|
|
|
mod shared_resources;
|
|
|
|
mod shared_resources_struct;
|
2019-06-13 23:56:59 +02:00
|
|
|
mod software_tasks;
|
|
|
|
mod timer_queue;
|
|
|
|
mod util;
|
|
|
|
|
|
|
|
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
2020-10-01 18:17:15 +02:00
|
|
|
let mut mod_app = vec![];
|
2019-06-13 23:56:59 +02:00
|
|
|
let mut mains = vec![];
|
|
|
|
let mut root = vec![];
|
|
|
|
let mut user = vec![];
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-09-01 19:04:55 +02:00
|
|
|
// Generate the `main` function
|
2020-12-10 20:33:13 +01:00
|
|
|
let assertion_stmts = assertions::codegen(app, analysis);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
let pre_init_stmts = pre_init::codegen(app, analysis, extra);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-15 18:50:17 +02:00
|
|
|
let (mod_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
let post_init_stmts = post_init::codegen(app, analysis);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-15 18:50:17 +02:00
|
|
|
let (mod_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra);
|
2020-05-19 11:55:50 +02:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
user.push(quote!(
|
|
|
|
#user_init
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
#user_idle
|
|
|
|
));
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
root.push(quote!(
|
|
|
|
#(#root_init)*
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
#(#root_idle)*
|
|
|
|
));
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
mod_app.push(quote!(
|
|
|
|
#mod_app_init
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2021-07-07 21:03:56 +02:00
|
|
|
#(#mod_app_idle)*
|
2020-08-27 13:21:56 +02:00
|
|
|
));
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
let main = util::suffixed("main");
|
|
|
|
mains.push(quote!(
|
2021-02-25 19:05:39 +01:00
|
|
|
#[doc(hidden)]
|
2020-11-15 18:40:14 +01:00
|
|
|
mod rtic_ext {
|
2020-11-15 18:27:08 +01:00
|
|
|
use super::*;
|
|
|
|
#[no_mangle]
|
|
|
|
unsafe extern "C" fn #main() -> ! {
|
|
|
|
#(#assertion_stmts)*
|
2020-05-26 22:21:32 +02:00
|
|
|
|
2020-11-15 18:27:08 +01:00
|
|
|
#(#pre_init_stmts)*
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2021-04-18 23:35:11 +02:00
|
|
|
#[inline(never)]
|
|
|
|
fn __rtic_init_resources<F>(f: F) where F: FnOnce() {
|
|
|
|
f();
|
|
|
|
}
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2021-04-18 23:35:11 +02:00
|
|
|
// Wrap late_init_stmts in a function to ensure that stack space is reclaimed.
|
|
|
|
__rtic_init_resources(||{
|
|
|
|
#call_init
|
|
|
|
|
|
|
|
#(#post_init_stmts)*
|
|
|
|
});
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2020-11-15 18:27:08 +01:00
|
|
|
#call_idle
|
|
|
|
}
|
2020-08-27 13:21:56 +02:00
|
|
|
}
|
|
|
|
));
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2021-07-07 21:03:56 +02:00
|
|
|
let (mod_app_shared_resources, mod_shared_resources) =
|
|
|
|
shared_resources::codegen(app, analysis, extra);
|
|
|
|
let (mod_app_local_resources, mod_local_resources) =
|
|
|
|
local_resources::codegen(app, analysis, extra);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-21 20:20:26 +02:00
|
|
|
let (mod_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
|
|
|
|
hardware_tasks::codegen(app, analysis, extra);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-15 18:50:17 +02:00
|
|
|
let (mod_app_software_tasks, root_software_tasks, user_software_tasks) =
|
|
|
|
software_tasks::codegen(app, analysis, extra);
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
let mod_app_dispatchers = dispatchers::codegen(app, analysis, extra);
|
|
|
|
let mod_app_timer_queue = timer_queue::codegen(app, analysis, extra);
|
2020-10-11 19:41:57 +02:00
|
|
|
let user_imports = &app.user_imports;
|
|
|
|
let user_code = &app.user_code;
|
2019-06-13 23:56:59 +02:00
|
|
|
let name = &app.name;
|
2020-10-23 10:35:56 +02:00
|
|
|
let device = &extra.device;
|
2021-02-18 19:30:59 +01:00
|
|
|
|
2021-02-20 18:32:05 +01:00
|
|
|
let monotonic_parts: Vec<_> = app
|
2020-12-12 23:31:05 +01:00
|
|
|
.monotonics
|
|
|
|
.iter()
|
|
|
|
.map(|(_, monotonic)| {
|
|
|
|
let name = &monotonic.ident;
|
2021-02-21 16:15:34 +01:00
|
|
|
let name_str = &name.to_string();
|
|
|
|
let ident = util::monotonic_ident(&name_str);
|
2021-02-23 19:35:26 +01:00
|
|
|
let panic_str = &format!(
|
|
|
|
"Use of monotonic '{}' before it was passed to the runtime",
|
|
|
|
name_str
|
|
|
|
);
|
2021-02-25 19:05:39 +01:00
|
|
|
let doc = &format!(
|
|
|
|
"This module holds the static implementation for `{}::now()`",
|
|
|
|
name_str
|
|
|
|
);
|
2021-02-21 16:15:34 +01:00
|
|
|
|
2021-04-20 10:34:26 +02:00
|
|
|
let default_monotonic = if monotonic.args.default {
|
|
|
|
quote!(pub use #name::now;)
|
|
|
|
} else {
|
|
|
|
quote!()
|
|
|
|
};
|
|
|
|
|
2021-02-18 19:30:59 +01:00
|
|
|
quote! {
|
2021-04-20 10:34:26 +02:00
|
|
|
#default_monotonic
|
|
|
|
|
2021-02-25 19:05:39 +01:00
|
|
|
#[doc = #doc]
|
2021-02-20 18:32:05 +01:00
|
|
|
#[allow(non_snake_case)]
|
2021-02-18 19:30:59 +01:00
|
|
|
pub mod #name {
|
2021-02-25 19:05:39 +01:00
|
|
|
|
|
|
|
/// Read the current time from this monotonic
|
2021-05-06 19:40:37 +02:00
|
|
|
pub fn now() -> rtic::time::Instant<super::super::#name> {
|
2021-02-18 19:30:59 +01:00
|
|
|
rtic::export::interrupt::free(|_| {
|
|
|
|
use rtic::Monotonic as _;
|
|
|
|
use rtic::time::Clock as _;
|
2021-11-02 13:41:12 +01:00
|
|
|
if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } {
|
2021-02-21 16:15:34 +01:00
|
|
|
if let Ok(v) = m.try_now() {
|
|
|
|
v
|
|
|
|
} else {
|
|
|
|
unreachable!("Your monotonic is not infallible!")
|
|
|
|
}
|
2021-02-18 19:30:59 +01:00
|
|
|
} else {
|
2021-02-21 16:15:34 +01:00
|
|
|
panic!(#panic_str);
|
2021-02-18 19:30:59 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-12 23:31:05 +01:00
|
|
|
})
|
|
|
|
.collect();
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2021-04-07 11:06:57 +02:00
|
|
|
let monotonics = if !monotonic_parts.is_empty() {
|
|
|
|
quote!(
|
|
|
|
pub use rtic::Monotonic as _;
|
|
|
|
|
|
|
|
/// Holds static methods for each monotonic.
|
|
|
|
pub mod monotonics {
|
|
|
|
#(#monotonic_parts)*
|
|
|
|
}
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
quote!()
|
|
|
|
};
|
2020-12-13 14:52:16 +01:00
|
|
|
let rt_err = util::rt_err_ident();
|
|
|
|
|
2019-04-21 20:02:59 +02:00
|
|
|
quote!(
|
2021-02-25 17:32:12 +01:00
|
|
|
/// The RTIC application module
|
2020-10-21 20:20:26 +02:00
|
|
|
pub mod #name {
|
2019-06-13 23:56:59 +02:00
|
|
|
/// Always include the device crate which contains the vector table
|
2020-12-13 14:52:16 +01:00
|
|
|
use #device as #rt_err;
|
2020-10-15 18:50:17 +02:00
|
|
|
|
2021-04-07 11:06:57 +02:00
|
|
|
#monotonics
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2020-05-26 12:55:13 +02:00
|
|
|
#(#user_imports)*
|
2019-02-15 19:52:25 +01:00
|
|
|
|
2020-06-04 17:43:16 +02:00
|
|
|
/// User code from within the module
|
|
|
|
#(#user_code)*
|
|
|
|
/// User code end
|
|
|
|
|
2020-10-15 18:50:17 +02:00
|
|
|
#(#user)*
|
|
|
|
|
|
|
|
#(#user_hardware_tasks)*
|
|
|
|
|
|
|
|
#(#user_software_tasks)*
|
|
|
|
|
|
|
|
#(#root)*
|
|
|
|
|
2021-07-06 22:47:48 +02:00
|
|
|
#mod_shared_resources
|
|
|
|
|
|
|
|
#mod_local_resources
|
2020-10-15 18:50:17 +02:00
|
|
|
|
|
|
|
#(#root_hardware_tasks)*
|
2020-06-04 17:43:16 +02:00
|
|
|
|
2020-10-15 18:50:17 +02:00
|
|
|
#(#root_software_tasks)*
|
2020-05-19 21:03:19 +02:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
/// app module
|
|
|
|
#(#mod_app)*
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2021-07-06 22:47:48 +02:00
|
|
|
#(#mod_app_shared_resources)*
|
|
|
|
|
|
|
|
#(#mod_app_local_resources)*
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
#(#mod_app_hardware_tasks)*
|
2018-12-16 18:37:36 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
#(#mod_app_software_tasks)*
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
#(#mod_app_dispatchers)*
|
2018-11-03 17:02:41 +01:00
|
|
|
|
2020-10-01 18:17:15 +02:00
|
|
|
#(#mod_app_timer_queue)*
|
2019-04-21 20:02:59 +02:00
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
#(#mains)*
|
2020-05-19 11:55:50 +02:00
|
|
|
}
|
2018-11-03 17:02:41 +01:00
|
|
|
)
|
|
|
|
}
|