aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen/timer_queue.rs
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <jorge@japaric.io> 2019-06-13 23:56:59 +0200
committerGravatar Jorge Aparicio <jorge@japaric.io> 2019-06-13 23:56:59 +0200
commit81275bfa4f41e2066770087f3a33cad4227eab41 (patch)
treec779a68e7cecf4c2613c7593376f980cea5dbc05 /macros/src/codegen/timer_queue.rs
parentfafeeb27270ef24fc3852711c6032f65aa7dbcc0 (diff)
downloadrtic-81275bfa4f41e2066770087f3a33cad4227eab41.tar.gz
rtic-81275bfa4f41e2066770087f3a33cad4227eab41.tar.zst
rtic-81275bfa4f41e2066770087f3a33cad4227eab41.zip
rtfm-syntax refactor + heterogeneous multi-core support
Diffstat (limited to 'macros/src/codegen/timer_queue.rs')
-rw-r--r--macros/src/codegen/timer_queue.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
new file mode 100644
index 00000000..cb845774
--- /dev/null
+++ b/macros/src/codegen/timer_queue.rs
@@ -0,0 +1,147 @@
+use proc_macro2::TokenStream as TokenStream2;
+use quote::quote;
+use rtfm_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> {
+ let mut items = vec![];
+
+ for (&sender, timer_queue) in &analysis.timer_queues {
+ let cfg_sender = util::cfg_core(sender, app.args.cores);
+ let t = util::schedule_t_ident(sender);
+
+ // Enumeration of `schedule`-able tasks
+ {
+ let variants = timer_queue
+ .tasks
+ .iter()
+ .map(|name| {
+ let cfgs = &app.software_tasks[name].cfgs;
+
+ quote!(
+ #(#cfgs)*
+ #name
+ )
+ })
+ .collect::<Vec<_>>();
+
+ let doc = format!("Tasks that can be scheduled from core #{}", sender);
+ items.push(quote!(
+ #cfg_sender
+ #[doc = #doc]
+ #[allow(non_camel_case_types)]
+ #[derive(Clone, Copy)]
+ enum #t {
+ #(#variants,)*
+ }
+ ));
+ }
+
+ let tq = util::tq_ident(sender);
+
+ // Static variable and resource proxy
+ {
+ let doc = format!("Core #{} timer queue", sender);
+ let m = extra.monotonic();
+ let n = util::capacity_typenum(timer_queue.capacity, false);
+ let tq_ty = quote!(rtfm::export::TimerQueue<#m, #t, #n>);
+
+ items.push(quote!(
+ #cfg_sender
+ #[doc = #doc]
+ static mut #tq: #tq_ty = rtfm::export::TimerQueue(
+ rtfm::export::BinaryHeap(
+ rtfm::export::iBinaryHeap::new()
+ )
+ );
+
+ #cfg_sender
+ struct #tq<'a> {
+ priority: &'a rtfm::export::Priority,
+ }
+ ));
+
+ items.push(util::impl_mutex(
+ extra,
+ &[],
+ cfg_sender.as_ref(),
+ false,
+ &tq,
+ tq_ty,
+ timer_queue.ceiling,
+ quote!(&mut #tq),
+ ));
+ }
+
+ // Timer queue handler
+ {
+ let device = extra.device;
+ let arms = timer_queue
+ .tasks
+ .iter()
+ .map(|name| {
+ let task = &app.software_tasks[name];
+
+ let cfgs = &task.cfgs;
+ let priority = task.args.priority;
+ let receiver = task.args.core;
+ let rq = util::rq_ident(receiver, priority, sender);
+ let rqt = util::spawn_t_ident(receiver, priority, sender);
+ let interrupt = &analysis.interrupts[&receiver][&priority];
+
+ let pend = if sender != receiver {
+ quote!(
+ #device::xpend(#receiver, #device::Interrupt::#interrupt);
+ )
+ } else {
+ quote!(
+ rtfm::pend(#device::Interrupt::#interrupt);
+ )
+ };
+
+ quote!(
+ #(#cfgs)*
+ #t::#name => {
+ (#rq { priority: &rtfm::export::Priority::new(PRIORITY) }).lock(|rq| {
+ rq.split().0.enqueue_unchecked((#rqt::#name, index))
+ });
+
+ #pend
+ }
+ )
+ })
+ .collect::<Vec<_>>();
+
+ let priority = timer_queue.priority;
+ items.push(quote!(
+ #cfg_sender
+ #[no_mangle]
+ unsafe fn SysTick() {
+ use rtfm::Mutex as _;
+
+ /// The priority of this handler
+ const PRIORITY: u8 = #priority;
+
+ rtfm::export::run(PRIORITY, || {
+ while let Some((task, index)) = (#tq {
+ // NOTE dynamic priority is always the static priority at this point
+ priority: &rtfm::export::Priority::new(PRIORITY),
+ })
+ // NOTE `inline(always)` produces faster and smaller code
+ .lock(#[inline(always)]
+ |tq| tq.dequeue())
+ {
+ match task {
+ #(#arms)*
+ }
+ }
+ });
+ }
+ ));
+ }
+ }
+
+ items
+}