aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/codegen')
-rw-r--r--macros/src/codegen/assertions.rs8
-rw-r--r--macros/src/codegen/dispatchers.rs2
-rw-r--r--macros/src/codegen/init.rs53
-rw-r--r--macros/src/codegen/module.rs212
-rw-r--r--macros/src/codegen/pre_init.rs39
-rw-r--r--macros/src/codegen/timer_queue.rs2
6 files changed, 138 insertions, 178 deletions
diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs
index 4d9aae47..a8a4491b 100644
--- a/macros/src/codegen/assertions.rs
+++ b/macros/src/codegen/assertions.rs
@@ -2,9 +2,10 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use crate::analyze::Analysis;
+use rtic_syntax::ast::App;
/// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits
-pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
let mut stmts = vec![];
for ty in &analysis.send_types {
@@ -15,5 +16,10 @@ pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
}
+ for (_, monotonic) in &app.monotonics {
+ let ty = &monotonic.ty;
+ stmts.push(quote!(rtic::export::assert_monotonic::<#ty>();));
+ }
+
stmts
}
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs
index d0a3ba01..01fb5119 100644
--- a/macros/src/codegen/dispatchers.rs
+++ b/macros/src/codegen/dispatchers.rs
@@ -5,7 +5,7 @@ use rtic_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates task dispatchers
-pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
let interrupts = &analysis.interrupts;
diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs
index 6b57add1..66c3bc4e 100644
--- a/macros/src/codegen/init.rs
+++ b/macros/src/codegen/init.rs
@@ -5,7 +5,7 @@ use rtic_syntax::{ast::App, Context};
use crate::{
analyze::Analysis,
check::Extra,
- codegen::{locals, module, resources_struct, util},
+ codegen::{locals, module, resources_struct},
};
type CodegenResult = (
@@ -32,50 +32,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
let mut root_init = vec![];
- let late_fields = analysis
- .late_resources
- .iter()
- .flat_map(|resources| {
- resources.iter().map(|name| {
- let ty = &app.late_resources[name].ty;
- let cfgs = &app.late_resources[name].cfgs;
-
- quote!(
- #(#cfgs)*
- pub #name: #ty
- )
- })
- })
- .collect::<Vec<_>>();
-
- let late_resources = util::late_resources_ident(&name);
-
- root_init.push(quote!(
- /// Resources initialized at runtime
- #[allow(non_snake_case)]
- pub struct #late_resources {
- #(#late_fields),*
- }
- ));
-
- let monotonic_types: Vec<_> = app
- .monotonics
- .iter()
- .map(|(_, monotonic)| {
- let mono = &monotonic.ty;
- quote! {#mono}
- })
- .collect();
- let monotonics = util::monotonics_ident(&name);
-
- root_init.push(quote!(
- /// Monotonics used by the system
- #[allow(non_snake_case)]
- pub struct #monotonics(
- #(#monotonic_types),*
- );
- ));
-
let mut locals_pat = None;
let mut locals_new = None;
if !init.locals.is_empty() {
@@ -91,15 +47,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
let stmts = &init.stmts;
let locals_pat = locals_pat.iter();
- let mut user_init_return = vec![quote! {#name::LateResources}];
- if !app.monotonics.is_empty() {
- user_init_return.push(quote! {#name::Monotonics});
- }
+ let user_init_return = quote! {#name::LateResources, #name::Monotonics};
let user_init = Some(quote!(
#(#attrs)*
#[allow(non_snake_case)]
- fn #name(#(#locals_pat,)* #context: #name::Context) -> (#(#user_init_return,)*) {
+ fn #name(#(#locals_pat,)* #context: #name::Context) -> (#user_init_return) {
#(#stmts)*
}
));
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index 2c42adce..6dd6e9a7 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -19,29 +19,13 @@ pub fn codegen(
let name = ctxt.ident(app);
- let mut needs_instant = false;
let mut lt = None;
match ctxt {
Context::Init => {
- // TODO: What fields are needed?
- // if let Some(m) = &extra.monotonic {
- // fields.push(quote!(
- // /// System start time = `Instant(0 /* cycles */)`
- // pub start: <#m as rtic::Monotonic>::Instant
- // ));
-
- // values.push(quote!(start: <#m as rtic::Monotonic>::zero()));
-
- // fields.push(quote!(
- // /// Core (Cortex-M) peripherals minus the SysTick
- // pub core: rtic::Peripherals
- // ));
- // } else {
- // fields.push(quote!(
- // /// Core (Cortex-M) peripherals
- // pub core: rtic::export::Peripherals
- // ));
- // }
+ fields.push(quote!(
+ /// Core (Cortex-M) peripherals
+ pub core: rtic::export::Peripherals
+ ));
if extra.peripherals {
let device = &extra.device;
@@ -68,31 +52,11 @@ pub fn codegen(
Context::Idle => {}
Context::HardwareTask(..) => {
- // TODO: What fields are needed for monotonic?
- // if let Some(m) = &extra.monotonic {
- // fields.push(quote!(
- // /// Time at which this handler started executing
- // pub start: <#m as rtic::Monotonic>::Instant
- // ));
-
- // values.push(quote!(start: instant));
-
- // needs_instant = true;
- // }
+ // None for now.
}
Context::SoftwareTask(..) => {
- // TODO: What fields are needed for monotonic?
- // if let Some(m) = &extra.monotonic {
- // fields.push(quote!(
- // /// The time at which this task was scheduled to run
- // pub scheduled: <#m as rtic::Monotonic>::Instant
- // ));
-
- // values.push(quote!(scheduled: instant));
-
- // needs_instant = true;
- // }
+ // None for now.
}
}
@@ -132,18 +96,45 @@ pub fn codegen(
}
if let Context::Init = ctxt {
- let init = &app.inits.first().unwrap();
- let late_resources = util::late_resources_ident(&init.name);
- let monotonics = util::monotonics_ident(&init.name);
+ let late_fields = analysis
+ .late_resources
+ .iter()
+ .flat_map(|resources| {
+ resources.iter().map(|name| {
+ let ty = &app.late_resources[name].ty;
+ let cfgs = &app.late_resources[name].cfgs;
+
+ quote!(
+ #(#cfgs)*
+ pub #name: #ty
+ )
+ })
+ })
+ .collect::<Vec<_>>();
items.push(quote!(
- #[doc(inline)]
- pub use super::#late_resources as LateResources;
+ /// Resources initialized at runtime
+ #[allow(non_snake_case)]
+ pub struct LateResources {
+ #(#late_fields),*
+ }
));
+ let monotonic_types: Vec<_> = app
+ .monotonics
+ .iter()
+ .map(|(_, monotonic)| {
+ let mono = &monotonic.ident;
+ quote! {#mono}
+ })
+ .collect();
+
items.push(quote!(
- #[doc(inline)]
- pub use super::#monotonics as Monotonics;
+ /// Monotonics used by the system
+ #[allow(non_snake_case)]
+ pub struct Monotonics(
+ #(#monotonic_types),*
+ );
));
}
@@ -166,16 +157,6 @@ pub fn codegen(
Some(quote!(priority: &#lt rtic::export::Priority))
};
- // TODO: What is needed for the new monotonic?
- // let instant = if needs_instant {
- // let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE");
-
- // Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
- // } else {
- // None
- // };
- let instant = quote!();
-
items.push(quote!(
/// Execution context
pub struct Context<#lt> {
@@ -184,7 +165,7 @@ pub fn codegen(
impl<#lt> Context<#lt> {
#[inline(always)]
- pub unsafe fn new(#core #priority #instant) -> Self {
+ pub unsafe fn new(#core #priority) -> Self {
Context {
#(#values,)*
}
@@ -202,7 +183,7 @@ pub fn codegen(
let cfgs = &spawnee.cfgs;
// Store a copy of the task cfgs
task_cfgs = cfgs.clone();
- let (args, tupled, _untupled, ty) = util::regroup_inputs(&spawnee.inputs);
+ let (args, tupled, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
let args = &args;
let tupled = &tupled;
let fq = util::fq_ident(name);
@@ -251,51 +232,70 @@ pub fn codegen(
}));
- // TODO: Needs updating for new monotonic.
- // // Schedule caller
- // if let Some(m) = &extra.monotonic {
- // let instants = util::instants_ident(name);
-
- // let tq = util::tq_ident();
- // let t = util::schedule_t_ident();
-
- // items.push(quote!(
- // #(#cfgs)*
- // pub fn schedule(
- // instant: <#m as rtic::Monotonic>::Instant
- // #(,#args)*
- // ) -> Result<(), #ty> {
- // unsafe {
- // use rtic::Mutex as _;
- // use rtic::mutex_prelude::*;
-
- // let input = #tupled;
- // if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
- // #app_path::#inputs
- // .get_unchecked_mut(usize::from(index))
- // .as_mut_ptr()
- // .write(input);
-
- // #app_path::#instants
- // .get_unchecked_mut(usize::from(index))
- // .as_mut_ptr()
- // .write(instant);
-
- // let nr = rtic::export::NotReady {
- // instant,
- // index,
- // task: #app_path::#t::#name,
- // };
-
- // rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr));
-
- // Ok(())
- // } else {
- // Err(input)
- // }
- // }
- // }));
- // }
+ // Schedule caller
+ for (_, monotonic) in &app.monotonics {
+ let instants = util::instants_ident(name);
+
+ let tq = util::tq_ident(&monotonic.ident.to_string());
+ let t = util::schedule_t_ident();
+ let m = &monotonic.ident;
+
+ if monotonic.args.default {
+ items.push(quote!(pub use #m::spawn_after;));
+ items.push(quote!(pub use #m::spawn_at;));
+ }
+
+ items.push(quote!(
+ pub mod #m {
+ #(#cfgs)*
+ pub fn spawn_after(
+ duration: rtic::Duration,
+ #(,#args)*
+ ) -> Result<(), #ty> {
+ let instant = <#app_path::#m as rtic::Monotonic>::now();
+
+ spawn_at(instant + duration, #(,#untupled)*)
+ }
+
+ #(#cfgs)*
+ pub fn spawn_at(
+ instant: Instant<#app_path::#m as rtic::Monotonic>
+ #(,#args)*
+ ) -> Result<(), #ty> {
+ unsafe {
+ use rtic::Mutex as _;
+ use rtic::mutex_prelude::*;
+
+ let input = #tupled;
+ if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
+ #app_path::#inputs
+ .get_unchecked_mut(usize::from(index))
+ .as_mut_ptr()
+ .write(input);
+
+ #app_path::#instants
+ .get_unchecked_mut(usize::from(index))
+ .as_mut_ptr()
+ .write(instant);
+
+ let nr = rtic::export::NotReady {
+ instant,
+ index,
+ task: #app_path::#t::#name,
+ };
+
+ rtic::export::interrupt::free(|_| #app_path::#tq.enqueue_unchecked(nr));
+
+ // TODO: After adding the scheduled task, check and setup the timer.
+
+ Ok(())
+ } else {
+ Err(input)
+ }
+ }
+ }
+ }));
+ }
}
if !items.is_empty() {
diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs
index dfdb30a0..26ba558c 100644
--- a/macros/src/codegen/pre_init.rs
+++ b/macros/src/codegen/pre_init.rs
@@ -74,25 +74,26 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
);));
}
- // TODO: Update for noew monotonic
- // // Initialize the SysTick if there exist a TimerQueue
- // if extra.monotonic.is_some() {
- // let priority = analysis.channels.keys().max().unwrap();
-
- // // Compile time assert that this priority is supported by the device
- // stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
-
- // stmts.push(quote!(core.SCB.set_priority(
- // rtic::export::SystemHandler::SysTick,
- // rtic::export::logical2hw(#priority, #nvic_prio_bits),
- // );));
-
- // stmts.push(quote!(
- // core.SYST.set_clock_source(rtic::export::SystClkSource::Core);
- // core.SYST.enable_counter();
- // core.DCB.enable_trace();
- // ));
- // }
+ // Initialize monotonic's interrupts
+ for (priority, name) in app
+ .monotonics
+ .iter()
+ .map(|(_, monotonic)| (&monotonic.args.priority, &monotonic.args.binds))
+ {
+ // Compile time assert that this priority is supported by the device
+ stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
+
+ // NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
+ let interrupt = util::interrupt_ident();
+ stmts.push(quote!(
+ core.NVIC.set_priority(
+ you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#interrupt::#name,
+ rtic::export::logical2hw(#priority, #nvic_prio_bits),
+ );
+ ));
+
+ // NOTE we do not unmask the interrupt as this is part of the monotonic to keep track of
+ }
// If there's no user `#[idle]` then optimize returning from interrupt handlers
if app.idles.is_empty() {
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
index ccde957d..f219eef2 100644
--- a/macros/src/codegen/timer_queue.rs
+++ b/macros/src/codegen/timer_queue.rs
@@ -5,7 +5,7 @@ use rtic_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates timer queues and timer queue handlers
-pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
+pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
if !app.monotonics.is_empty() {