mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-24 19:09:33 +01:00
Flattened the _ out of it
This commit is contained in:
parent
aad8f81991
commit
b4509bdbfe
11 changed files with 146 additions and 147 deletions
|
@ -7,15 +7,11 @@
|
||||||
|
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
pub struct SomeStruct;
|
|
||||||
|
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use dwt_systick_monotonic::DwtSystick;
|
use dwt_systick_monotonic::DwtSystick;
|
||||||
use rtic::time::duration::Seconds;
|
use rtic::time::duration::Seconds;
|
||||||
|
|
||||||
use super::SomeStruct;
|
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type MyMono = DwtSystick<8_000_000>; // 8 MHz
|
type MyMono = DwtSystick<8_000_000>; // 8 MHz
|
||||||
|
|
||||||
|
|
|
@ -22,4 +22,5 @@ proc-macro2 = "1"
|
||||||
proc-macro-error = "1"
|
proc-macro-error = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
rtic-syntax = "0.5.0-alpha.2"
|
# rtic-syntax = "0.5.0-alpha.2"
|
||||||
|
rtic-syntax = { path = "../../rtic-syntax" }
|
||||||
|
|
|
@ -97,8 +97,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let user_code = &app.user_code;
|
let user_code = &app.user_code;
|
||||||
let name = &app.name;
|
let name = &app.name;
|
||||||
let device = &extra.device;
|
let device = &extra.device;
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
|
|
||||||
let monotonic_parts: Vec<_> = app
|
let monotonic_parts: Vec<_> = app
|
||||||
.monotonics
|
.monotonics
|
||||||
|
@ -106,7 +104,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
.map(|(_, monotonic)| {
|
.map(|(_, monotonic)| {
|
||||||
let name = &monotonic.ident;
|
let name = &monotonic.ident;
|
||||||
let name_str = &name.to_string();
|
let name_str = &name.to_string();
|
||||||
let ty = &monotonic.ty;
|
|
||||||
let ident = util::monotonic_ident(&name_str);
|
let ident = util::monotonic_ident(&name_str);
|
||||||
let ident = util::mark_internal_ident(&ident);
|
let ident = util::mark_internal_ident(&ident);
|
||||||
let panic_str = &format!(
|
let panic_str = &format!(
|
||||||
|
@ -117,7 +114,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
"This module holds the static implementation for `{}::now()`",
|
"This module holds the static implementation for `{}::now()`",
|
||||||
name_str
|
name_str
|
||||||
);
|
);
|
||||||
let user_imports = &app.user_imports;
|
|
||||||
|
|
||||||
let default_monotonic = if monotonic.args.default {
|
let default_monotonic = if monotonic.args.default {
|
||||||
quote!(pub use #name::now;)
|
quote!(pub use #name::now;)
|
||||||
|
@ -131,17 +127,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
#user_imports
|
|
||||||
)*
|
|
||||||
|
|
||||||
/// Read the current time from this monotonic
|
/// Read the current time from this monotonic
|
||||||
pub fn now() -> rtic::time::Instant<#ty> {
|
pub fn now() -> rtic::time::Instant<super::super::#name> {
|
||||||
rtic::export::interrupt::free(|_| {
|
rtic::export::interrupt::free(|_| {
|
||||||
use rtic::Monotonic as _;
|
use rtic::Monotonic as _;
|
||||||
use rtic::time::Clock as _;
|
use rtic::time::Clock as _;
|
||||||
if let Some(m) = unsafe{ #app_path::#ident.get_mut_unchecked() } {
|
if let Some(m) = unsafe{ super::super::#ident.get_mut_unchecked() } {
|
||||||
if let Ok(v) = m.try_now() {
|
if let Ok(v) = m.try_now() {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,11 +155,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
|
|
||||||
/// Holds static methods for each monotonic.
|
/// Holds static methods for each monotonic.
|
||||||
pub mod monotonics {
|
pub mod monotonics {
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
#user_imports
|
|
||||||
)*
|
|
||||||
|
|
||||||
#(#monotonic_parts)*
|
#(#monotonic_parts)*
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -82,8 +82,6 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
quote!(#name::Locals::new(),)
|
quote!(#name::Locals::new(),)
|
||||||
};
|
};
|
||||||
|
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
quote!(
|
quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#t::#name => {
|
#t::#name => {
|
||||||
|
@ -95,7 +93,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
.read();
|
.read();
|
||||||
#fq.get_mut_unchecked().split().0.enqueue_unchecked(index);
|
#fq.get_mut_unchecked().split().0.enqueue_unchecked(index);
|
||||||
let priority = &rtic::export::Priority::new(PRIORITY);
|
let priority = &rtic::export::Priority::new(PRIORITY);
|
||||||
#app_path::#name(
|
#name(
|
||||||
#locals_new
|
#locals_new
|
||||||
#name::Context::new(priority)
|
#name::Context::new(priority)
|
||||||
#(,#pats)*
|
#(,#pats)*
|
||||||
|
|
|
@ -40,8 +40,6 @@ pub fn codegen(
|
||||||
let cfgs = &task.cfgs;
|
let cfgs = &task.cfgs;
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
|
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
mod_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -51,7 +49,7 @@ pub fn codegen(
|
||||||
const PRIORITY: u8 = #priority;
|
const PRIORITY: u8 = #priority;
|
||||||
|
|
||||||
rtic::export::run(PRIORITY, || {
|
rtic::export::run(PRIORITY, || {
|
||||||
#app_path::#name(
|
#name(
|
||||||
#locals_new
|
#locals_new
|
||||||
#name::Context::new(&rtic::export::Priority::new(PRIORITY))
|
#name::Context::new(&rtic::export::Priority::new(PRIORITY))
|
||||||
)
|
)
|
||||||
|
|
|
@ -74,10 +74,8 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
let locals_new = locals_new.iter();
|
let locals_new = locals_new.iter();
|
||||||
let call_idle = quote!(#app_path::#name(
|
let call_idle = quote!(#name(
|
||||||
#(#locals_new,)*
|
#(#locals_new,)*
|
||||||
#name::Context::new(&rtic::export::Priority::new(0))
|
#name::Context::new(&rtic::export::Priority::new(0))
|
||||||
));
|
));
|
||||||
|
|
|
@ -65,11 +65,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> CodegenResult {
|
||||||
mod_app = Some(constructor);
|
mod_app = Some(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
let locals_new = locals_new.iter();
|
let locals_new = locals_new.iter();
|
||||||
let call_init = Some(
|
let call_init = Some(
|
||||||
quote!(let (late, mut monotonics) = #app_path::#name(#(#locals_new,)* #name::Context::new(core.into()));),
|
quote!(let (late, mut monotonics) = #name(#(#locals_new,)* #name::Context::new(core.into()));),
|
||||||
);
|
);
|
||||||
|
|
||||||
root_init.push(module::codegen(
|
root_init.push(module::codegen(
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtic_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
|
||||||
|
|
||||||
pub fn codegen(
|
pub fn codegen(
|
||||||
ctxt: Context,
|
ctxt: Context,
|
||||||
resources_tick: bool,
|
resources_tick: bool,
|
||||||
|
@ -12,48 +11,13 @@ pub fn codegen(
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
|
let mut module_items = vec![];
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
// Used to copy task cfgs to the whole module
|
// Used to copy task cfgs to the whole module
|
||||||
let mut task_cfgs = vec![];
|
let mut task_cfgs = vec![];
|
||||||
|
|
||||||
let name = ctxt.ident(app);
|
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;
|
let mut lt = None;
|
||||||
match ctxt {
|
match ctxt {
|
||||||
|
@ -94,7 +58,7 @@ pub fn codegen(
|
||||||
|
|
||||||
if ctxt.has_locals(app) {
|
if ctxt.has_locals(app) {
|
||||||
let ident = util::locals_ident(ctxt, app);
|
let ident = util::locals_ident(ctxt, app);
|
||||||
items.push(quote!(
|
module_items.push(quote!(
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use super::#ident as Locals;
|
pub use super::#ident as Locals;
|
||||||
));
|
));
|
||||||
|
@ -110,14 +74,14 @@ pub fn codegen(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
items.push(quote!(
|
module_items.push(quote!(
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use super::#ident as Resources;
|
pub use super::#ident as Resources;
|
||||||
));
|
));
|
||||||
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
/// Resources this task has access to
|
/// Resources this task has access to
|
||||||
pub resources: Resources<#lt>
|
pub resources: #name::Resources<#lt>
|
||||||
));
|
));
|
||||||
|
|
||||||
let priority = if ctxt.is_init() {
|
let priority = if ctxt.is_init() {
|
||||||
|
@ -125,7 +89,7 @@ pub fn codegen(
|
||||||
} else {
|
} else {
|
||||||
Some(quote!(priority))
|
Some(quote!(priority))
|
||||||
};
|
};
|
||||||
values.push(quote!(resources: Resources::new(#priority)));
|
values.push(quote!(resources: #name::Resources::new(#priority)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Context::Init = ctxt {
|
if let Context::Init = ctxt {
|
||||||
|
@ -145,13 +109,17 @@ pub fn codegen(
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let internal_late_ident = util::mark_internal_name("LateResources");
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
/// Resources initialized at runtime
|
/// Resources initialized at runtime
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub struct LateResources {
|
pub struct #internal_late_ident {
|
||||||
#(#late_fields),*
|
#(#late_fields),*
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
module_items.push(quote!(
|
||||||
|
pub use super::#internal_late_ident as LateResources;
|
||||||
|
));
|
||||||
|
|
||||||
let monotonic_types: Vec<_> = app
|
let monotonic_types: Vec<_> = app
|
||||||
.monotonics
|
.monotonics
|
||||||
|
@ -162,13 +130,19 @@ pub fn codegen(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let internal_monotonics_ident = util::mark_internal_name("Monotonics");
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
/// Monotonics used by the system
|
/// Monotonics used by the system
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub struct Monotonics(
|
pub struct #internal_monotonics_ident(
|
||||||
#(pub #monotonic_types),*
|
#(pub #monotonic_types),*
|
||||||
);
|
);
|
||||||
));
|
));
|
||||||
|
|
||||||
|
module_items.push(quote!(
|
||||||
|
pub use super::#internal_monotonics_ident as Monotonics;
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = match ctxt {
|
let doc = match ctxt {
|
||||||
|
@ -178,6 +152,19 @@ pub fn codegen(
|
||||||
Context::SoftwareTask(_) => "Software task",
|
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() {
|
let core = if ctxt.is_init() {
|
||||||
Some(quote!(core: rtic::export::Peripherals,))
|
Some(quote!(core: rtic::export::Peripherals,))
|
||||||
} else {
|
} else {
|
||||||
|
@ -190,22 +177,31 @@ pub fn codegen(
|
||||||
Some(quote!(priority: &#lt rtic::export::Priority))
|
Some(quote!(priority: &#lt rtic::export::Priority))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let internal_context_name = util::internal_task_ident(name, "Context");
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
/// Execution context
|
/// Execution context
|
||||||
pub struct Context<#lt> {
|
pub struct #internal_context_name<#lt> {
|
||||||
#(#fields,)*
|
#(#fields,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<#lt> Context<#lt> {
|
#(#cfgs)*
|
||||||
|
impl<#lt> #internal_context_name<#lt> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn new(#core #priority) -> Self {
|
pub unsafe fn new(#core #priority) -> Self {
|
||||||
Context {
|
#internal_context_name {
|
||||||
#(#values,)*
|
#(#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,
|
// not sure if this is the right way, maybe its backwards,
|
||||||
// that spawn_module should put in in root
|
// that spawn_module should put in in root
|
||||||
|
|
||||||
|
@ -234,26 +230,26 @@ pub fn codegen(
|
||||||
.expect("RTIC-ICE: interrupt identifer not found")
|
.expect("RTIC-ICE: interrupt identifer not found")
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
let internal_spawn_ident = util::internal_task_ident(name, "spawn");
|
||||||
|
|
||||||
// Spawn caller
|
// Spawn caller
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
|
||||||
#(#all_task_imports)*
|
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
/// Spawns the task directly
|
/// Spawns the task directly
|
||||||
pub fn spawn(#(#args,)*) -> Result<(), #ty> {
|
pub fn #internal_spawn_ident(#(#args,)*) -> Result<(), #ty> {
|
||||||
let input = #tupled;
|
let input = #tupled;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) {
|
if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) {
|
||||||
#app_path::#inputs
|
#inputs
|
||||||
.get_mut_unchecked()
|
.get_mut_unchecked()
|
||||||
.get_unchecked_mut(usize::from(index))
|
.get_unchecked_mut(usize::from(index))
|
||||||
.as_mut_ptr()
|
.as_mut_ptr()
|
||||||
.write(input);
|
.write(input);
|
||||||
|
|
||||||
rtic::export::interrupt::free(|_| {
|
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);
|
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
|
// Schedule caller
|
||||||
for (_, monotonic) in &app.monotonics {
|
for (_, monotonic) in &app.monotonics {
|
||||||
let instants = util::monotonic_instants_ident(name, &monotonic.ident);
|
let instants = util::monotonic_instants_ident(name, &monotonic.ident);
|
||||||
|
@ -282,12 +283,6 @@ pub fn codegen(
|
||||||
let m_isr = &monotonic.args.binds;
|
let m_isr = &monotonic.args.binds;
|
||||||
let enum_ = util::interrupt_ident();
|
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" {
|
let (enable_interrupt, pend) = if &*m_isr.to_string() == "SysTick" {
|
||||||
(
|
(
|
||||||
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
|
quote!(core::mem::transmute::<_, cortex_m::peripheral::SYST>(())
|
||||||
|
@ -297,49 +292,56 @@ pub fn codegen(
|
||||||
} else {
|
} else {
|
||||||
let rt_err = util::rt_err_ident();
|
let rt_err = util::rt_err_ident();
|
||||||
(
|
(
|
||||||
quote!(rtic::export::NVIC::unmask(#app_path::#rt_err::#enum_::#m_isr)),
|
quote!(rtic::export::NVIC::unmask(#rt_err::#enum_::#m_isr)),
|
||||||
quote!(rtic::pend(#app_path::#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());
|
let tq_marker = util::mark_internal_ident(&util::timer_queue_marker_ident());
|
||||||
|
|
||||||
// For future use
|
// For future use
|
||||||
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
|
// let doc = format!(" RTIC internal: {}:{}", file!(), line!());
|
||||||
// items.push(quote!(#[doc = #doc]));
|
// 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!(
|
items.push(quote!(
|
||||||
/// Holds methods related to this monotonic
|
pub struct #internal_spawn_handle_ident {
|
||||||
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 {
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
marker: u32,
|
marker: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpawnHandle {
|
impl #internal_spawn_handle_ident {
|
||||||
pub fn cancel(self) -> Result<#ty, ()> {
|
pub fn cancel(self) -> Result<#ty, ()> {
|
||||||
rtic::export::interrupt::free(|_| unsafe {
|
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) {
|
if let Some((_task, index)) = tq.cancel_marker(self.marker) {
|
||||||
// Get the message
|
// Get the message
|
||||||
let msg = #app_path::#inputs
|
let msg = #inputs
|
||||||
.get_unchecked()
|
.get_unchecked()
|
||||||
.get_unchecked(usize::from(index))
|
.get_unchecked(usize::from(index))
|
||||||
.as_ptr()
|
.as_ptr()
|
||||||
.read();
|
.read();
|
||||||
// Return the index to the free queue
|
// 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)
|
Ok(msg)
|
||||||
} else {
|
} else {
|
||||||
|
@ -351,20 +353,20 @@ pub fn codegen(
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()>
|
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()>
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
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 {
|
rtic::export::interrupt::free(|_| unsafe {
|
||||||
let marker = *#tq_marker.get_mut_unchecked();
|
let marker = *#tq_marker.get_mut_unchecked();
|
||||||
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
|
*#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]`,
|
/// 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]`
|
/// 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
|
duration: D
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<SpawnHandle, #ty>
|
) -> Result<#name::#m::SpawnHandle, #ty>
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
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)
|
rtic::time::Instant::new(0)
|
||||||
} else {
|
} else {
|
||||||
#app_path::monotonics::#m::now()
|
monotonics::#m::now()
|
||||||
};
|
};
|
||||||
|
|
||||||
spawn_at(instant + duration #(,#untupled)*)
|
#internal_spawn_at_ident(instant + duration #(,#untupled)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
/// Spawns the task at a fixed time instant
|
/// Spawns the task at a fixed time instant
|
||||||
pub fn spawn_at(
|
pub fn #internal_spawn_at_ident(
|
||||||
instant: rtic::time::Instant<#app_path::#mono_type>
|
instant: rtic::time::Instant<#mono_type>
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<SpawnHandle, #ty> {
|
) -> Result<#name::#m::SpawnHandle, #ty> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let input = #tupled;
|
let input = #tupled;
|
||||||
if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.get_mut_unchecked().dequeue()) {
|
if let Some(index) = rtic::export::interrupt::free(|_| #fq.get_mut_unchecked().dequeue()) {
|
||||||
#app_path::#inputs
|
#inputs
|
||||||
.get_mut_unchecked()
|
.get_mut_unchecked()
|
||||||
.get_unchecked_mut(usize::from(index))
|
.get_unchecked_mut(usize::from(index))
|
||||||
.as_mut_ptr()
|
.as_mut_ptr()
|
||||||
.write(input);
|
.write(input);
|
||||||
|
|
||||||
#app_path::#instants
|
#instants
|
||||||
.get_mut_unchecked()
|
.get_mut_unchecked()
|
||||||
.get_unchecked_mut(usize::from(index))
|
.get_unchecked_mut(usize::from(index))
|
||||||
.as_mut_ptr()
|
.as_mut_ptr()
|
||||||
|
@ -417,44 +419,40 @@ pub fn codegen(
|
||||||
let nr = rtic::export::NotReady {
|
let nr = rtic::export::NotReady {
|
||||||
instant,
|
instant,
|
||||||
index,
|
index,
|
||||||
task: #app_path::#t::#name,
|
task: #t::#name,
|
||||||
marker,
|
marker,
|
||||||
};
|
};
|
||||||
|
|
||||||
*#tq_marker.get_mut_unchecked() = #tq_marker.get_mut_unchecked().wrapping_add(1);
|
*#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(
|
tq.enqueue_unchecked(
|
||||||
nr,
|
nr,
|
||||||
|| #enable_interrupt,
|
|| #enable_interrupt,
|
||||||
|| #pend,
|
|| #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 {
|
} else {
|
||||||
Err(input)
|
Err(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
let user_imports = &app.user_imports;
|
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
#(#items)*
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#(#task_cfgs)*
|
#(#task_cfgs)*
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
#(
|
#(#module_items)*
|
||||||
#[allow(unused_imports)]
|
|
||||||
#user_imports
|
|
||||||
)*
|
|
||||||
#(#items)*
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -93,8 +93,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
// Compile time assert that this priority is supported by the device
|
// Compile time assert that this priority is supported by the device
|
||||||
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];));
|
||||||
|
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
let mono_type = &monotonic.ty;
|
let mono_type = &monotonic.ty;
|
||||||
|
|
||||||
if &*binds.to_string() == "SysTick" {
|
if &*binds.to_string() == "SysTick" {
|
||||||
|
@ -121,7 +119,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
|
|
||||||
// Always enable monotonic interrupts if they should never be off
|
// Always enable monotonic interrupts if they should never be off
|
||||||
if !<#mono_type as rtic::Monotonic>::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
|
if !<#mono_type as rtic::Monotonic>::DISABLE_INTERRUPT_ON_EMPTY_QUEUE {
|
||||||
rtic::export::NVIC::unmask(#app_path::#rt_err::#interrupt::#binds);
|
rtic::export::NVIC::unmask(#rt_err::#interrupt::#binds);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,6 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
let mono_type = &monotonic.ty;
|
let mono_type = &monotonic.ty;
|
||||||
let m_ident = util::monotonic_ident(&monotonic_name);
|
let m_ident = util::monotonic_ident(&monotonic_name);
|
||||||
let m_ident = util::mark_internal_ident(&m_ident);
|
let m_ident = util::mark_internal_ident(&m_ident);
|
||||||
let app_name = &app.name;
|
|
||||||
let app_path = quote! {crate::#app_name};
|
|
||||||
|
|
||||||
// Static variables and resource proxy
|
// Static variables and resource proxy
|
||||||
{
|
{
|
||||||
|
@ -139,7 +137,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe fn #bound_interrupt() {
|
unsafe fn #bound_interrupt() {
|
||||||
while let Some((task, index)) = rtic::export::interrupt::free(|_|
|
while let Some((task, index)) = rtic::export::interrupt::free(|_|
|
||||||
if let Some(mono) = #app_path::#m_ident.get_mut_unchecked().as_mut() {
|
if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() {
|
||||||
(&mut *#tq.get_mut_unchecked().as_mut_ptr()).dequeue(|| #disable_isr, mono)
|
(&mut *#tq.get_mut_unchecked().as_mut_ptr()).dequeue(|| #disable_isr, mono)
|
||||||
} else {
|
} else {
|
||||||
// We can only use the timer queue if `init` has returned, and it
|
// We can only use the timer queue if `init` has returned, and it
|
||||||
|
@ -152,7 +150,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtic::export::interrupt::free(|_| if let Some(mono) = #app_path::#m_ident.get_mut_unchecked().as_mut() {
|
rtic::export::interrupt::free(|_| if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() {
|
||||||
mono.on_interrupt();
|
mono.on_interrupt();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,27 @@ pub fn is_exception(name: &Ident) -> bool {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate an internal identifier for monotonics
|
||||||
|
pub fn internal_monotonics_ident(task: &Ident, monotonic: &Ident, ident_name: &str) -> Ident {
|
||||||
|
Ident::new(
|
||||||
|
&format!(
|
||||||
|
"__rtic_internal_{}_{}_{}",
|
||||||
|
task.to_string(),
|
||||||
|
monotonic.to_string(),
|
||||||
|
ident_name,
|
||||||
|
),
|
||||||
|
Span::call_site(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate an internal identifier for tasks
|
||||||
|
pub fn internal_task_ident(task: &Ident, ident_name: &str) -> Ident {
|
||||||
|
Ident::new(
|
||||||
|
&format!("__rtic_internal_{}_{}", task.to_string(), ident_name,),
|
||||||
|
Span::call_site(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Mark an ident as internal
|
/// Mark an ident as internal
|
||||||
pub fn mark_internal_ident(ident: &Ident) -> Ident {
|
pub fn mark_internal_ident(ident: &Ident) -> Ident {
|
||||||
Ident::new(
|
Ident::new(
|
||||||
|
@ -119,6 +140,14 @@ pub fn mark_internal_ident(ident: &Ident) -> Ident {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mark an ident as internal
|
||||||
|
pub fn mark_internal_name(name: &str) -> Ident {
|
||||||
|
Ident::new(
|
||||||
|
&format!("__rtic_internal_{}", name),
|
||||||
|
Span::call_site(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn link_section_index() -> usize {
|
fn link_section_index() -> usize {
|
||||||
static INDEX: AtomicUsize = AtomicUsize::new(0);
|
static INDEX: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue