aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/codegen')
-rw-r--r--macros/src/codegen/async_dispatchers.rs87
-rw-r--r--macros/src/codegen/main.rs13
-rw-r--r--macros/src/codegen/module.rs17
-rw-r--r--macros/src/codegen/util.rs4
4 files changed, 79 insertions, 42 deletions
diff --git a/macros/src/codegen/async_dispatchers.rs b/macros/src/codegen/async_dispatchers.rs
index 62b17fee..f6408e1e 100644
--- a/macros/src/codegen/async_dispatchers.rs
+++ b/macros/src/codegen/async_dispatchers.rs
@@ -26,9 +26,22 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
for (&level, channel) in &analysis.channels {
let mut stmts = vec![];
- let device = &app.args.device;
- let enum_ = util::interrupt_ident();
- let interrupt = util::suffixed(&interrupts[&level].0.to_string());
+
+ let dispatcher_name = if level > 0 {
+ util::suffixed(&interrupts.get(&level).expect("UNREACHABLE").0.to_string())
+ } else {
+ util::zero_prio_dispatcher_ident()
+ };
+
+ let pend_interrupt = if level > 0 {
+ let device = &app.args.device;
+ let enum_ = util::interrupt_ident();
+
+ quote!(rtic::pend(#device::#enum_::#dispatcher_name);)
+ } else {
+ // For 0 priority tasks we don't need to pend anything
+ quote!()
+ };
for name in channel.tasks.iter() {
let exec_name = util::internal_task_ident(name, "EXEC");
@@ -60,40 +73,56 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
#executor_run_ident.store(false, core::sync::atomic::Ordering::Relaxed);
if (&mut *#exec_name.get_mut()).poll(|| {
#executor_run_ident.store(true, core::sync::atomic::Ordering::Release);
- rtic::pend(#device::#enum_::#interrupt);
+ #pend_interrupt
}) && #rq.load(core::sync::atomic::Ordering::Relaxed) {
// If the ready queue is not empty and the executor finished, restart this
// dispatch to check if the executor should be restarted.
- rtic::pend(#device::#enum_::#interrupt);
+ #pend_interrupt
}
}
));
}
- let doc = format!(
- "Interrupt handler to dispatch async tasks at priority {}",
- level
- );
- let attribute = &interrupts[&level].1.attrs;
- items.push(quote!(
- #[allow(non_snake_case)]
- #[doc = #doc]
- #[no_mangle]
- #(#attribute)*
- unsafe fn #interrupt() {
- /// The priority of this interrupt handler
- const PRIORITY: u8 = #level;
-
- rtic::export::run(PRIORITY, || {
- // Have the acquire/release semantics outside the checks to no overdo it
- core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire);
-
- #(#stmts)*
-
- core::sync::atomic::fence(core::sync::atomic::Ordering::Release);
- });
- }
- ));
+ if level > 0 {
+ let doc = format!(
+ "Interrupt handler to dispatch async tasks at priority {}",
+ level
+ );
+ let attribute = &interrupts.get(&level).expect("UNREACHABLE").1.attrs;
+ items.push(quote!(
+ #[allow(non_snake_case)]
+ #[doc = #doc]
+ #[no_mangle]
+ #(#attribute)*
+ unsafe fn #dispatcher_name() {
+ /// The priority of this interrupt handler
+ const PRIORITY: u8 = #level;
+
+ rtic::export::run(PRIORITY, || {
+ // Have the acquire/release semantics outside the checks to no overdo it
+ core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire);
+
+ #(#stmts)*
+
+ core::sync::atomic::fence(core::sync::atomic::Ordering::Release);
+ });
+ }
+ ));
+ } else {
+ items.push(quote!(
+ #[allow(non_snake_case)]
+ unsafe fn #dispatcher_name() -> ! {
+ loop {
+ // Have the acquire/release semantics outside the checks to no overdo it
+ core::sync::atomic::fence(core::sync::atomic::Ordering::Acquire);
+
+ #(#stmts)*
+
+ core::sync::atomic::fence(core::sync::atomic::Ordering::Release);
+ }
+ }
+ ));
+ }
}
quote!(#(#items)*)
diff --git a/macros/src/codegen/main.rs b/macros/src/codegen/main.rs
index 90f09ae0..8e7138f4 100644
--- a/macros/src/codegen/main.rs
+++ b/macros/src/codegen/main.rs
@@ -16,11 +16,14 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
let name = &idle.name;
quote!(#name(#name::Context::new()))
} else {
- // TODO: No idle defined, check for 0-priority tasks and generate an executor if needed
-
- quote!(loop {
- rtic::export::nop()
- })
+ if analysis.channels.get(&0).is_some() {
+ let dispatcher = util::zero_prio_dispatcher_ident();
+ quote!(#dispatcher();)
+ } else {
+ quote!(loop {
+ rtic::export::nop()
+ })
+ }
};
let main = util::suffixed("main");
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index c6f7690f..70fbb5e6 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -135,13 +135,14 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
// Store a copy of the task cfgs
task_cfgs = cfgs.clone();
- let device = &app.args.device;
- let enum_ = util::interrupt_ident();
- let interrupt = &analysis
- .interrupts
- .get(&priority)
- .expect("RTIC-ICE: interrupt identifier not found")
- .0;
+ let pend_interrupt = if priority > 0 {
+ let device = &app.args.device;
+ let enum_ = util::interrupt_ident();
+ let interrupt = &analysis.interrupts.get(&priority).expect("UREACHABLE").0;
+ quote!(rtic::pend(#device::#enum_::#interrupt);)
+ } else {
+ quote!()
+ };
let internal_spawn_ident = util::internal_task_ident(name, "spawn");
@@ -160,7 +161,7 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
Err(())
} else {
#rq.store(true, core::sync::atomic::Ordering::Release);
- rtic::pend(#device::#enum_::#interrupt);
+ #pend_interrupt
Ok(())
}
}
diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs
index a071ca27..6552839f 100644
--- a/macros/src/codegen/util.rs
+++ b/macros/src/codegen/util.rs
@@ -187,6 +187,10 @@ pub fn need_to_lock_ident(name: &Ident) -> Ident {
Ident::new(&format!("{}_that_needs_to_be_locked", name), name.span())
}
+pub fn zero_prio_dispatcher_ident() -> Ident {
+ Ident::new("__rtic_internal_async_0_prio_dispatcher", Span::call_site())
+}
+
/// The name to get better RT flag errors
pub fn rt_err_ident() -> Ident {
Ident::new(