diff options
Diffstat (limited to 'macros/src/codegen/module.rs')
-rw-r--r-- | macros/src/codegen/module.rs | 263 |
1 files changed, 140 insertions, 123 deletions
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 8dcdbcf3..7ac06c5c 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -1,7 +1,7 @@ -use crate::{analyze::Analysis, check::Extra, codegen::util}; +use crate::syntax::{ast::App, Context}; +use crate::{analyze::Analysis, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use rtic_syntax::{ast::App, Context}; #[allow(clippy::too_many_lines)] pub fn codegen( @@ -10,12 +10,13 @@ pub fn codegen( local_resources_tick: bool, app: &App, analysis: &Analysis, - extra: &Extra, ) -> TokenStream2 { let mut items = vec![]; let mut module_items = vec![]; let mut fields = vec![]; let mut values = vec![]; + // Used to copy task cfgs to the whole module + let mut task_cfgs = vec![]; let name = ctxt.ident(app); @@ -27,8 +28,8 @@ pub fn codegen( pub core: rtic::export::Peripherals )); - if extra.peripherals { - let device = &extra.device; + if app.args.peripherals { + let device = &app.args.device; fields.push(quote!( /// Device peripherals @@ -52,14 +53,6 @@ pub fn codegen( Context::Idle | Context::HardwareTask(_) | Context::SoftwareTask(_) => {} } - // if ctxt.has_locals(app) { - // let ident = util::locals_ident(ctxt, app); - // module_items.push(quote!( - // #[doc(inline)] - // pub use super::#ident as Locals; - // )); - // } - if ctxt.has_local_resources(app) { let ident = util::local_resources_ident(ctxt, app); let lt = if local_resources_tick { @@ -114,12 +107,8 @@ pub fn codegen( .monotonics .iter() .map(|(_, monotonic)| { - let cfgs = &monotonic.cfgs; let mono = &monotonic.ty; - quote! { - #(#cfgs)* - pub #mono - } + quote! {#mono} }) .collect(); @@ -130,7 +119,7 @@ pub fn codegen( #[allow(non_snake_case)] #[allow(non_camel_case_types)] pub struct #internal_monotonics_ident( - #(#monotonic_types),* + #(pub #monotonic_types),* ); )); @@ -141,10 +130,10 @@ pub fn codegen( } let doc = match ctxt { - Context::Idle => " Idle loop", - Context::Init => " Initialization function", - Context::HardwareTask(_) => " Hardware task", - Context::SoftwareTask(_) => " Software task", + Context::Idle => "Idle loop", + Context::Init => "Initialization function", + Context::HardwareTask(_) => "Hardware task", + Context::SoftwareTask(_) => "Software task", }; let v = Vec::new(); @@ -175,8 +164,8 @@ pub fn codegen( let internal_context_name = util::internal_task_ident(name, "Context"); items.push(quote!( - /// Execution context #(#cfgs)* + /// Execution context #[allow(non_snake_case)] #[allow(non_camel_case_types)] pub struct #internal_context_name<#lt> { @@ -185,7 +174,6 @@ pub fn codegen( #(#cfgs)* impl<#lt> #internal_context_name<#lt> { - #[doc(hidden)] #[inline(always)] pub unsafe fn new(#core #priority) -> Self { #internal_context_name { @@ -196,8 +184,8 @@ pub fn codegen( )); module_items.push(quote!( - #[doc(inline)] #(#cfgs)* + #[doc(inline)] pub use super::#internal_context_name as Context; )); @@ -206,6 +194,8 @@ pub fn codegen( let priority = spawnee.args.priority; let t = util::spawn_t_ident(priority); 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 = &args; let tupled = &tupled; @@ -213,112 +203,141 @@ pub fn codegen( let rq = util::rq_ident(priority); let inputs = util::inputs_ident(name); - let device = &extra.device; + let device = &app.args.device; let enum_ = util::interrupt_ident(); - let interrupt = &analysis - .interrupts - .get(&priority) - .expect("RTIC-ICE: interrupt identifer not found") - .0; + let interrupt = if spawnee.is_async { + &analysis + .interrupts_async + .get(&priority) + .expect("RTIC-ICE: interrupt identifer not found") + .0 + } else { + &analysis + .interrupts_normal + .get(&priority) + .expect("RTIC-ICE: interrupt identifer not found") + .0 + }; let internal_spawn_ident = util::internal_task_ident(name, "spawn"); // Spawn caller - items.push(quote!( + if spawnee.is_async { + let rq = util::rq_async_ident(name); + items.push(quote!( - /// Spawns the task directly - #(#cfgs)* - pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { - let input = #tupled; + #(#cfgs)* + /// Spawns the task directly + #[allow(non_snake_case)] + #[doc(hidden)] + pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { + let input = #tupled; - unsafe { - if let Some(index) = rtic::export::interrupt::free(|_| (&mut *#fq.get_mut()).dequeue()) { - (&mut *#inputs - .get_mut()) - .get_unchecked_mut(usize::from(index)) - .as_mut_ptr() - .write(input); + unsafe { + let r = rtic::export::interrupt::free(|_| (&mut *#rq.get_mut()).enqueue(input)); - rtic::export::interrupt::free(|_| { - (&mut *#rq.get_mut()).enqueue_unchecked((#t::#name, index)); - }); + if r.is_ok() { + rtic::pend(#device::#enum_::#interrupt); + } - rtic::pend(#device::#enum_::#interrupt); + r + } + })); + } else { + items.push(quote!( - Ok(()) - } else { - Err(input) + #(#cfgs)* + /// Spawns the task directly + #[allow(non_snake_case)] + #[doc(hidden)] + pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { + let input = #tupled; + + unsafe { + if let Some(index) = rtic::export::interrupt::free(|_| (&mut *#fq.get_mut()).dequeue()) { + (&mut *#inputs + .get_mut()) + .get_unchecked_mut(usize::from(index)) + .as_mut_ptr() + .write(input); + + rtic::export::interrupt::free(|_| { + (&mut *#rq.get_mut()).enqueue_unchecked((#t::#name, index)); + }); + rtic::pend(#device::#enum_::#interrupt); + + Ok(()) + } else { + Err(input) + } } - } - })); + })); + } module_items.push(quote!( - #[doc(inline)] #(#cfgs)* + #[doc(inline)] pub use super::#internal_spawn_ident as spawn; )); // Schedule caller - for (_, monotonic) in &app.monotonics { - let instants = util::monotonic_instants_ident(name, &monotonic.ident); - let monotonic_name = monotonic.ident.to_string(); - - let tq = util::tq_ident(&monotonic.ident.to_string()); - let t = util::schedule_t_ident(); - let m = &monotonic.ident; - let cfgs = &monotonic.cfgs; - let m_ident = util::monotonic_ident(&monotonic_name); - let m_isr = &monotonic.args.binds; - let enum_ = util::interrupt_ident(); - let spawn_handle_string = format!("{}::SpawnHandle", m); - - let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" { - ( - quote!(core::mem::transmute::<_, rtic::export::SYST>(()).enable_interrupt()), - quote!(rtic::export::SCB::set_pendst()), - ) - } else { - let rt_err = util::rt_err_ident(); - ( - quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)), - quote!(rtic::pend(#rt_err::#enum_::#m_isr)), - ) - }; - - let tq_marker = &util::timer_queue_marker_ident(); - - // For future use - // let doc = format!(" RTIC internal: {}:{}", file!(), line!()); - // items.push(quote!(#[doc = #doc])); - let internal_spawn_handle_ident = - util::internal_monotonics_ident(name, m, "SpawnHandle"); - let internal_spawn_at_ident = util::internal_monotonics_ident(name, m, "spawn_at"); - let internal_spawn_after_ident = - util::internal_monotonics_ident(name, m, "spawn_after"); - - if monotonic.args.default { + if !spawnee.is_async { + for (_, monotonic) in &app.monotonics { + let instants = util::monotonic_instants_ident(name, &monotonic.ident); + let monotonic_name = monotonic.ident.to_string(); + + let tq = util::tq_ident(&monotonic.ident.to_string()); + let t = util::schedule_t_ident(); + let m = &monotonic.ident; + let m_ident = util::monotonic_ident(&monotonic_name); + let m_isr = &monotonic.args.binds; + let enum_ = util::interrupt_ident(); + let spawn_handle_string = format!("{}::SpawnHandle", m); + + let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" { + ( + quote!(core::mem::transmute::<_, rtic::export::SYST>(()).enable_interrupt()), + quote!(rtic::export::SCB::set_pendst()), + ) + } else { + let rt_err = util::rt_err_ident(); + ( + quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)), + quote!(rtic::pend(#rt_err::#enum_::#m_isr)), + ) + }; + + let tq_marker = &util::timer_queue_marker_ident(); + + let internal_spawn_handle_ident = + util::internal_monotonics_ident(name, m, "SpawnHandle"); + let internal_spawn_at_ident = util::internal_monotonics_ident(name, m, "spawn_at"); + let internal_spawn_after_ident = + util::internal_monotonics_ident(name, m, "spawn_after"); + + if monotonic.args.default { + module_items.push(quote!( + #[doc(inline)] + pub use #m::spawn_after; + #[doc(inline)] + pub use #m::spawn_at; + #[doc(inline)] + pub use #m::SpawnHandle; + )); + } module_items.push(quote!( - #(#cfgs)* - pub use #m::spawn_after; - #(#cfgs)* - pub use #m::spawn_at; - #(#cfgs)* - pub use #m::SpawnHandle; + pub mod #m { + #[doc(inline)] + pub use super::super::#internal_spawn_after_ident as spawn_after; + #[doc(inline)] + pub use super::super::#internal_spawn_at_ident as spawn_at; + #[doc(inline)] + pub use super::super::#internal_spawn_handle_ident as SpawnHandle; + } )); - } - module_items.push(quote!( - #[doc(hidden)] - #(#cfgs)* - pub mod #m { - pub use super::super::#internal_spawn_after_ident as spawn_after; - pub use super::super::#internal_spawn_at_ident as spawn_at; - pub use super::super::#internal_spawn_handle_ident as SpawnHandle; - } - )); - items.push(quote!( - #[doc(hidden)] + items.push(quote!( #(#cfgs)* #[allow(non_snake_case)] #[allow(non_camel_case_types)] @@ -329,7 +348,6 @@ pub fn codegen( #(#cfgs)* impl core::fmt::Debug for #internal_spawn_handle_ident { - #[doc(hidden)] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct(#spawn_handle_string).finish() } @@ -340,7 +358,7 @@ pub fn codegen( pub fn cancel(self) -> Result<#ty, ()> { rtic::export::interrupt::free(|_| unsafe { let tq = &mut *#tq.get_mut(); - if let Some((_task, index)) = tq.cancel_marker(self.marker) { + if let Some((_task, index)) = tq.cancel_task_marker(self.marker) { // Get the message let msg = (&*#inputs .get()) @@ -357,9 +375,7 @@ pub fn codegen( }) } - /// Reschedule after #[inline] - #(#cfgs)* pub fn reschedule_after( self, duration: <#m as rtic::Monotonic>::Duration @@ -367,8 +383,6 @@ pub fn codegen( self.reschedule_at(monotonics::#m::now() + duration) } - /// Reschedule at - #(#cfgs)* pub fn reschedule_at( self, instant: <#m as rtic::Monotonic>::Instant @@ -379,16 +393,17 @@ pub fn codegen( let tq = (&mut *#tq.get_mut()); - tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) + tq.update_task_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) }) } } + + #(#cfgs)* /// Spawns the task after a set duration relative to the current time /// /// This will use the time `Instant::new(0)` as baseline if called in `#[init]`, /// so if you use a non-resetable timer use `spawn_at` when in `#[init]` - #(#cfgs)* #[allow(non_snake_case)] pub fn #internal_spawn_after_ident( duration: <#m as rtic::Monotonic>::Duration @@ -424,10 +439,10 @@ pub fn codegen( rtic::export::interrupt::free(|_| { let marker = #tq_marker.get().read(); - let nr = rtic::export::NotReady { - instant, - index, + let nr = rtic::export::TaskNotReady { task: #t::#name, + index, + instant, marker, }; @@ -435,7 +450,7 @@ pub fn codegen( let tq = &mut *#tq.get_mut(); - tq.enqueue_unchecked( + tq.enqueue_task_unchecked( nr, || #enable_interrupt, || #pend, @@ -449,6 +464,7 @@ pub fn codegen( } } )); + } } } @@ -457,8 +473,9 @@ pub fn codegen( } else { quote!( #(#items)* + #[allow(non_snake_case)] - #(#cfgs)* + #(#task_cfgs)* #[doc = #doc] pub mod #name { #(#module_items)* |