diff options
author | 2020-10-15 16:42:30 +0000 | |
---|---|---|
committer | 2020-10-15 16:42:30 +0000 | |
commit | 355cb82d0693fe108ac28ec8a0d77e8aab4e6e06 (patch) | |
tree | 67c0eadf6d8a98a2691b816d46a5103d159d6bbc /macros/src/codegen/software_tasks.rs | |
parent | f9303cef1cf5b2d57d26e7667289fbdccf959ea8 (diff) | |
parent | 6808cc7cdf1512a7b10dd43f268f430a676c606e (diff) | |
download | rtic-355cb82d0693fe108ac28ec8a0d77e8aab4e6e06.tar.gz rtic-355cb82d0693fe108ac28ec8a0d77e8aab4e6e06.tar.zst rtic-355cb82d0693fe108ac28ec8a0d77e8aab4e6e06.zip |
Merge #390
390: Spawn and schedule from anywhere r=AfoHT a=korken89
This PR moves RTIC to the spawn and schedule from anywhere syntax.
Notable changes:
* We do no longer support non-`Send` types.
* Some extra code is generated as any task may spawn/schedule any task. However Rust/LLVM does a great job optimizing away non used instantiations (no real code-size difference observed).
* Worst case priority inversion has increased, but it is now predictable.
Upsides:
* With this we should be able to support async/await.
* RTIC tasks can now be callbacks (spawned and scheduled).
* RTIC tasks can be stored.
Needs the following PR to land first: https://github.com/rtic-rs/rtic-syntax/pull/34
The following now works:
```rust
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
mod app {
#[init]
fn init(mut cx: init::Context) -> init::LateResources {
// Init stuff...
// New spawn syntax
foo::spawn().unwrap();
// New schedule syntax
bar::schedule(now + 4_000_000.cycles()).unwrap();
init::LateResources {}
}
#[task]
fn foo(_: foo::Context) {}
#[task]
fn bar(_: bar::Context) {}
extern "C" {
fn SSI0();
}
}
```
Co-authored-by: Per Lindgren <per.lindgren@ltu.se>
Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
Diffstat (limited to 'macros/src/codegen/software_tasks.rs')
-rw-r--r-- | macros/src/codegen/software_tasks.rs | 89 |
1 files changed, 34 insertions, 55 deletions
diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 4ae37e4e..9918dea1 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -39,71 +39,49 @@ pub fn codegen( let cap_ty = util::capacity_typenum(cap, true); // Create free queues and inputs / instants buffers - if let Some(&ceiling) = analysis.free_queues.get(name) { - let fq = util::fq_ident(name); - - let (fq_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> Option<_>>) = { - ( - quote!(rtic::export::SCFQ<#cap_ty>), - quote!(rtic::export::Queue(unsafe { - rtic::export::iQueue::u8_sc() - })), - Box::new(|| util::link_section_uninit(true)), - ) - }; - mod_app.push(quote!( - /// Queue version of a free-list that keeps track of empty slots in - /// the following buffers - static mut #fq: #fq_ty = #fq_expr; - )); + let fq = util::fq_ident(name); + + let (fq_ty, fq_expr, mk_uninit): (_, _, Box<dyn Fn() -> Option<_>>) = { + ( + quote!(rtic::export::SCFQ<#cap_ty>), + quote!(rtic::export::Queue(unsafe { + rtic::export::iQueue::u8_sc() + })), + Box::new(|| util::link_section_uninit(true)), + ) + }; + mod_app.push(quote!( + /// Queue version of a free-list that keeps track of empty slots in + /// the following buffers + pub static mut #fq: #fq_ty = #fq_expr; + )); - // Generate a resource proxy if needed - if let Some(ceiling) = ceiling { - mod_app.push(quote!( - struct #fq<'a> { - priority: &'a rtic::export::Priority, - } - )); - - mod_app.push(util::impl_mutex( - extra, - &[], - false, - &fq, - fq_ty, - ceiling, - quote!(&mut #fq), - )); - } + let ref elems = (0..cap) + .map(|_| quote!(core::mem::MaybeUninit::uninit())) + .collect::<Vec<_>>(); - let ref elems = (0..cap) - .map(|_| quote!(core::mem::MaybeUninit::uninit())) - .collect::<Vec<_>>(); - - if app.uses_schedule() { - let m = extra.monotonic(); - let instants = util::instants_ident(name); - - let uninit = mk_uninit(); - mod_app.push(quote!( - #uninit - /// Buffer that holds the instants associated to the inputs of a task - static mut #instants: - [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = - [#(#elems,)*]; - )); - } + if let Some(m) = extra.monotonic { + let instants = util::instants_ident(name); let uninit = mk_uninit(); - let inputs = util::inputs_ident(name); mod_app.push(quote!( #uninit - /// Buffer that holds the inputs of a task - static mut #inputs: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = + /// Buffer that holds the instants associated to the inputs of a task + pub static mut #instants: + [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] = [#(#elems,)*]; )); } + let uninit = mk_uninit(); + let inputs_ident = util::inputs_ident(name); + mod_app.push(quote!( + #uninit + /// Buffer that holds the inputs of a task + pub static mut #inputs_ident: [core::mem::MaybeUninit<#input_ty>; #cap_lit] = + [#(#elems,)*]; + )); + // `${task}Resources` let mut needs_lt = false; if !task.args.resources.is_empty() { @@ -161,6 +139,7 @@ pub fn codegen( Context::SoftwareTask(name), needs_lt, app, + analysis, extra, )); } |