mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-30 15:34:33 +01:00
Removed Priority, simplified lifetime handling
This commit is contained in:
parent
53f3d397e7
commit
714020a624
15 changed files with 99 additions and 236 deletions
|
@ -15,7 +15,9 @@ mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
|
|
||||||
#[shared]
|
#[shared]
|
||||||
struct Shared {}
|
struct Shared {
|
||||||
|
a: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[local]
|
#[local]
|
||||||
struct Local {}
|
struct Local {}
|
||||||
|
@ -25,11 +27,12 @@ mod app {
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
|
|
||||||
async_task::spawn().unwrap();
|
async_task::spawn().unwrap();
|
||||||
|
async_task2::spawn().unwrap();
|
||||||
|
|
||||||
(Shared {}, Local {})
|
(Shared { a: 0 }, Local {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[idle]
|
#[idle(shared = [a])]
|
||||||
fn idle(_: idle::Context) -> ! {
|
fn idle(_: idle::Context) -> ! {
|
||||||
// debug::exit(debug::EXIT_SUCCESS);
|
// debug::exit(debug::EXIT_SUCCESS);
|
||||||
loop {
|
loop {
|
||||||
|
@ -38,10 +41,23 @@ mod app {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task(binds = UART1, shared = [a])]
|
||||||
async fn async_task(_cx: async_task::Context) {
|
fn hw_task(cx: hw_task::Context) {
|
||||||
|
let hw_task::SharedResources { a } = cx.shared;
|
||||||
|
hprintln!("hello from hw").ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(shared = [a])]
|
||||||
|
async fn async_task(cx: async_task::Context) {
|
||||||
|
let async_task::SharedResources { a } = cx.shared;
|
||||||
hprintln!("hello from async").ok();
|
hprintln!("hello from async").ok();
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task(priority = 2, shared = [a])]
|
||||||
|
async fn async_task2(cx: async_task2::Context) {
|
||||||
|
let async_task2::SharedResources { a } = cx.shared;
|
||||||
|
hprintln!("hello from async2").ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -19,6 +19,10 @@ mod shared_resources_struct;
|
||||||
mod software_tasks;
|
mod software_tasks;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
// TODO: organize codegen to actual parts of code
|
||||||
|
// so `main::codegen` generates ALL the code for `fn main`,
|
||||||
|
// `software_tasks::codegen` generates ALL the code for software tasks etc...
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn app(app: &App, analysis: &Analysis) -> TokenStream2 {
|
pub fn app(app: &App, analysis: &Analysis) -> TokenStream2 {
|
||||||
let mut mod_app = vec![];
|
let mut mod_app = vec![];
|
||||||
|
|
|
@ -13,7 +13,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
for (name, _) in app.software_tasks.iter() {
|
for (name, _) in app.software_tasks.iter() {
|
||||||
let type_name = util::internal_task_ident(name, "F");
|
let type_name = util::internal_task_ident(name, "F");
|
||||||
let exec_name = util::internal_task_ident(name, "EXEC");
|
let exec_name = util::internal_task_ident(name, "EXEC");
|
||||||
let prio_name = util::internal_task_ident(name, "PRIORITY");
|
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
@ -22,12 +21,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
static #exec_name:
|
static #exec_name:
|
||||||
rtic::RacyCell<rtic::export::executor::AsyncTaskExecutor<#type_name>> =
|
rtic::RacyCell<rtic::export::executor::AsyncTaskExecutor<#type_name>> =
|
||||||
rtic::RacyCell::new(rtic::export::executor::AsyncTaskExecutor::new());
|
rtic::RacyCell::new(rtic::export::executor::AsyncTaskExecutor::new());
|
||||||
|
|
||||||
// The executors priority, this can be any value - we will overwrite it when we
|
|
||||||
// start a task
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
static #prio_name: rtic::RacyCell<rtic::export::Priority> =
|
|
||||||
unsafe { rtic::RacyCell::new(rtic::export::Priority::new(0)) };
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +32,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
|
|
||||||
for name in channel.tasks.iter() {
|
for name in channel.tasks.iter() {
|
||||||
let exec_name = util::internal_task_ident(name, "EXEC");
|
let exec_name = util::internal_task_ident(name, "EXEC");
|
||||||
let prio_name = util::internal_task_ident(name, "PRIORITY");
|
|
||||||
// let task = &app.software_tasks[name];
|
// let task = &app.software_tasks[name];
|
||||||
// let cfgs = &task.cfgs;
|
// let cfgs = &task.cfgs;
|
||||||
let executor_run_ident = util::executor_run_ident(name);
|
let executor_run_ident = util::executor_run_ident(name);
|
||||||
|
@ -59,12 +51,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
|
||||||
if #rq.load(core::sync::atomic::Ordering::Relaxed) {
|
if #rq.load(core::sync::atomic::Ordering::Relaxed) {
|
||||||
#rq.store(false, core::sync::atomic::Ordering::Relaxed);
|
#rq.store(false, core::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
(&mut *#exec_name.get_mut()).spawn(#name(#name::Context::new()));
|
||||||
// The async executor needs a static priority
|
|
||||||
#prio_name.get_mut().write(rtic::export::Priority::new(PRIORITY));
|
|
||||||
let priority: &'static _ = &*#prio_name.get();
|
|
||||||
|
|
||||||
(&mut *#exec_name.get_mut()).spawn(#name(#name::Context::new(priority)));
|
|
||||||
#executor_run_ident.store(true, core::sync::atomic::Ordering::Relaxed);
|
#executor_run_ident.store(true, core::sync::atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,22 +41,16 @@ pub fn codegen(
|
||||||
|
|
||||||
rtic::export::run(PRIORITY, || {
|
rtic::export::run(PRIORITY, || {
|
||||||
#name(
|
#name(
|
||||||
#name::Context::new(&rtic::export::Priority::new(PRIORITY))
|
#name::Context::new()
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut shared_needs_lt = false;
|
|
||||||
let mut local_needs_lt = false;
|
|
||||||
|
|
||||||
// `${task}Locals`
|
// `${task}Locals`
|
||||||
if !task.args.local_resources.is_empty() {
|
if !task.args.local_resources.is_empty() {
|
||||||
let (item, constructor) = local_resources_struct::codegen(
|
let (item, constructor) =
|
||||||
Context::HardwareTask(name),
|
local_resources_struct::codegen(Context::HardwareTask(name), app);
|
||||||
&mut local_needs_lt,
|
|
||||||
app,
|
|
||||||
);
|
|
||||||
|
|
||||||
root.push(item);
|
root.push(item);
|
||||||
|
|
||||||
|
@ -65,24 +59,19 @@ pub fn codegen(
|
||||||
|
|
||||||
// `${task}Resources`
|
// `${task}Resources`
|
||||||
if !task.args.shared_resources.is_empty() {
|
if !task.args.shared_resources.is_empty() {
|
||||||
let (item, constructor) = shared_resources_struct::codegen(
|
let (item, constructor) =
|
||||||
Context::HardwareTask(name),
|
shared_resources_struct::codegen(Context::HardwareTask(name), app);
|
||||||
&mut shared_needs_lt,
|
|
||||||
app,
|
|
||||||
);
|
|
||||||
|
|
||||||
root.push(item);
|
root.push(item);
|
||||||
|
|
||||||
mod_app.push(constructor);
|
mod_app.push(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.push(module::codegen(
|
// Module generation...
|
||||||
Context::HardwareTask(name),
|
|
||||||
shared_needs_lt,
|
root.push(module::codegen(Context::HardwareTask(name), app, analysis));
|
||||||
local_needs_lt,
|
|
||||||
app,
|
// End module generation
|
||||||
analysis,
|
|
||||||
));
|
|
||||||
|
|
||||||
if !task.is_extern {
|
if !task.is_extern {
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
|
|
|
@ -24,37 +24,27 @@ pub fn codegen(
|
||||||
TokenStream2,
|
TokenStream2,
|
||||||
) {
|
) {
|
||||||
if let Some(idle) = &app.idle {
|
if let Some(idle) = &app.idle {
|
||||||
let mut shared_needs_lt = false;
|
|
||||||
let mut local_needs_lt = false;
|
|
||||||
let mut mod_app = vec![];
|
let mut mod_app = vec![];
|
||||||
let mut root_idle = vec![];
|
let mut root_idle = vec![];
|
||||||
|
|
||||||
let name = &idle.name;
|
let name = &idle.name;
|
||||||
|
|
||||||
if !idle.args.shared_resources.is_empty() {
|
if !idle.args.shared_resources.is_empty() {
|
||||||
let (item, constructor) =
|
let (item, constructor) = shared_resources_struct::codegen(Context::Idle, app);
|
||||||
shared_resources_struct::codegen(Context::Idle, &mut shared_needs_lt, app);
|
|
||||||
|
|
||||||
root_idle.push(item);
|
root_idle.push(item);
|
||||||
mod_app.push(constructor);
|
mod_app.push(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !idle.args.local_resources.is_empty() {
|
if !idle.args.local_resources.is_empty() {
|
||||||
let (item, constructor) =
|
let (item, constructor) = local_resources_struct::codegen(Context::Idle, app);
|
||||||
local_resources_struct::codegen(Context::Idle, &mut local_needs_lt, app);
|
|
||||||
|
|
||||||
root_idle.push(item);
|
root_idle.push(item);
|
||||||
|
|
||||||
mod_app.push(constructor);
|
mod_app.push(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
root_idle.push(module::codegen(
|
root_idle.push(module::codegen(Context::Idle, app, analysis));
|
||||||
Context::Idle,
|
|
||||||
shared_needs_lt,
|
|
||||||
local_needs_lt,
|
|
||||||
app,
|
|
||||||
analysis,
|
|
||||||
));
|
|
||||||
|
|
||||||
let attrs = &idle.attrs;
|
let attrs = &idle.attrs;
|
||||||
let context = &idle.context;
|
let context = &idle.context;
|
||||||
|
@ -71,7 +61,7 @@ pub fn codegen(
|
||||||
));
|
));
|
||||||
|
|
||||||
let call_idle = quote!(#name(
|
let call_idle = quote!(#name(
|
||||||
#name::Context::new(&rtic::export::Priority::new(0))
|
#name::Context::new()
|
||||||
));
|
));
|
||||||
|
|
||||||
(mod_app, root_idle, user_idle, call_idle)
|
(mod_app, root_idle, user_idle, call_idle)
|
||||||
|
|
|
@ -91,8 +91,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> CodegenResult {
|
||||||
|
|
||||||
// `${task}Locals`
|
// `${task}Locals`
|
||||||
if !init.args.local_resources.is_empty() {
|
if !init.args.local_resources.is_empty() {
|
||||||
let (item, constructor) =
|
let (item, constructor) = local_resources_struct::codegen(Context::Init, app);
|
||||||
local_resources_struct::codegen(Context::Init, &mut local_needs_lt, app);
|
|
||||||
|
|
||||||
root_init.push(item);
|
root_init.push(item);
|
||||||
|
|
||||||
|
@ -103,13 +102,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> CodegenResult {
|
||||||
let (shared_resources, local_resources) = #name(#name::Context::new(core.into()));
|
let (shared_resources, local_resources) = #name(#name::Context::new(core.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
root_init.push(module::codegen(
|
root_init.push(module::codegen(Context::Init, app, analysis));
|
||||||
Context::Init,
|
|
||||||
false,
|
|
||||||
local_needs_lt,
|
|
||||||
app,
|
|
||||||
analysis,
|
|
||||||
));
|
|
||||||
|
|
||||||
(mod_app, root_init, user_init, call_init)
|
(mod_app, root_init, user_init, call_init)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use quote::quote;
|
||||||
use crate::codegen::util;
|
use crate::codegen::util;
|
||||||
|
|
||||||
/// Generates local resources structs
|
/// Generates local resources structs
|
||||||
pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2, TokenStream2) {
|
pub fn codegen(ctxt: Context, app: &App) -> (TokenStream2, TokenStream2) {
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
|
|
||||||
let resources = match ctxt {
|
let resources = match ctxt {
|
||||||
|
@ -74,16 +74,14 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if lt.is_some() {
|
if lt.is_some() {
|
||||||
*needs_lt = true;
|
|
||||||
|
|
||||||
// The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
// The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
||||||
if has_cfgs {
|
if has_cfgs {
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub __marker__: core::marker::PhantomData<&'a ()>
|
pub __rtic_internal_marker: ::core::marker::PhantomData<&'a ()>
|
||||||
));
|
));
|
||||||
|
|
||||||
values.push(quote!(__marker__: core::marker::PhantomData));
|
values.push(quote!(__rtic_internal_marker: ::core::marker::PhantomData));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,7 @@ use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn codegen(
|
pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
|
||||||
ctxt: Context,
|
|
||||||
shared_resources_tick: bool,
|
|
||||||
local_resources_tick: bool,
|
|
||||||
app: &App,
|
|
||||||
analysis: &Analysis,
|
|
||||||
) -> TokenStream2 {
|
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
let mut module_items = vec![];
|
let mut module_items = vec![];
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
|
@ -20,7 +14,6 @@ pub fn codegen(
|
||||||
|
|
||||||
let name = ctxt.ident(app);
|
let name = ctxt.ident(app);
|
||||||
|
|
||||||
let mut lt = None;
|
|
||||||
match ctxt {
|
match ctxt {
|
||||||
Context::Init => {
|
Context::Init => {
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
|
@ -39,10 +32,9 @@ pub fn codegen(
|
||||||
values.push(quote!(device: #device::Peripherals::steal()));
|
values.push(quote!(device: #device::Peripherals::steal()));
|
||||||
}
|
}
|
||||||
|
|
||||||
lt = Some(quote!('a));
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
/// Critical section token for init
|
/// Critical section token for init
|
||||||
pub cs: rtic::export::CriticalSection<#lt>
|
pub cs: rtic::export::CriticalSection<'a>
|
||||||
));
|
));
|
||||||
|
|
||||||
values.push(quote!(cs: rtic::export::CriticalSection::new()));
|
values.push(quote!(cs: rtic::export::CriticalSection::new()));
|
||||||
|
@ -55,12 +47,6 @@ pub fn codegen(
|
||||||
|
|
||||||
if ctxt.has_local_resources(app) {
|
if ctxt.has_local_resources(app) {
|
||||||
let ident = util::local_resources_ident(ctxt, app);
|
let ident = util::local_resources_ident(ctxt, app);
|
||||||
let lt = if local_resources_tick {
|
|
||||||
lt = Some(quote!('a));
|
|
||||||
Some(quote!('a))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
module_items.push(quote!(
|
module_items.push(quote!(
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -69,7 +55,7 @@ pub fn codegen(
|
||||||
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
/// Local Resources this task has access to
|
/// Local Resources this task has access to
|
||||||
pub local: #name::LocalResources<#lt>
|
pub local: #name::LocalResources<'a>
|
||||||
));
|
));
|
||||||
|
|
||||||
values.push(quote!(local: #name::LocalResources::new()));
|
values.push(quote!(local: #name::LocalResources::new()));
|
||||||
|
@ -77,12 +63,6 @@ pub fn codegen(
|
||||||
|
|
||||||
if ctxt.has_shared_resources(app) {
|
if ctxt.has_shared_resources(app) {
|
||||||
let ident = util::shared_resources_ident(ctxt, app);
|
let ident = util::shared_resources_ident(ctxt, app);
|
||||||
let lt = if shared_resources_tick {
|
|
||||||
lt = Some(quote!('a));
|
|
||||||
Some(quote!('a))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
module_items.push(quote!(
|
module_items.push(quote!(
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -91,15 +71,10 @@ pub fn codegen(
|
||||||
|
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
/// Shared Resources this task has access to
|
/// Shared Resources this task has access to
|
||||||
pub shared: #name::SharedResources<#lt>
|
pub shared: #name::SharedResources<'a>
|
||||||
));
|
));
|
||||||
|
|
||||||
let priority = if ctxt.is_init() {
|
values.push(quote!(shared: #name::SharedResources::new()));
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(quote!(priority))
|
|
||||||
};
|
|
||||||
values.push(quote!(shared: #name::SharedResources::new(#priority)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = match ctxt {
|
let doc = match ctxt {
|
||||||
|
@ -122,12 +97,6 @@ pub fn codegen(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let priority = if ctxt.is_init() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(quote!(priority: &#lt rtic::export::Priority))
|
|
||||||
};
|
|
||||||
|
|
||||||
let internal_context_name = util::internal_task_ident(name, "Context");
|
let internal_context_name = util::internal_task_ident(name, "Context");
|
||||||
|
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
@ -135,15 +104,18 @@ pub fn codegen(
|
||||||
/// Execution context
|
/// Execution context
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub struct #internal_context_name<#lt> {
|
pub struct #internal_context_name<'a> {
|
||||||
|
#[doc(hidden)]
|
||||||
|
__rtic_internal_p: ::core::marker::PhantomData<&'a ()>,
|
||||||
#(#fields,)*
|
#(#fields,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
impl<#lt> #internal_context_name<#lt> {
|
impl<'a> #internal_context_name<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn new(#core #priority) -> Self {
|
pub unsafe fn new(#core) -> Self {
|
||||||
#internal_context_name {
|
#internal_context_name {
|
||||||
|
__rtic_internal_p: ::core::marker::PhantomData,
|
||||||
#(#values,)*
|
#(#values,)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,19 +57,14 @@ pub fn codegen(
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
pub struct #shared_name<'a> {
|
pub struct #shared_name<'a> {
|
||||||
priority: &'a Priority,
|
__rtic_internal_p: ::core::marker::PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
impl<'a> #shared_name<'a> {
|
impl<'a> #shared_name<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn new(priority: &'a Priority) -> Self {
|
pub unsafe fn new() -> Self {
|
||||||
#shared_name { priority }
|
#shared_name { __rtic_internal_p: ::core::marker::PhantomData }
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn priority(&self) -> &Priority {
|
|
||||||
self.priority
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
@ -104,8 +99,6 @@ pub fn codegen(
|
||||||
quote!()
|
quote!()
|
||||||
} else {
|
} else {
|
||||||
quote!(mod shared_resources {
|
quote!(mod shared_resources {
|
||||||
use rtic::export::Priority;
|
|
||||||
|
|
||||||
#(#mod_resources)*
|
#(#mod_resources)*
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ use quote::quote;
|
||||||
use crate::codegen::util;
|
use crate::codegen::util;
|
||||||
|
|
||||||
/// Generate shared resources structs
|
/// Generate shared resources structs
|
||||||
pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2, TokenStream2) {
|
pub fn codegen(ctxt: Context, app: &App) -> (TokenStream2, TokenStream2) {
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
|
|
||||||
let resources = match ctxt {
|
let resources = match ctxt {
|
||||||
|
@ -72,7 +72,7 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
|
||||||
|
|
||||||
values.push(quote!(
|
values.push(quote!(
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#name: shared_resources::#shared_name::new(priority)
|
#name: shared_resources::#shared_name::new()
|
||||||
|
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -93,8 +93,6 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
|
||||||
}
|
}
|
||||||
|
|
||||||
if lt.is_some() {
|
if lt.is_some() {
|
||||||
*needs_lt = true;
|
|
||||||
|
|
||||||
// The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
// The struct could end up empty due to `cfg`s leading to an error due to `'a` being unused
|
||||||
if has_cfgs {
|
if has_cfgs {
|
||||||
fields.push(quote!(
|
fields.push(quote!(
|
||||||
|
@ -117,15 +115,10 @@ pub fn codegen(ctxt: Context, needs_lt: &mut bool, app: &App) -> (TokenStream2,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let arg = if ctxt.is_init() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(quote!(priority: &#lt rtic::export::Priority))
|
|
||||||
};
|
|
||||||
let constructor = quote!(
|
let constructor = quote!(
|
||||||
impl<#lt> #ident<#lt> {
|
impl<#lt> #ident<#lt> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn new(#arg) -> Self {
|
pub unsafe fn new() -> Self {
|
||||||
#ident {
|
#ident {
|
||||||
#(#values,)*
|
#(#values,)*
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,16 +36,11 @@ pub fn codegen(
|
||||||
));
|
));
|
||||||
|
|
||||||
// `${task}Resources`
|
// `${task}Resources`
|
||||||
let mut shared_needs_lt = false;
|
|
||||||
let mut local_needs_lt = false;
|
|
||||||
|
|
||||||
// `${task}Locals`
|
// `${task}Locals`
|
||||||
if !task.args.local_resources.is_empty() {
|
if !task.args.local_resources.is_empty() {
|
||||||
let (item, constructor) = local_resources_struct::codegen(
|
let (item, constructor) =
|
||||||
Context::SoftwareTask(name),
|
local_resources_struct::codegen(Context::SoftwareTask(name), app);
|
||||||
&mut local_needs_lt,
|
|
||||||
app,
|
|
||||||
);
|
|
||||||
|
|
||||||
root.push(item);
|
root.push(item);
|
||||||
|
|
||||||
|
@ -53,11 +48,8 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !task.args.shared_resources.is_empty() {
|
if !task.args.shared_resources.is_empty() {
|
||||||
let (item, constructor) = shared_resources_struct::codegen(
|
let (item, constructor) =
|
||||||
Context::SoftwareTask(name),
|
shared_resources_struct::codegen(Context::SoftwareTask(name), app);
|
||||||
&mut shared_needs_lt,
|
|
||||||
app,
|
|
||||||
);
|
|
||||||
|
|
||||||
root.push(item);
|
root.push(item);
|
||||||
|
|
||||||
|
@ -69,17 +61,12 @@ pub fn codegen(
|
||||||
let attrs = &task.attrs;
|
let attrs = &task.attrs;
|
||||||
let cfgs = &task.cfgs;
|
let cfgs = &task.cfgs;
|
||||||
let stmts = &task.stmts;
|
let stmts = &task.stmts;
|
||||||
let context_lifetime = if shared_needs_lt || local_needs_lt {
|
|
||||||
quote!(<'static>)
|
|
||||||
} else {
|
|
||||||
quote!()
|
|
||||||
};
|
|
||||||
|
|
||||||
user_tasks.push(quote!(
|
user_tasks.push(quote!(
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
async fn #name(#context: #name::Context #context_lifetime) {
|
async fn #name(#context: #name::Context<'static>) {
|
||||||
use rtic::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
use rtic::mutex::prelude::*;
|
use rtic::mutex::prelude::*;
|
||||||
|
|
||||||
|
@ -88,13 +75,7 @@ pub fn codegen(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
root.push(module::codegen(
|
root.push(module::codegen(Context::SoftwareTask(name), app, analysis));
|
||||||
Context::SoftwareTask(name),
|
|
||||||
shared_needs_lt,
|
|
||||||
local_needs_lt,
|
|
||||||
app,
|
|
||||||
analysis,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(mod_app, root, user_tasks)
|
(mod_app, root, user_tasks)
|
||||||
|
|
|
@ -17,10 +17,10 @@ pub fn impl_mutex(
|
||||||
ceiling: u8,
|
ceiling: u8,
|
||||||
ptr: &TokenStream2,
|
ptr: &TokenStream2,
|
||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let (path, priority) = if resources_prefix {
|
let path = if resources_prefix {
|
||||||
(quote!(shared_resources::#name), quote!(self.priority()))
|
quote!(shared_resources::#name)
|
||||||
} else {
|
} else {
|
||||||
(quote!(#name), quote!(self.priority))
|
quote!(#name)
|
||||||
};
|
};
|
||||||
|
|
||||||
let device = &app.args.device;
|
let device = &app.args.device;
|
||||||
|
@ -38,7 +38,6 @@ pub fn impl_mutex(
|
||||||
unsafe {
|
unsafe {
|
||||||
rtic::export::lock(
|
rtic::export::lock(
|
||||||
#ptr,
|
#ptr,
|
||||||
#priority,
|
|
||||||
CEILING,
|
CEILING,
|
||||||
#device::NVIC_PRIO_BITS,
|
#device::NVIC_PRIO_BITS,
|
||||||
&#masks_name,
|
&#masks_name,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly"
|
channel = "nightly"
|
||||||
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
|
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
|
||||||
targets = [ "thumbv7em-none-eabihf" ]
|
targets = [ "thumbv6m-none-eabi", "thumbv7m-none-eabi" ]
|
||||||
|
|
|
@ -163,38 +163,6 @@ impl Barrier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newtype over `Cell` that forbids mutation through a shared reference
|
|
||||||
pub struct Priority {
|
|
||||||
inner: Cell<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Priority {
|
|
||||||
/// Create a new Priority
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Will overwrite the current Priority
|
|
||||||
#[inline(always)]
|
|
||||||
pub const unsafe fn new(value: u8) -> Self {
|
|
||||||
Priority {
|
|
||||||
inner: Cell::new(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change the current priority to `value`
|
|
||||||
// These two methods are used by `lock` (see below) but can't be used from the RTIC application
|
|
||||||
#[inline(always)]
|
|
||||||
fn set(&self, value: u8) {
|
|
||||||
self.inner.set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the current priority
|
|
||||||
#[inline(always)]
|
|
||||||
fn get(&self) -> u8 {
|
|
||||||
self.inner.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Const helper to check architecture
|
/// Const helper to check architecture
|
||||||
pub const fn have_basepri() -> bool {
|
pub const fn have_basepri() -> bool {
|
||||||
#[cfg(have_basepri)]
|
#[cfg(have_basepri)]
|
||||||
|
@ -260,31 +228,21 @@ where
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lock<T, R, const M: usize>(
|
pub unsafe fn lock<T, R, const M: usize>(
|
||||||
ptr: *mut T,
|
ptr: *mut T,
|
||||||
priority: &Priority,
|
|
||||||
ceiling: u8,
|
ceiling: u8,
|
||||||
nvic_prio_bits: u8,
|
nvic_prio_bits: u8,
|
||||||
_mask: &[Mask<M>; 3],
|
_mask: &[Mask<M>; 3],
|
||||||
f: impl FnOnce(&mut T) -> R,
|
f: impl FnOnce(&mut T) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
let current = priority.get();
|
|
||||||
|
|
||||||
if current < ceiling {
|
|
||||||
if ceiling == (1 << nvic_prio_bits) {
|
if ceiling == (1 << nvic_prio_bits) {
|
||||||
priority.set(u8::max_value());
|
|
||||||
let r = interrupt::free(|_| f(&mut *ptr));
|
let r = interrupt::free(|_| f(&mut *ptr));
|
||||||
priority.set(current);
|
|
||||||
r
|
r
|
||||||
} else {
|
} else {
|
||||||
priority.set(ceiling);
|
let current = basepri::read();
|
||||||
basepri::write(logical2hw(ceiling, nvic_prio_bits));
|
basepri::write(logical2hw(ceiling, nvic_prio_bits));
|
||||||
let r = f(&mut *ptr);
|
let r = f(&mut *ptr);
|
||||||
basepri::write(logical2hw(current, nvic_prio_bits));
|
basepri::write(logical2hw(current, nvic_prio_bits));
|
||||||
priority.set(current);
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
f(&mut *ptr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock implementation using interrupt masking
|
/// Lock implementation using interrupt masking
|
||||||
|
@ -335,26 +293,20 @@ pub unsafe fn lock<T, R, const M: usize>(
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lock<T, R, const M: usize>(
|
pub unsafe fn lock<T, R, const M: usize>(
|
||||||
ptr: *mut T,
|
ptr: *mut T,
|
||||||
priority: &Priority,
|
|
||||||
ceiling: u8,
|
ceiling: u8,
|
||||||
_nvic_prio_bits: u8,
|
_nvic_prio_bits: u8,
|
||||||
masks: &[Mask<M>; 3],
|
masks: &[Mask<M>; 3],
|
||||||
f: impl FnOnce(&mut T) -> R,
|
f: impl FnOnce(&mut T) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
let current = priority.get();
|
|
||||||
if current < ceiling {
|
|
||||||
if ceiling >= 4 {
|
if ceiling >= 4 {
|
||||||
// safe to manipulate outside critical section
|
// safe to manipulate outside critical section
|
||||||
priority.set(ceiling);
|
|
||||||
// execute closure under protection of raised system ceiling
|
// execute closure under protection of raised system ceiling
|
||||||
let r = interrupt::free(|_| f(&mut *ptr));
|
let r = interrupt::free(|_| f(&mut *ptr));
|
||||||
// safe to manipulate outside critical section
|
// safe to manipulate outside critical section
|
||||||
priority.set(current);
|
|
||||||
r
|
r
|
||||||
} else {
|
} else {
|
||||||
// safe to manipulate outside critical section
|
// safe to manipulate outside critical section
|
||||||
priority.set(ceiling);
|
let mask = compute_mask(0, ceiling, masks);
|
||||||
let mask = compute_mask(current, ceiling, masks);
|
|
||||||
clear_enable_mask(mask);
|
clear_enable_mask(mask);
|
||||||
|
|
||||||
// execute closure under protection of raised system ceiling
|
// execute closure under protection of raised system ceiling
|
||||||
|
@ -363,13 +315,8 @@ pub unsafe fn lock<T, R, const M: usize>(
|
||||||
set_enable_mask(mask);
|
set_enable_mask(mask);
|
||||||
|
|
||||||
// safe to manipulate outside critical section
|
// safe to manipulate outside critical section
|
||||||
priority.set(current);
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// execute closure without raising system ceiling
|
|
||||||
f(&mut *ptr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(have_basepri))]
|
#[cfg(not(have_basepri))]
|
||||||
|
|
Loading…
Reference in a new issue