diff options
Diffstat (limited to 'macros/src/codegen/module.rs')
-rw-r--r-- | macros/src/codegen/module.rs | 214 |
1 files changed, 106 insertions, 108 deletions
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 9bcc8f64..2f6ec335 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -1,9 +1,8 @@ +use crate::{analyze::Analysis, check::Extra, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::{ast::App, Context}; -use crate::{analyze::Analysis, check::Extra, codegen::util}; - pub fn codegen( ctxt: Context, resources_tick: bool, @@ -12,48 +11,13 @@ pub fn codegen( 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); - let app_name = &app.name; - let app_path = quote! {crate::#app_name}; - - let all_task_imports: Vec<_> = app - .software_tasks - .iter() - .map(|(name, st)| { - if !st.is_extern { - let cfgs = &st.cfgs; - quote! { - #(#cfgs)* - #[allow(unused_imports)] - use #app_path::#name as #name; - } - } else { - quote!() - } - }) - .chain(app.hardware_tasks.iter().map(|(name, ht)| { - if !ht.is_extern { - quote! { - #[allow(unused_imports)] - use #app_path::#name as #name; - } - } else { - quote!() - } - })) - .chain(app.user_types.iter().map(|ty| { - let t = &ty.ident; - quote! { - #[allow(unused_imports)] - use super::#t; - } - })) - .collect(); let mut lt = None; match ctxt { @@ -94,7 +58,7 @@ pub fn codegen( if ctxt.has_locals(app) { let ident = util::locals_ident(ctxt, app); - items.push(quote!( + module_items.push(quote!( #[doc(inline)] pub use super::#ident as Locals; )); @@ -110,14 +74,14 @@ pub fn codegen( None }; - items.push(quote!( + module_items.push(quote!( #[doc(inline)] pub use super::#ident as Resources; )); fields.push(quote!( /// Resources this task has access to - pub resources: Resources<#lt> + pub resources: #name::Resources<#lt> )); let priority = if ctxt.is_init() { @@ -125,7 +89,7 @@ pub fn codegen( } else { Some(quote!(priority)) }; - values.push(quote!(resources: Resources::new(#priority))); + values.push(quote!(resources: #name::Resources::new(#priority))); } if let Context::Init = ctxt { @@ -145,13 +109,17 @@ pub fn codegen( }) .collect::<Vec<_>>(); + let internal_late_ident = util::mark_internal_name("LateResources"); items.push(quote!( /// Resources initialized at runtime #[allow(non_snake_case)] - pub struct LateResources { + pub struct #internal_late_ident { #(#late_fields),* } )); + module_items.push(quote!( + pub use super::#internal_late_ident as LateResources; + )); let monotonic_types: Vec<_> = app .monotonics @@ -162,13 +130,19 @@ pub fn codegen( }) .collect(); + let internal_monotonics_ident = util::mark_internal_name("Monotonics"); + items.push(quote!( /// Monotonics used by the system #[allow(non_snake_case)] - pub struct Monotonics( + pub struct #internal_monotonics_ident( #(pub #monotonic_types),* ); )); + + module_items.push(quote!( + pub use super::#internal_monotonics_ident as Monotonics; + )); } let doc = match ctxt { @@ -178,6 +152,19 @@ pub fn codegen( Context::SoftwareTask(_) => "Software task", }; + let v = Vec::new(); + let cfgs = match ctxt { + Context::HardwareTask(t) => { + &app.hardware_tasks[t].cfgs + // ... + }, + Context::SoftwareTask(t) => { + &app.software_tasks[t].cfgs + // ... + }, + _ => &v, + }; + let core = if ctxt.is_init() { Some(quote!(core: rtic::export::Peripherals,)) } else { @@ -190,22 +177,31 @@ pub fn codegen( Some(quote!(priority: &#lt rtic::export::Priority)) }; + let internal_context_name = util::internal_task_ident(name, "Context"); + items.push(quote!( + #(#cfgs)* /// Execution context - pub struct Context<#lt> { + pub struct #internal_context_name<#lt> { #(#fields,)* } - impl<#lt> Context<#lt> { + #(#cfgs)* + impl<#lt> #internal_context_name<#lt> { #[inline(always)] pub unsafe fn new(#core #priority) -> Self { - Context { + #internal_context_name { #(#values,)* } } } )); + module_items.push(quote!( + #(#cfgs)* + pub use super::#internal_context_name as Context; + )); + // not sure if this is the right way, maybe its backwards, // that spawn_module should put in in root @@ -234,26 +230,26 @@ pub fn codegen( .expect("RTIC-ICE: interrupt identifer not found") .0; + let internal_spawn_ident = util::internal_task_ident(name, "spawn"); + // Spawn caller items.push(quote!( - #(#all_task_imports)* - #(#cfgs)* /// Spawns the task directly - pub fn spawn(#(#args,)*) -> Result<(), #ty> { + pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> { let input = #tupled; unsafe { - if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) { - #app_path::#inputs + if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) { + #inputs .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); rtic::export::interrupt::free(|_| { - #app_path::#rq.get_mut_unchecked().enqueue_unchecked((#app_path::#t::#name, index)); + #rq.get_mut_unchecked().enqueue_unchecked((#t::#name, index)); }); rtic::pend(#device::#enum_::#interrupt); @@ -266,6 +262,11 @@ pub fn codegen( })); + module_items.push(quote!( + #(#cfgs)* + pub use super::#internal_spawn_ident as spawn; + )); + // Schedule caller for (_, monotonic) in &app.monotonics { let instants = util::monotonic_instants_ident(name, &monotonic.ident); @@ -282,12 +283,6 @@ pub fn codegen( let m_isr = &monotonic.args.binds; let enum_ = util::interrupt_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 use #m::SpawnHandle;)); - } - let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" { ( quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()) @@ -297,49 +292,56 @@ pub fn codegen( } else { let rt_err = util::rt_err_ident(); ( - quote!(rtic::export::NVIC::unmask(#app_path::#rt_err::#enum_::#m_isr)), - quote!(rtic::pend(#app_path::#rt_err::#enum_::#m_isr)), + quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)), + quote!(rtic::pend(#rt_err::#enum_::#m_isr)), ) }; - let user_imports = &app.user_imports; let tq_marker = util::mark_internal_ident(&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 { + module_items.push(quote!( + pub use #m::spawn_after; + pub use #m::spawn_at; + pub use #m::SpawnHandle; + )); + } + module_items.push(quote!( + 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!( - /// Holds methods related to this monotonic - pub mod #m { - use super::*; - #[allow(unused_imports)] - use #app_path::#tq_marker; - #[allow(unused_imports)] - use #app_path::#t; - #( - #[allow(unused_imports)] - #user_imports - )* - - pub struct SpawnHandle { + pub struct #internal_spawn_handle_ident { #[doc(hidden)] marker: u32, } - impl SpawnHandle { + impl #internal_spawn_handle_ident { pub fn cancel(self) -> Result<#ty, ()> { rtic::export::interrupt::free(|_| unsafe { - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); if let Some((_task, index)) = tq.cancel_marker(self.marker) { // Get the message - let msg = #app_path::#inputs + let msg = #inputs .get_unchecked() .get_unchecked(usize::from(index)) .as_ptr() .read(); // Return the index to the free queue - #app_path::#fq.get_mut_unchecked().split().0.enqueue_unchecked(index); + #fq.get_mut_unchecked().split().0.enqueue_unchecked(index); Ok(msg) } else { @@ -351,20 +353,20 @@ pub fn codegen( #[inline] pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()> where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>, + D::T: Into<<#mono_type as rtic::time::Clock>::T>, { - self.reschedule_at(#app_path::monotonics::#m::now() + duration) + self.reschedule_at(monotonics::#m::now() + duration) } - pub fn reschedule_at(self, instant: rtic::time::Instant<#app_path::#mono_type>) -> Result<Self, ()> + pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result<Self, ()> { rtic::export::interrupt::free(|_| unsafe { let marker = *#tq_marker.get_mut_unchecked(); *#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1); - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); - tq.update_marker(self.marker, marker, instant, || #pend).map(|_| SpawnHandle { marker }) + tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker }) }) } } @@ -374,39 +376,39 @@ pub fn codegen( /// /// 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]` - pub fn spawn_after<D>( + pub fn #internal_spawn_after_ident<D>( duration: D #(,#args)* - ) -> Result<SpawnHandle, #ty> + ) -> Result<#name::#m::SpawnHandle, #ty> where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>, + D::T: Into<<#mono_type as rtic::time::Clock>::T>, { - let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.get_mut_unchecked().is_none() }) { + let instant = if rtic::export::interrupt::free(|_| unsafe { #m_ident.get_mut_unchecked().is_none() }) { rtic::time::Instant::new(0) } else { - #app_path::monotonics::#m::now() + monotonics::#m::now() }; - spawn_at(instant + duration #(,#untupled)*) + #internal_spawn_at_ident(instant + duration #(,#untupled)*) } #(#cfgs)* /// Spawns the task at a fixed time instant - pub fn spawn_at( - instant: rtic::time::Instant<#app_path::#mono_type> + pub fn #internal_spawn_at_ident( + instant: rtic::time::Instant<#mono_type> #(,#args)* - ) -> Result<SpawnHandle, #ty> { + ) -> Result<#name::#m::SpawnHandle, #ty> { unsafe { let input = #tupled; - if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) { - #app_path::#inputs + if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) { + #inputs .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() .write(input); - #app_path::#instants + #instants .get_mut_unchecked() .get_unchecked_mut(usize::from(index)) .as_mut_ptr() @@ -417,44 +419,40 @@ pub fn codegen( let nr = rtic::export::NotReady { instant, index, - task: #app_path::#t::#name, + task: #t::#name, marker, }; *#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1); - let tq = &mut *#app_path::#tq.get_mut_unchecked().as_mut_ptr(); + let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr(); tq.enqueue_unchecked( nr, || #enable_interrupt, || #pend, - #app_path::#m_ident.get_mut_unchecked().as_mut()); + #m_ident.get_mut_unchecked().as_mut()); - Ok(SpawnHandle { marker }) + Ok(#name::#m::SpawnHandle { marker }) }) } else { Err(input) } } } - })); + )); } } if !items.is_empty() { - let user_imports = &app.user_imports; - quote!( + #(#items)* + #[allow(non_snake_case)] #(#task_cfgs)* #[doc = #doc] pub mod #name { - #( - #[allow(unused_imports)] - #user_imports - )* - #(#items)* + #(#module_items)* } ) } else { |