diff options
Diffstat (limited to 'macros/src/codegen/timer_queue.rs')
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index fa2c7b36..82d0ac98 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -5,10 +5,10 @@ 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 let Some(m) = &extra.monotonic { + if !app.monotonics.is_empty() { let t = util::schedule_t_ident(); // Enumeration of `schedule`-able tasks @@ -26,9 +26,10 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream }) .collect::<Vec<_>>(); - let doc = "Tasks that can be scheduled".to_string(); + // let doc = "Tasks that can be scheduled".to_string(); items.push(quote!( - #[doc = #doc] + // #[doc = #doc] + #[doc(hidden)] #[allow(non_camel_case_types)] #[derive(Clone, Copy)] enum #t { @@ -36,32 +37,54 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream } )); } + } - let tq = util::tq_ident(); + for (_, monotonic) in &app.monotonics { + let monotonic_name = monotonic.ident.to_string(); + let tq = util::tq_ident(&monotonic_name); + let tq = util::mark_internal_ident(&tq); + let t = util::schedule_t_ident(); + let mono_type = &monotonic.ty; + let m_ident = util::monotonic_ident(&monotonic_name); + let m_ident = util::mark_internal_ident(&m_ident); + let app_name = &app.name; + let app_path = quote! {crate::#app_name}; - // Static variable and resource proxy + // Static variables and resource proxy { - let doc = "Timer queue".to_string(); + // let doc = &format!("Timer queue for {}", monotonic_name); let cap = app .software_tasks .iter() .map(|(_name, task)| task.args.capacity) .sum(); let n = util::capacity_typenum(cap, false); - let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>); + let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n>); items.push(quote!( - #[doc = #doc] + #[doc(hidden)] static mut #tq: #tq_ty = rtic::export::TimerQueue( rtic::export::BinaryHeap( rtic::export::iBinaryHeap::new() ) ); )); + + let mono = util::monotonic_ident(&monotonic_name); + let mono = util::mark_internal_ident(&mono); + // let doc = &format!("Storage for {}", monotonic_name); + + items.push(quote!( + #[doc(hidden)] + static mut #mono: Option<#mono_type> = None; + )); } // Timer queue handler { + let enum_ = util::interrupt_ident(); + let rt_err = util::rt_err_ident(); + let arms = app .software_tasks .iter() @@ -69,13 +92,15 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream let cfgs = &task.cfgs; let priority = task.args.priority; let rq = util::rq_ident(priority); + let rq = util::mark_internal_ident(&rq); let rqt = util::spawn_t_ident(priority); - let enum_ = util::interrupt_ident(); + + // The interrupt that runs the task dispatcher let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0; let pend = { quote!( - rtic::pend(you_must_enable_the_rt_feature_for_the_pac_in_your_cargo_toml::#enum_::#interrupt); + rtic::pend(#rt_err::#enum_::#interrupt); ) }; @@ -90,21 +115,39 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream }) .collect::<Vec<_>>(); - let sys_tick = util::suffixed("SysTick"); + let bound_interrupt = &monotonic.args.binds; + let disable_isr = if &*bound_interrupt.to_string() == "SysTick" { + quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(()).disable_interrupt()) + } else { + quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt)) + }; + items.push(quote!( #[no_mangle] - unsafe fn #sys_tick() { - use rtic::Mutex as _; + #[allow(non_snake_case)] + unsafe fn #bound_interrupt() { - while let Some((task, index)) = rtic::export::interrupt::free(|_| #tq.dequeue()) + while let Some((task, index)) = rtic::export::interrupt::free(|_| + if let Some(mono) = #app_path::#m_ident.as_mut() { + #tq.dequeue(|| #disable_isr, mono) + } else { + // We can only use the timer queue if `init` has returned, and it + // writes the `Some(monotonic)` we are accessing here. + core::hint::unreachable_unchecked() + }) { match task { #(#arms)* } } + + rtic::export::interrupt::free(|_| if let Some(mono) = #app_path::#m_ident.as_mut() { + mono.on_interrupt(); + }); } )); } } + items } |