2021-05-06 19:40:37 +02:00
|
|
|
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
2019-06-13 23:56:59 +02:00
|
|
|
use proc_macro2::TokenStream as TokenStream2;
|
|
|
|
use quote::quote;
|
2020-06-11 19:18:29 +02:00
|
|
|
use rtic_syntax::{ast::App, Context};
|
2019-06-13 23:56:59 +02:00
|
|
|
|
2020-10-05 21:57:44 +02:00
|
|
|
pub fn codegen(
|
|
|
|
ctxt: Context,
|
|
|
|
resources_tick: bool,
|
|
|
|
app: &App,
|
|
|
|
analysis: &Analysis,
|
|
|
|
extra: &Extra,
|
|
|
|
) -> TokenStream2 {
|
2019-06-13 23:56:59 +02:00
|
|
|
let mut items = vec![];
|
2021-05-06 19:40:37 +02:00
|
|
|
let mut module_items = vec![];
|
2019-06-13 23:56:59 +02:00
|
|
|
let mut fields = vec![];
|
|
|
|
let mut values = vec![];
|
2020-10-16 10:20:43 +02:00
|
|
|
// Used to copy task cfgs to the whole module
|
|
|
|
let mut task_cfgs = vec![];
|
2019-06-13 23:56:59 +02:00
|
|
|
|
|
|
|
let name = ctxt.ident(app);
|
2021-03-14 21:27:21 +01:00
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
let mut lt = None;
|
|
|
|
match ctxt {
|
2020-08-27 13:21:56 +02:00
|
|
|
Context::Init => {
|
2020-12-10 20:33:13 +01:00
|
|
|
fields.push(quote!(
|
|
|
|
/// Core (Cortex-M) peripherals
|
|
|
|
pub core: rtic::export::Peripherals
|
|
|
|
));
|
2019-06-13 23:56:59 +02:00
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
if extra.peripherals {
|
2020-10-23 10:35:56 +02:00
|
|
|
let device = &extra.device;
|
2019-06-13 23:56:59 +02:00
|
|
|
|
|
|
|
fields.push(quote!(
|
|
|
|
/// Device peripherals
|
|
|
|
pub device: #device::Peripherals
|
|
|
|
));
|
|
|
|
|
|
|
|
values.push(quote!(device: #device::Peripherals::steal()));
|
|
|
|
}
|
|
|
|
|
2020-10-01 20:01:25 +02:00
|
|
|
lt = Some(quote!('a));
|
|
|
|
fields.push(quote!(
|
|
|
|
/// Critical section token for init
|
|
|
|
pub cs: rtic::export::CriticalSection<#lt>
|
|
|
|
));
|
|
|
|
|
|
|
|
values.push(quote!(cs: rtic::export::CriticalSection::new()));
|
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
values.push(quote!(core));
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
Context::Idle => {}
|
2019-06-13 23:56:59 +02:00
|
|
|
|
2021-02-25 17:32:12 +01:00
|
|
|
Context::HardwareTask(_) => {}
|
2019-06-13 23:56:59 +02:00
|
|
|
|
2021-02-25 17:32:12 +01:00
|
|
|
Context::SoftwareTask(_) => {}
|
2019-06-13 23:56:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ctxt.has_locals(app) {
|
|
|
|
let ident = util::locals_ident(ctxt, app);
|
2021-05-06 19:40:37 +02:00
|
|
|
module_items.push(quote!(
|
2019-06-13 23:56:59 +02:00
|
|
|
#[doc(inline)]
|
|
|
|
pub use super::#ident as Locals;
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ctxt.has_resources(app) {
|
|
|
|
let ident = util::resources_ident(ctxt, app);
|
2021-02-25 19:05:39 +01:00
|
|
|
let ident = util::mark_internal_ident(&ident);
|
2019-06-13 23:56:59 +02:00
|
|
|
let lt = if resources_tick {
|
|
|
|
lt = Some(quote!('a));
|
|
|
|
Some(quote!('a))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
module_items.push(quote!(
|
2019-06-13 23:56:59 +02:00
|
|
|
#[doc(inline)]
|
|
|
|
pub use super::#ident as Resources;
|
|
|
|
));
|
|
|
|
|
|
|
|
fields.push(quote!(
|
|
|
|
/// Resources this task has access to
|
2021-05-06 19:40:37 +02:00
|
|
|
pub resources: #name::Resources<#lt>
|
2019-06-13 23:56:59 +02:00
|
|
|
));
|
|
|
|
|
|
|
|
let priority = if ctxt.is_init() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(quote!(priority))
|
|
|
|
};
|
2021-05-06 19:40:37 +02:00
|
|
|
values.push(quote!(resources: #name::Resources::new(#priority)));
|
2019-06-13 23:56:59 +02:00
|
|
|
}
|
|
|
|
|
2020-08-27 13:21:56 +02:00
|
|
|
if let Context::Init = ctxt {
|
2020-12-10 20:33:13 +01:00
|
|
|
let late_fields = analysis
|
|
|
|
.late_resources
|
|
|
|
.iter()
|
|
|
|
.flat_map(|resources| {
|
|
|
|
resources.iter().map(|name| {
|
|
|
|
let ty = &app.late_resources[name].ty;
|
|
|
|
let cfgs = &app.late_resources[name].cfgs;
|
|
|
|
|
|
|
|
quote!(
|
|
|
|
#(#cfgs)*
|
|
|
|
pub #name: #ty
|
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
2019-06-13 23:56:59 +02:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let internal_late_ident = util::mark_internal_name("LateResources");
|
2020-10-01 19:38:49 +02:00
|
|
|
items.push(quote!(
|
2020-12-10 20:33:13 +01:00
|
|
|
/// Resources initialized at runtime
|
|
|
|
#[allow(non_snake_case)]
|
2021-05-06 19:40:37 +02:00
|
|
|
pub struct #internal_late_ident {
|
2020-12-10 20:33:13 +01:00
|
|
|
#(#late_fields),*
|
|
|
|
}
|
2020-10-01 19:38:49 +02:00
|
|
|
));
|
2021-05-06 19:40:37 +02:00
|
|
|
module_items.push(quote!(
|
|
|
|
pub use super::#internal_late_ident as LateResources;
|
|
|
|
));
|
2020-12-03 21:04:06 +01:00
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
let monotonic_types: Vec<_> = app
|
|
|
|
.monotonics
|
|
|
|
.iter()
|
|
|
|
.map(|(_, monotonic)| {
|
2021-02-25 19:05:39 +01:00
|
|
|
let mono = &monotonic.ty;
|
|
|
|
quote! {#mono}
|
2020-12-10 20:33:13 +01:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let internal_monotonics_ident = util::mark_internal_name("Monotonics");
|
|
|
|
|
2020-12-03 21:04:06 +01:00
|
|
|
items.push(quote!(
|
2020-12-10 20:33:13 +01:00
|
|
|
/// Monotonics used by the system
|
|
|
|
#[allow(non_snake_case)]
|
2021-05-06 19:40:37 +02:00
|
|
|
pub struct #internal_monotonics_ident(
|
2021-02-04 20:22:02 +01:00
|
|
|
#(pub #monotonic_types),*
|
2020-12-10 20:33:13 +01:00
|
|
|
);
|
2020-12-03 21:04:06 +01:00
|
|
|
));
|
2021-05-06 19:40:37 +02:00
|
|
|
|
|
|
|
module_items.push(quote!(
|
|
|
|
pub use super::#internal_monotonics_ident as Monotonics;
|
|
|
|
));
|
2019-06-13 23:56:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let doc = match ctxt {
|
2020-08-27 13:21:56 +02:00
|
|
|
Context::Idle => "Idle loop",
|
|
|
|
Context::Init => "Initialization function",
|
2019-06-13 23:56:59 +02:00
|
|
|
Context::HardwareTask(_) => "Hardware task",
|
|
|
|
Context::SoftwareTask(_) => "Software task",
|
|
|
|
};
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let v = Vec::new();
|
|
|
|
let cfgs = match ctxt {
|
|
|
|
Context::HardwareTask(t) => {
|
|
|
|
&app.hardware_tasks[t].cfgs
|
|
|
|
// ...
|
2021-05-27 18:06:28 +02:00
|
|
|
}
|
2021-05-06 19:40:37 +02:00
|
|
|
Context::SoftwareTask(t) => {
|
|
|
|
&app.software_tasks[t].cfgs
|
|
|
|
// ...
|
2021-05-27 18:06:28 +02:00
|
|
|
}
|
2021-05-06 19:40:37 +02:00
|
|
|
_ => &v,
|
|
|
|
};
|
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
let core = if ctxt.is_init() {
|
2020-12-08 20:49:13 +01:00
|
|
|
Some(quote!(core: rtic::export::Peripherals,))
|
2019-06-13 23:56:59 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let priority = if ctxt.is_init() {
|
|
|
|
None
|
|
|
|
} else {
|
2020-06-11 19:18:29 +02:00
|
|
|
Some(quote!(priority: &#lt rtic::export::Priority))
|
2019-06-13 23:56:59 +02:00
|
|
|
};
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let internal_context_name = util::internal_task_ident(name, "Context");
|
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
items.push(quote!(
|
2021-05-06 19:40:37 +02:00
|
|
|
#(#cfgs)*
|
2019-06-13 23:56:59 +02:00
|
|
|
/// Execution context
|
2021-05-06 19:40:37 +02:00
|
|
|
pub struct #internal_context_name<#lt> {
|
2019-06-13 23:56:59 +02:00
|
|
|
#(#fields,)*
|
|
|
|
}
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
#(#cfgs)*
|
|
|
|
impl<#lt> #internal_context_name<#lt> {
|
2019-06-13 23:56:59 +02:00
|
|
|
#[inline(always)]
|
2020-12-10 20:33:13 +01:00
|
|
|
pub unsafe fn new(#core #priority) -> Self {
|
2021-05-06 19:40:37 +02:00
|
|
|
#internal_context_name {
|
2019-06-13 23:56:59 +02:00
|
|
|
#(#values,)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
));
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
module_items.push(quote!(
|
|
|
|
#(#cfgs)*
|
|
|
|
pub use super::#internal_context_name as Context;
|
|
|
|
));
|
|
|
|
|
2020-10-05 21:57:44 +02:00
|
|
|
// not sure if this is the right way, maybe its backwards,
|
|
|
|
// that spawn_module should put in in root
|
|
|
|
|
|
|
|
if let Context::SoftwareTask(..) = ctxt {
|
|
|
|
let spawnee = &app.software_tasks[name];
|
|
|
|
let priority = spawnee.args.priority;
|
|
|
|
let t = util::spawn_t_ident(priority);
|
|
|
|
let cfgs = &spawnee.cfgs;
|
2020-10-16 10:20:43 +02:00
|
|
|
// Store a copy of the task cfgs
|
|
|
|
task_cfgs = cfgs.clone();
|
2020-12-10 20:33:13 +01:00
|
|
|
let (args, tupled, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
|
2020-10-05 21:57:44 +02:00
|
|
|
let args = &args;
|
|
|
|
let tupled = &tupled;
|
|
|
|
let fq = util::fq_ident(name);
|
2021-02-25 19:05:39 +01:00
|
|
|
let fq = util::mark_internal_ident(&fq);
|
2020-10-05 21:57:44 +02:00
|
|
|
let rq = util::rq_ident(priority);
|
2021-02-25 19:05:39 +01:00
|
|
|
let rq = util::mark_internal_ident(&rq);
|
2020-10-05 21:57:44 +02:00
|
|
|
let inputs = util::inputs_ident(name);
|
2021-02-25 19:05:39 +01:00
|
|
|
let inputs = util::mark_internal_ident(&inputs);
|
2020-10-05 21:57:44 +02:00
|
|
|
|
2020-10-23 10:35:56 +02:00
|
|
|
let device = &extra.device;
|
2020-10-05 21:57:44 +02:00
|
|
|
let enum_ = util::interrupt_ident();
|
2020-10-23 10:35:56 +02:00
|
|
|
let interrupt = &analysis
|
|
|
|
.interrupts
|
|
|
|
.get(&priority)
|
|
|
|
.expect("RTIC-ICE: interrupt identifer not found")
|
|
|
|
.0;
|
2020-10-05 21:57:44 +02:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let internal_spawn_ident = util::internal_task_ident(name, "spawn");
|
|
|
|
|
2020-10-11 18:38:38 +02:00
|
|
|
// Spawn caller
|
2020-10-05 21:57:44 +02:00
|
|
|
items.push(quote!(
|
2021-03-14 21:27:21 +01:00
|
|
|
|
2020-10-05 21:57:44 +02:00
|
|
|
#(#cfgs)*
|
2021-02-25 19:05:39 +01:00
|
|
|
/// Spawns the task directly
|
2021-05-06 19:40:37 +02:00
|
|
|
pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> {
|
2020-10-05 21:57:44 +02:00
|
|
|
let input = #tupled;
|
2020-10-08 17:33:16 +02:00
|
|
|
|
2020-10-11 18:38:38 +02:00
|
|
|
unsafe {
|
2021-05-06 19:40:37 +02:00
|
|
|
if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) {
|
|
|
|
#inputs
|
2021-04-08 18:25:09 +02:00
|
|
|
.get_mut_unchecked()
|
2020-10-05 21:57:44 +02:00
|
|
|
.get_unchecked_mut(usize::from(index))
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write(input);
|
|
|
|
|
2020-10-11 18:38:38 +02:00
|
|
|
rtic::export::interrupt::free(|_| {
|
2021-05-06 19:40:37 +02:00
|
|
|
#rq.get_mut_unchecked().enqueue_unchecked((#t::#name, index));
|
2020-10-11 18:38:38 +02:00
|
|
|
});
|
2020-10-05 21:57:44 +02:00
|
|
|
|
2020-10-11 18:38:38 +02:00
|
|
|
rtic::pend(#device::#enum_::#interrupt);
|
2020-10-05 21:57:44 +02:00
|
|
|
|
2020-10-11 18:38:38 +02:00
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(input)
|
|
|
|
}
|
2020-10-05 21:57:44 +02:00
|
|
|
}
|
2020-10-08 17:33:16 +02:00
|
|
|
|
2020-10-05 21:57:44 +02:00
|
|
|
}));
|
2020-10-11 18:38:38 +02:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
module_items.push(quote!(
|
|
|
|
#(#cfgs)*
|
|
|
|
pub use super::#internal_spawn_ident as spawn;
|
|
|
|
));
|
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
// Schedule caller
|
|
|
|
for (_, monotonic) in &app.monotonics {
|
2020-12-12 23:24:54 +01:00
|
|
|
let instants = util::monotonic_instants_ident(name, &monotonic.ident);
|
2021-02-25 19:05:39 +01:00
|
|
|
let instants = util::mark_internal_ident(&instants);
|
2021-02-22 20:59:03 +01:00
|
|
|
let monotonic_name = monotonic.ident.to_string();
|
2020-12-10 20:33:13 +01:00
|
|
|
|
|
|
|
let tq = util::tq_ident(&monotonic.ident.to_string());
|
2021-02-25 19:05:39 +01:00
|
|
|
let tq = util::mark_internal_ident(&tq);
|
2020-12-10 20:33:13 +01:00
|
|
|
let t = util::schedule_t_ident();
|
|
|
|
let m = &monotonic.ident;
|
2021-04-07 11:06:57 +02:00
|
|
|
let mono_type = &monotonic.ident;
|
2021-02-22 20:59:03 +01:00
|
|
|
let m_ident = util::monotonic_ident(&monotonic_name);
|
2021-02-25 19:05:39 +01:00
|
|
|
let m_ident = util::mark_internal_ident(&m_ident);
|
2020-12-12 23:24:54 +01:00
|
|
|
let m_isr = &monotonic.args.binds;
|
|
|
|
let enum_ = util::interrupt_ident();
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2021-02-18 19:30:59 +01:00
|
|
|
let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" {
|
2020-12-13 14:52:16 +01:00
|
|
|
(
|
2021-02-18 19:30:59 +01:00
|
|
|
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
|
|
|
|
.enable_interrupt()),
|
2020-12-13 14:52:16 +01:00
|
|
|
quote!(cortex_m::peripheral::SCB::set_pendst()),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
let rt_err = util::rt_err_ident();
|
|
|
|
(
|
2021-05-06 19:40:37 +02:00
|
|
|
quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)),
|
|
|
|
quote!(rtic::pend(#rt_err::#enum_::#m_isr)),
|
2020-12-13 14:52:16 +01:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-03-11 19:12:02 +01:00
|
|
|
let tq_marker = util::mark_internal_ident(&util::timer_queue_marker_ident());
|
2021-02-25 19:05:39 +01:00
|
|
|
|
2021-04-22 18:38:42 +02:00
|
|
|
// For future use
|
2021-04-08 18:25:09 +02:00
|
|
|
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
|
|
|
|
// items.push(quote!(#[doc = #doc]));
|
2021-05-06 19:40:37 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
));
|
2021-04-08 18:25:09 +02:00
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
items.push(quote!(
|
2021-05-06 19:40:37 +02:00
|
|
|
pub struct #internal_spawn_handle_ident {
|
2021-03-11 19:12:02 +01:00
|
|
|
#[doc(hidden)]
|
|
|
|
marker: u32,
|
|
|
|
}
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
impl #internal_spawn_handle_ident {
|
2021-03-11 19:12:02 +01:00
|
|
|
pub fn cancel(self) -> Result<#ty, ()> {
|
2021-03-14 21:27:21 +01:00
|
|
|
rtic::export::interrupt::free(|_| unsafe {
|
2021-05-06 19:40:37 +02:00
|
|
|
let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
|
2021-03-14 21:27:21 +01:00
|
|
|
if let Some((_task, index)) = tq.cancel_marker(self.marker) {
|
|
|
|
// Get the message
|
2021-05-06 19:40:37 +02:00
|
|
|
let msg = #inputs
|
2021-04-08 18:25:09 +02:00
|
|
|
.get_unchecked()
|
|
|
|
.get_unchecked(usize::from(index))
|
|
|
|
.as_ptr()
|
|
|
|
.read();
|
2021-03-14 21:27:21 +01:00
|
|
|
// Return the index to the free queue
|
2021-05-06 19:40:37 +02:00
|
|
|
#fq.get_mut_unchecked().split().0.enqueue_unchecked(index);
|
2021-03-14 21:27:21 +01:00
|
|
|
|
|
|
|
Ok(msg)
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
})
|
2021-03-11 19:12:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()>
|
|
|
|
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
2021-05-06 19:40:37 +02:00
|
|
|
D::T: Into<<#mono_type as rtic::time::Clock>::T>,
|
2021-03-11 19:12:02 +01:00
|
|
|
{
|
2021-05-06 19:40:37 +02:00
|
|
|
self.reschedule_at(monotonics::#m::now() + duration)
|
2021-03-11 19:12:02 +01:00
|
|
|
}
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result<Self, ()>
|
2021-03-11 19:12:02 +01:00
|
|
|
{
|
2021-03-14 21:27:21 +01:00
|
|
|
rtic::export::interrupt::free(|_| unsafe {
|
2021-04-08 18:25:09 +02:00
|
|
|
let marker = *#tq_marker.get_mut_unchecked();
|
|
|
|
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
|
2021-03-11 19:12:02 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
|
2021-03-11 19:12:02 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
tq.update_marker(self.marker, marker, instant, || #pend).map(|_| #name::#m::SpawnHandle { marker })
|
2021-03-14 21:27:21 +01:00
|
|
|
})
|
2021-03-11 19:12:02 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-10 20:33:13 +01:00
|
|
|
#(#cfgs)*
|
2021-02-25 19:05:39 +01:00
|
|
|
/// Spawns the task after a set duration relative to the current time
|
2021-03-02 19:31:47 +01:00
|
|
|
///
|
|
|
|
/// 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]`
|
2021-05-06 19:40:37 +02:00
|
|
|
pub fn #internal_spawn_after_ident<D>(
|
2021-02-23 19:35:26 +01:00
|
|
|
duration: D
|
2020-12-10 20:33:13 +01:00
|
|
|
#(,#args)*
|
2021-05-06 19:40:37 +02:00
|
|
|
) -> Result<#name::#m::SpawnHandle, #ty>
|
2021-02-04 20:22:02 +01:00
|
|
|
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
2021-05-06 19:40:37 +02:00
|
|
|
D::T: Into<<#mono_type as rtic::time::Clock>::T>,
|
2021-02-04 20:22:02 +01:00
|
|
|
{
|
2021-02-22 21:45:22 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let instant = if rtic::export::interrupt::free(|_| unsafe { #m_ident.get_mut_unchecked().is_none() }) {
|
2021-02-22 21:45:22 +01:00
|
|
|
rtic::time::Instant::new(0)
|
|
|
|
} else {
|
2021-05-06 19:40:37 +02:00
|
|
|
monotonics::#m::now()
|
2021-02-22 21:45:22 +01:00
|
|
|
};
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
#internal_spawn_at_ident(instant + duration #(,#untupled)*)
|
2020-12-10 20:33:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#(#cfgs)*
|
2021-02-25 19:05:39 +01:00
|
|
|
/// Spawns the task at a fixed time instant
|
2021-05-06 19:40:37 +02:00
|
|
|
pub fn #internal_spawn_at_ident(
|
|
|
|
instant: rtic::time::Instant<#mono_type>
|
2020-12-10 20:33:13 +01:00
|
|
|
#(,#args)*
|
2021-05-06 19:40:37 +02:00
|
|
|
) -> Result<#name::#m::SpawnHandle, #ty> {
|
2020-12-10 20:33:13 +01:00
|
|
|
unsafe {
|
|
|
|
let input = #tupled;
|
2021-05-06 19:40:37 +02:00
|
|
|
if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) {
|
|
|
|
#inputs
|
2021-04-08 18:25:09 +02:00
|
|
|
.get_mut_unchecked()
|
2020-12-10 20:33:13 +01:00
|
|
|
.get_unchecked_mut(usize::from(index))
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write(input);
|
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
#instants
|
2021-04-08 18:25:09 +02:00
|
|
|
.get_mut_unchecked()
|
2020-12-10 20:33:13 +01:00
|
|
|
.get_unchecked_mut(usize::from(index))
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write(instant);
|
|
|
|
|
2021-03-11 19:12:02 +01:00
|
|
|
rtic::export::interrupt::free(|_| {
|
2021-04-08 18:25:09 +02:00
|
|
|
let marker = *#tq_marker.get_mut_unchecked();
|
2021-03-11 19:12:02 +01:00
|
|
|
let nr = rtic::export::NotReady {
|
|
|
|
instant,
|
|
|
|
index,
|
2021-05-06 19:40:37 +02:00
|
|
|
task: #t::#name,
|
2021-03-11 19:12:02 +01:00
|
|
|
marker,
|
|
|
|
};
|
|
|
|
|
2021-04-08 18:25:09 +02:00
|
|
|
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
let tq = &mut *#tq.get_mut_unchecked().as_mut_ptr();
|
2021-03-14 21:27:21 +01:00
|
|
|
|
2021-04-08 09:12:08 +02:00
|
|
|
tq.enqueue_unchecked(
|
|
|
|
nr,
|
|
|
|
|| #enable_interrupt,
|
|
|
|
|| #pend,
|
2021-05-06 19:40:37 +02:00
|
|
|
#m_ident.get_mut_unchecked().as_mut());
|
2020-12-10 20:33:13 +01:00
|
|
|
|
2021-05-06 19:40:37 +02:00
|
|
|
Ok(#name::#m::SpawnHandle { marker })
|
2021-03-11 19:12:02 +01:00
|
|
|
})
|
2020-12-10 20:33:13 +01:00
|
|
|
} else {
|
|
|
|
Err(input)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-06 19:40:37 +02:00
|
|
|
));
|
2020-12-10 20:33:13 +01:00
|
|
|
}
|
2020-10-05 21:57:44 +02:00
|
|
|
}
|
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
if !items.is_empty() {
|
|
|
|
quote!(
|
2021-05-06 19:40:37 +02:00
|
|
|
#(#items)*
|
|
|
|
|
2019-06-13 23:56:59 +02:00
|
|
|
#[allow(non_snake_case)]
|
2020-10-16 10:20:43 +02:00
|
|
|
#(#task_cfgs)*
|
2019-06-13 23:56:59 +02:00
|
|
|
#[doc = #doc]
|
|
|
|
pub mod #name {
|
2021-05-06 19:40:37 +02:00
|
|
|
#(#module_items)*
|
2019-06-13 23:56:59 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
quote!()
|
|
|
|
}
|
|
|
|
}
|