mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-23 20:22:51 +01:00
WIP generators tasks
This commit is contained in:
parent
f9b30a1ff8
commit
a3783a6d3d
12 changed files with 348 additions and 13 deletions
61
examples/generator.rs
Normal file
61
examples/generator.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//! examples/hardware.rs
|
||||||
|
|
||||||
|
#![feature(generator_trait)]
|
||||||
|
#![feature(generators)]
|
||||||
|
#![feature(never_type)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![deny(unsafe_code)]
|
||||||
|
#![deny(warnings)]
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
|
use lm3s6965::Interrupt;
|
||||||
|
use panic_semihosting as _;
|
||||||
|
|
||||||
|
#[rtfm::app(device = lm3s6965)]
|
||||||
|
const APP: () = {
|
||||||
|
struct Resources {
|
||||||
|
#[init(0)]
|
||||||
|
x: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[init]
|
||||||
|
fn init(_: init::Context) {
|
||||||
|
hprintln!("init").ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[idle]
|
||||||
|
fn idle(_: idle::Context) -> ! {
|
||||||
|
hprintln!("idle").ok();
|
||||||
|
|
||||||
|
rtfm::pend(Interrupt::UART0);
|
||||||
|
hprintln!("C").ok();
|
||||||
|
rtfm::pend(Interrupt::UART0);
|
||||||
|
hprintln!("E").ok();
|
||||||
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(binds = UART0, priority = 1, resources = [x])]
|
||||||
|
fn uart0(mut cx: uart0::Context) -> impl Generator<Yield = (), Return = !> {
|
||||||
|
hprintln!("A").ok();
|
||||||
|
|
||||||
|
move || loop {
|
||||||
|
hprintln!("B").ok();
|
||||||
|
yield;
|
||||||
|
|
||||||
|
cx.resources.x.lock(|x| {
|
||||||
|
hprintln!("lock").ok();
|
||||||
|
*x += 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
hprintln!("D").ok();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task(binds = UART1, priority = 2, resources = [x])]
|
||||||
|
fn uart1(_: uart1::Context) {}
|
||||||
|
};
|
|
@ -21,7 +21,8 @@ proc-macro = true
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
rtfm-syntax = "0.4.0-beta.2"
|
# rtfm-syntax = "0.4.0-beta.2"
|
||||||
|
rtfm-syntax = { git = "https://github.com/rtfm-rs/rtfm-syntax", branch = "impl-generator" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
heterogeneous = []
|
heterogeneous = []
|
||||||
|
|
|
@ -39,7 +39,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let (const_app_init, root_init, user_init, call_init) =
|
let (const_app_init, root_init, user_init, call_init) =
|
||||||
init::codegen(core, app, analysis, extra);
|
init::codegen(core, app, analysis, extra);
|
||||||
|
|
||||||
let (const_app_post_init, post_init_stmts) = post_init::codegen(core, analysis, extra);
|
let (const_app_post_init, root_post_init, post_init_stmts) =
|
||||||
|
post_init::codegen(core, &app, analysis, extra);
|
||||||
|
|
||||||
let (const_app_idle, root_idle, user_idle, call_idle) =
|
let (const_app_idle, root_idle, user_idle, call_idle) =
|
||||||
idle::codegen(core, app, analysis, extra);
|
idle::codegen(core, app, analysis, extra);
|
||||||
|
@ -53,6 +54,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
root.push(quote!(
|
root.push(quote!(
|
||||||
#(#root_init)*
|
#(#root_init)*
|
||||||
|
|
||||||
|
#(#root_post_init)*
|
||||||
|
|
||||||
#(#root_idle)*
|
#(#root_idle)*
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -87,7 +90,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (const_app_resources, mod_resources) = resources::codegen(app, analysis, extra);
|
let (const_app_resources, mod_resources, mod_gresources) =
|
||||||
|
resources::codegen(app, analysis, extra);
|
||||||
|
|
||||||
let (const_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
|
let (const_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) =
|
||||||
hardware_tasks::codegen(app, analysis, extra);
|
hardware_tasks::codegen(app, analysis, extra);
|
||||||
|
@ -128,6 +132,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
|
|
||||||
#mod_resources
|
#mod_resources
|
||||||
|
|
||||||
|
#mod_gresources
|
||||||
|
|
||||||
#(#root_hardware_tasks)*
|
#(#root_hardware_tasks)*
|
||||||
|
|
||||||
#(#root_software_tasks)*
|
#(#root_software_tasks)*
|
||||||
|
|
|
@ -29,6 +29,46 @@ pub fn codegen(
|
||||||
let mut user_tasks = vec![];
|
let mut user_tasks = vec![];
|
||||||
|
|
||||||
for (name, task) in &app.hardware_tasks {
|
for (name, task) in &app.hardware_tasks {
|
||||||
|
// TODO split this big conditional to reuse code below
|
||||||
|
if task.is_generator {
|
||||||
|
let symbol = task.args.binds.clone();
|
||||||
|
let gen_i = util::generator_ident(&name.to_string());
|
||||||
|
const_app.push(quote!(
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe fn #symbol() {
|
||||||
|
use core::ops::Generator;
|
||||||
|
|
||||||
|
core::pin::Pin::new_unchecked(&mut *#gen_i.as_mut_ptr()).resume();
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
let priority = task.args.priority;
|
||||||
|
// `${task}Resources`
|
||||||
|
if !task.args.resources.is_empty() {
|
||||||
|
let (item, constructor) = resources_struct::codegen(
|
||||||
|
Context::HardwareTask(name),
|
||||||
|
priority,
|
||||||
|
&mut false,
|
||||||
|
app,
|
||||||
|
analysis,
|
||||||
|
);
|
||||||
|
|
||||||
|
root.push(item);
|
||||||
|
|
||||||
|
const_app.push(constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.push(module::codegen(
|
||||||
|
Context::HardwareTask(name),
|
||||||
|
false,
|
||||||
|
app,
|
||||||
|
extra,
|
||||||
|
));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let core = task.args.core;
|
let core = task.args.core;
|
||||||
let cfg_core = util::cfg_core(core, app.args.cores);
|
let cfg_core = util::cfg_core(core, app.args.cores);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn codegen(
|
||||||
) {
|
) {
|
||||||
assert!(!locals.is_empty());
|
assert!(!locals.is_empty());
|
||||||
|
|
||||||
let runs_once = ctxt.runs_once();
|
let runs_once = ctxt.runs_once(app);
|
||||||
let ident = util::locals_ident(ctxt, app);
|
let ident = util::locals_ident(ctxt, app);
|
||||||
|
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
|
||||||
pub resources: Resources<#lt>
|
pub resources: Resources<#lt>
|
||||||
));
|
));
|
||||||
|
|
||||||
let priority = if ctxt.is_init() {
|
let priority = if ctxt.is_init() || ctxt.is_generator(app) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(quote!(priority))
|
Some(quote!(priority))
|
||||||
|
@ -281,7 +281,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let priority = if ctxt.is_init() {
|
let priority = if ctxt.is_init() || ctxt.is_generator(app) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(quote!(priority: &#lt rtfm::export::Priority))
|
Some(quote!(priority: &#lt rtfm::export::Priority))
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
use rtfm_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
use crate::{
|
||||||
|
analyze::Analysis,
|
||||||
|
check::Extra,
|
||||||
|
codegen::{locals, util},
|
||||||
|
};
|
||||||
|
|
||||||
/// Generates code that runs after `#[init]` returns
|
/// Generates code that runs after `#[init]` returns
|
||||||
pub fn codegen(
|
pub fn codegen(
|
||||||
core: u8,
|
core: u8,
|
||||||
|
app: &App,
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
extra: &Extra,
|
extra: &Extra,
|
||||||
) -> (Vec<TokenStream2>, Vec<TokenStream2>) {
|
) -> (
|
||||||
|
// const_app
|
||||||
|
Vec<TokenStream2>,
|
||||||
|
// root
|
||||||
|
Vec<TokenStream2>,
|
||||||
|
// stmts
|
||||||
|
Vec<TokenStream2>,
|
||||||
|
) {
|
||||||
let mut const_app = vec![];
|
let mut const_app = vec![];
|
||||||
|
let mut root = vec![];
|
||||||
let mut stmts = vec![];
|
let mut stmts = vec![];
|
||||||
|
|
||||||
// initialize late resources
|
// initialize late resources
|
||||||
|
@ -22,6 +36,48 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO WIP
|
||||||
|
for (name, task) in &app.hardware_tasks {
|
||||||
|
if task.is_generator {
|
||||||
|
let name_s = name.to_string();
|
||||||
|
let gen_i = util::generator_ident(&name_s);
|
||||||
|
let gen_t = util::generator_type(&name_s);
|
||||||
|
const_app.push(quote!(
|
||||||
|
static mut #gen_i: core::mem::MaybeUninit<#gen_t> =
|
||||||
|
core::mem::MaybeUninit::uninit();
|
||||||
|
));
|
||||||
|
|
||||||
|
let (locals_pat, locals_new) = if task.locals.is_empty() {
|
||||||
|
(None, quote!())
|
||||||
|
} else {
|
||||||
|
let (struct_, pat) =
|
||||||
|
locals::codegen(Context::HardwareTask(name), &task.locals, core, app);
|
||||||
|
|
||||||
|
root.push(struct_);
|
||||||
|
|
||||||
|
(Some(pat), quote!(#name::Locals::new(),))
|
||||||
|
};
|
||||||
|
|
||||||
|
let context = &task.context;
|
||||||
|
let task_stmts = &task.stmts;
|
||||||
|
let locals_pat = locals_pat.iter();
|
||||||
|
root.push(quote!(
|
||||||
|
type #gen_t = impl core::ops::Generator<Yield = (), Return = !>;
|
||||||
|
|
||||||
|
// #[allow(non_snake_case)]
|
||||||
|
fn #name(#(#locals_pat,)* #context: #name::Context) -> #gen_t {
|
||||||
|
use rtfm::Mutex as _;
|
||||||
|
|
||||||
|
#(#task_stmts)*
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
stmts.push(quote!(
|
||||||
|
#gen_i.as_mut_ptr().write(#name(#locals_new #name::Context::new()));
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if analysis.timer_queues.is_empty() {
|
if analysis.timer_queues.is_empty() {
|
||||||
// cross-initialization barriers -- notify *other* cores that their resources have been
|
// cross-initialization barriers -- notify *other* cores that their resources have been
|
||||||
// initialized
|
// initialized
|
||||||
|
@ -151,5 +207,5 @@ pub fn codegen(
|
||||||
// enable the interrupts -- this completes the `init`-ialization phase
|
// enable the interrupts -- this completes the `init`-ialization phase
|
||||||
stmts.push(quote!(rtfm::export::interrupt::enable();));
|
stmts.push(quote!(rtfm::export::interrupt::enable();));
|
||||||
|
|
||||||
(const_app, stmts)
|
(const_app, root, stmts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,12 @@ pub fn codegen(
|
||||||
Vec<TokenStream2>,
|
Vec<TokenStream2>,
|
||||||
// mod_resources -- the `resources` module
|
// mod_resources -- the `resources` module
|
||||||
TokenStream2,
|
TokenStream2,
|
||||||
|
// mod_gresources -- the `gresources` module
|
||||||
|
TokenStream2,
|
||||||
) {
|
) {
|
||||||
let mut const_app = vec![];
|
let mut const_app = vec![];
|
||||||
let mut mod_resources = vec![];
|
let mut mod_resources = vec![];
|
||||||
|
let mut mod_gresources = vec![];
|
||||||
|
|
||||||
for (name, res, expr, loc) in app.resources(analysis) {
|
for (name, res, expr, loc) in app.resources(analysis) {
|
||||||
let cfgs = &res.cfgs;
|
let cfgs = &res.cfgs;
|
||||||
|
@ -77,6 +80,8 @@ pub fn codegen(
|
||||||
if let Some(Ownership::Contended { ceiling }) = analysis.ownerships.get(name) {
|
if let Some(Ownership::Contended { ceiling }) = analysis.ownerships.get(name) {
|
||||||
let cfg_core = util::cfg_core(loc.core().expect("UNREACHABLE"), app.args.cores);
|
let cfg_core = util::cfg_core(loc.core().expect("UNREACHABLE"), app.args.cores);
|
||||||
|
|
||||||
|
// TODO generate less code -- we don't always need both `gresources::foo` and
|
||||||
|
// `resources::foo`
|
||||||
mod_resources.push(quote!(
|
mod_resources.push(quote!(
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
|
@ -114,8 +119,37 @@ pub fn codegen(
|
||||||
name,
|
name,
|
||||||
quote!(#ty),
|
quote!(#ty),
|
||||||
*ceiling,
|
*ceiling,
|
||||||
|
ptr.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
mod_gresources.push(quote!(
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#(#cfgs)*
|
||||||
|
#cfg_core
|
||||||
|
pub struct #name {
|
||||||
|
_not_send_or_sync: core::marker::PhantomData<*mut ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#(#cfgs)*
|
||||||
|
#cfg_core
|
||||||
|
impl #name {
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn new() -> Self {
|
||||||
|
#name { _not_send_or_sync: core::marker::PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
const_app.push(util::impl_gmutex(
|
||||||
|
extra,
|
||||||
|
cfgs,
|
||||||
|
cfg_core.as_ref(),
|
||||||
|
name,
|
||||||
|
quote!(#ty),
|
||||||
|
*ceiling,
|
||||||
ptr,
|
ptr,
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,5 +163,13 @@ pub fn codegen(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
(const_app, mod_resources)
|
let mod_gresources = if mod_gresources.is_empty() {
|
||||||
|
quote!()
|
||||||
|
} else {
|
||||||
|
quote!(mod gresources {
|
||||||
|
#(#mod_gresources)*
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
(const_app, mod_resources, mod_gresources)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use rtfm_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{analyze::Analysis, codegen::util};
|
use crate::{analyze::Analysis, codegen::util};
|
||||||
|
|
||||||
|
// TODO need to do something different when generators are involved
|
||||||
pub fn codegen(
|
pub fn codegen(
|
||||||
ctxt: Context,
|
ctxt: Context,
|
||||||
priority: u8,
|
priority: u8,
|
||||||
|
@ -63,6 +64,67 @@ pub fn codegen(
|
||||||
#name: &mut #name
|
#name: &mut #name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
} else if ctxt.is_generator(app) {
|
||||||
|
let ownership = &analysis.ownerships[name];
|
||||||
|
|
||||||
|
if ownership.needs_lock(priority) {
|
||||||
|
if mut_.is_none() {
|
||||||
|
// mod gresourcesd
|
||||||
|
unimplemented!()
|
||||||
|
} else {
|
||||||
|
// resource proxy
|
||||||
|
fields.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: gresources::#name
|
||||||
|
));
|
||||||
|
|
||||||
|
values.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: gresources::#name::new()
|
||||||
|
|
||||||
|
));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let lt = if ctxt.runs_once(app) {
|
||||||
|
quote!('static)
|
||||||
|
} else {
|
||||||
|
lt = Some(quote!('a));
|
||||||
|
quote!('a)
|
||||||
|
};
|
||||||
|
|
||||||
|
if ownership.is_owned() || mut_.is_none() {
|
||||||
|
fields.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &#lt #mut_ #ty
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
fields.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
pub #name: &#lt mut #ty
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_late = expr.is_none();
|
||||||
|
if is_late {
|
||||||
|
let expr = if mut_.is_some() {
|
||||||
|
quote!(&mut *#name.as_mut_ptr())
|
||||||
|
} else {
|
||||||
|
quote!(&*#name.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
values.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: #expr
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
values.push(quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#name: &#mut_ #name
|
||||||
|
));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let ownership = &analysis.ownerships[name];
|
let ownership = &analysis.ownerships[name];
|
||||||
|
|
||||||
|
@ -92,7 +154,7 @@ pub fn codegen(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let lt = if ctxt.runs_once() {
|
let lt = if ctxt.runs_once(app) {
|
||||||
quote!('static)
|
quote!('static)
|
||||||
} else {
|
} else {
|
||||||
lt = Some(quote!('a));
|
lt = Some(quote!('a));
|
||||||
|
@ -161,7 +223,7 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let arg = if ctxt.is_init() {
|
let arg = if ctxt.is_init() || ctxt.is_generator(app) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(quote!(priority: &#lt rtfm::export::Priority))
|
Some(quote!(priority: &#lt rtfm::export::Priority))
|
||||||
|
|
|
@ -91,6 +91,43 @@ pub fn impl_mutex(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates a `Mutex` implementation for a resource seen from a generator task
|
||||||
|
pub fn impl_gmutex(
|
||||||
|
extra: &Extra,
|
||||||
|
cfgs: &[Attribute],
|
||||||
|
cfg_core: Option<&TokenStream2>,
|
||||||
|
name: &Ident,
|
||||||
|
ty: TokenStream2,
|
||||||
|
ceiling: u8,
|
||||||
|
ptr: TokenStream2,
|
||||||
|
) -> TokenStream2 {
|
||||||
|
let path = quote!(gresources::#name);
|
||||||
|
|
||||||
|
let device = extra.device;
|
||||||
|
quote!(
|
||||||
|
#(#cfgs)*
|
||||||
|
#cfg_core
|
||||||
|
impl rtfm::Mutex for #path {
|
||||||
|
type T = #ty;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn lock<R>(&mut self, f: impl FnOnce(&mut #ty) -> R) -> R {
|
||||||
|
/// Priority ceiling
|
||||||
|
const CEILING: u8 = #ceiling;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rtfm::export::glock(
|
||||||
|
#ptr,
|
||||||
|
CEILING,
|
||||||
|
#device::NVIC_PRIO_BITS,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates an identifier for a cross-initialization barrier
|
/// Generates an identifier for a cross-initialization barrier
|
||||||
pub fn init_barrier(initializer: Core) -> Ident {
|
pub fn init_barrier(initializer: Core) -> Ident {
|
||||||
Ident::new(&format!("IB{}", initializer), Span::call_site())
|
Ident::new(&format!("IB{}", initializer), Span::call_site())
|
||||||
|
@ -323,3 +360,11 @@ pub fn suffixed(name: &str, core: u8) -> Ident {
|
||||||
pub fn tq_ident(core: Core) -> Ident {
|
pub fn tq_ident(core: Core) -> Ident {
|
||||||
Ident::new(&format!("TQ{}", core), Span::call_site())
|
Ident::new(&format!("TQ{}", core), Span::call_site())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generator_ident(task: &str) -> Ident {
|
||||||
|
Ident::new(&format!("{}S", task), Span::call_site())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generator_type(task: &str) -> Ident {
|
||||||
|
Ident::new(&format!("{}T", task), Span::call_site())
|
||||||
|
}
|
||||||
|
|
|
@ -209,6 +209,7 @@ pub fn app(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
settings.parse_cores = cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous");
|
settings.parse_cores = cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous");
|
||||||
settings.parse_extern_interrupt = true;
|
settings.parse_extern_interrupt = true;
|
||||||
settings.parse_schedule = true;
|
settings.parse_schedule = true;
|
||||||
|
settings.parse_impl_generator = true;
|
||||||
|
|
||||||
let (app, analysis) = match rtfm_syntax::parse(args, input, settings) {
|
let (app, analysis) = match rtfm_syntax::parse(args, input, settings) {
|
||||||
Err(e) => return e.to_compile_error().into(),
|
Err(e) => return e.to_compile_error().into(),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use core::{
|
||||||
|
|
||||||
pub use crate::tq::{NotReady, TimerQueue};
|
pub use crate::tq::{NotReady, TimerQueue};
|
||||||
#[cfg(armv7m)]
|
#[cfg(armv7m)]
|
||||||
pub use cortex_m::register::basepri;
|
pub use cortex_m::register::{basepri, basepri_max};
|
||||||
pub use cortex_m::{
|
pub use cortex_m::{
|
||||||
asm::wfi,
|
asm::wfi,
|
||||||
interrupt,
|
interrupt,
|
||||||
|
@ -145,6 +145,25 @@ pub unsafe fn lock<T, R>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(armv7m)]
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn glock<T, R>(
|
||||||
|
ptr: *mut T,
|
||||||
|
ceiling: u8,
|
||||||
|
nvic_prio_bits: u8,
|
||||||
|
f: impl FnOnce(&mut T) -> R,
|
||||||
|
) -> R {
|
||||||
|
if ceiling == (1 << nvic_prio_bits) {
|
||||||
|
interrupt::free(|_| f(&mut *ptr))
|
||||||
|
} else {
|
||||||
|
let current = basepri::read();
|
||||||
|
basepri_max::write(logical2hw(ceiling, nvic_prio_bits));
|
||||||
|
let r = f(&mut *ptr);
|
||||||
|
basepri::write(logical2hw(current, nvic_prio_bits));
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(armv7m))]
|
#[cfg(not(armv7m))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lock<T, R>(
|
pub unsafe fn lock<T, R>(
|
||||||
|
@ -166,6 +185,8 @@ pub unsafe fn lock<T, R>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO glock for ARMv6-M
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
|
pub fn logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 {
|
||||||
((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
|
((1 << nvic_prio_bits) - logical) << (8 - nvic_prio_bits)
|
||||||
|
|
Loading…
Reference in a new issue