485: New codegen structure to eliminate issues with paths r=korken89 a=korken89



Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
This commit is contained in:
bors[bot] 2021-05-27 16:18:46 +00:00 committed by GitHub
commit 0b0bb1bfa9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 166 additions and 160 deletions

View file

@ -5,7 +5,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased] ## [Unreleased]
## [v0.6.0-alpha.2] - 2020-04-08 ## [v0.6.0-alpha.3] - 2021-05-27
### Fixed
- Fixed codegen structure to not have issues with local paths
- Default paths for monotonics now work properly
- New `embedded-time` version to `0.11`
## [v0.6.0-alpha.2] - 2021-04-08
### Added ### Added
@ -21,7 +29,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- The access to monotonic static methods was for example `MyMono::now()`, and is now `monotonics::MyMono::now()` - The access to monotonic static methods was for example `MyMono::now()`, and is now `monotonics::MyMono::now()`
## [v0.6.0-alpha.1] - 2020-03-04 ## [v0.6.0-alpha.1] - 2021-03-04
### Added ### Added

View file

@ -14,7 +14,7 @@ name = "cortex-m-rtic"
readme = "README.md" readme = "README.md"
repository = "https://github.com/rtic-rs/cortex-m-rtic" repository = "https://github.com/rtic-rs/cortex-m-rtic"
version = "0.6.0-alpha.2" version = "0.6.0-alpha.4"
[lib] [lib]
name = "rtic" name = "rtic"
@ -53,15 +53,15 @@ required-features = ["__v7"]
[dependencies] [dependencies]
cortex-m = "0.7.0" cortex-m = "0.7.0"
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.2" } cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.4" }
rtic-monotonic = "0.1.0-alpha.0" rtic-monotonic = "0.1.0-alpha.1"
rtic-core = "0.3.1" rtic-core = "0.3.1"
heapless = "0.6.1" heapless = "0.6.1"
bare-metal = "1.0.0" bare-metal = "1.0.0"
generic-array = "0.14" generic-array = "0.14"
[dependencies.dwt-systick-monotonic] [dependencies.dwt-systick-monotonic]
version = "0.1.0-alpha.0" version = "0.1.0-alpha.2"
optional = true optional = true
[build-dependencies] [build-dependencies]
@ -110,3 +110,4 @@ overflow-checks = false
[patch.crates-io] [patch.crates-io]
lm3s6965 = { git = "https://github.com/japaric/lm3s6965" } lm3s6965 = { git = "https://github.com/japaric/lm3s6965" }
# embedded-time = { path = "../../embedded-time" }

View file

@ -14,8 +14,10 @@ mod app {
use dwt_systick_monotonic::DwtSystick; use dwt_systick_monotonic::DwtSystick;
use rtic::time::duration::Seconds; use rtic::time::duration::Seconds;
const MONO_HZ: u32 = 8_000_000; // 8 MHz
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
type MyMono = DwtSystick<8_000_000>; // 8 MHz type MyMono = DwtSystick<MONO_HZ>;
#[init()] #[init()]
fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
@ -25,24 +27,24 @@ mod app {
let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000);
hprintln!("init").unwrap(); hprintln!("init").ok();
// Schedule `foo` to run 1 second in the future // Schedule `foo` to run 1 second in the future
foo::spawn_after(Seconds(1_u32)).unwrap(); foo::spawn_after(Seconds(1_u32)).ok();
// Schedule `bar` to run 2 seconds in the future // Schedule `bar` to run 2 seconds in the future
bar::spawn_after(Seconds(2_u32)).unwrap(); bar::spawn_after(Seconds(2_u32)).ok();
(init::LateResources {}, init::Monotonics(mono)) (init::LateResources {}, init::Monotonics(mono))
} }
#[task] #[task]
fn foo(_: foo::Context) { fn foo(_: foo::Context) {
hprintln!("foo").unwrap(); hprintln!("foo").ok();
} }
#[task] #[task]
fn bar(_: bar::Context) { fn bar(_: bar::Context) {
hprintln!("bar").unwrap(); hprintln!("bar").ok();
} }
} }

View file

@ -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

View file

@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0"
name = "cortex-m-rtic-macros" name = "cortex-m-rtic-macros"
readme = "../README.md" readme = "../README.md"
repository = "https://github.com/rtic-rs/cortex-m-rtic" repository = "https://github.com/rtic-rs/cortex-m-rtic"
version = "0.6.0-alpha.2" version = "0.6.0-alpha.4"
[lib] [lib]
proc-macro = true proc-macro = true
@ -22,4 +22,4 @@ 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.3"

View file

@ -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)*
} }
) )

View file

@ -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)*

View file

@ -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))
) )

View file

@ -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))
)); ));

View file

@ -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(

View file

@ -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 {

View file

@ -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);
} }
)); ));
} }

View file

@ -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();
}); });
} }

View file

@ -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,11 @@ 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);