diff options
Diffstat (limited to 'macros/src/codegen')
-rw-r--r-- | macros/src/codegen/async_dispatchers.rs | 87 | ||||
-rw-r--r-- | macros/src/codegen/main.rs | 13 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 17 | ||||
-rw-r--r-- | macros/src/codegen/util.rs | 4 |
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( |