aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/codegen')
-rw-r--r--macros/src/codegen/assertions.rs26
-rw-r--r--macros/src/codegen/dispatchers.rs290
-rw-r--r--macros/src/codegen/hardware_tasks.rs50
-rw-r--r--macros/src/codegen/idle.rs45
-rw-r--r--macros/src/codegen/init.rs102
-rw-r--r--macros/src/codegen/locals.rs9
-rw-r--r--macros/src/codegen/module.rs48
-rw-r--r--macros/src/codegen/post_init.rs149
-rw-r--r--macros/src/codegen/pre_init.rs109
-rw-r--r--macros/src/codegen/resources.rs67
-rw-r--r--macros/src/codegen/resources_struct.rs19
-rw-r--r--macros/src/codegen/schedule.rs23
-rw-r--r--macros/src/codegen/schedule_body.rs14
-rw-r--r--macros/src/codegen/software_tasks.rs181
-rw-r--r--macros/src/codegen/spawn.rs28
-rw-r--r--macros/src/codegen/spawn_body.rs24
-rw-r--r--macros/src/codegen/timer_queue.rs40
-rw-r--r--macros/src/codegen/util.rs148
18 files changed, 490 insertions, 882 deletions
diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs
index 51bbdbff..4d9aae47 100644
--- a/macros/src/codegen/assertions.rs
+++ b/macros/src/codegen/assertions.rs
@@ -1,32 +1,18 @@
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
-use crate::{analyze::Analysis, check::Extra};
+use crate::analyze::Analysis;
/// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits
-pub fn codegen(core: u8, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
+pub fn codegen(analysis: &Analysis) -> Vec<TokenStream2> {
let mut stmts = vec![];
- // we don't generate *all* assertions on all cores because the user could conditionally import a
- // type only on some core (e.g. `#[cfg(core = "0")] use some::Type;`)
-
- if let Some(types) = analysis.send_types.get(&core) {
- for ty in types {
- stmts.push(quote!(rtic::export::assert_send::<#ty>();));
- }
- }
-
- if let Some(types) = analysis.sync_types.get(&core) {
- for ty in types {
- stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
- }
+ for ty in &analysis.send_types {
+ stmts.push(quote!(rtic::export::assert_send::<#ty>();));
}
- // if the `schedule` API is used in more than one core then we need to check that the
- // `monotonic` timer can be used in multi-core context
- if analysis.timer_queues.len() > 1 && analysis.timer_queues.contains_key(&core) {
- let monotonic = extra.monotonic();
- stmts.push(quote!(rtic::export::assert_multicore::<#monotonic>();));
+ for ty in &analysis.sync_types {
+ stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
}
stmts
diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs
index 60b8626e..300aa996 100644
--- a/macros/src/codegen/dispatchers.rs
+++ b/macros/src/codegen/dispatchers.rs
@@ -8,181 +8,147 @@ use crate::{analyze::Analysis, check::Extra, codegen::util};
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
- for (&receiver, dispatchers) in &analysis.channels {
- let interrupts = &analysis.interrupts[&receiver];
+ let interrupts = &analysis.interrupts;
+
+ for (&level, channel) in &analysis.channels {
+ let mut stmts = vec![];
+
+ let variants = channel
+ .tasks
+ .iter()
+ .map(|name| {
+ let cfgs = &app.software_tasks[name].cfgs;
+
+ quote!(
+ #(#cfgs)*
+ #name
+ )
+ })
+ .collect::<Vec<_>>();
+
+ let doc = format!(
+ "Software tasks to be dispatched at priority level {}",
+ level,
+ );
+ let t = util::spawn_t_ident(level);
+ items.push(quote!(
+ #[allow(non_camel_case_types)]
+ #[derive(Clone, Copy)]
+ #[doc = #doc]
+ enum #t {
+ #(#variants,)*
+ }
+ ));
+
+ let n = util::capacity_typenum(channel.capacity, true);
+ let rq = util::rq_ident(level);
+ let (rq_ty, rq_expr) = {
+ (
+ quote!(rtic::export::SCRQ<#t, #n>),
+ quote!(rtic::export::Queue(unsafe {
+ rtic::export::iQueue::u8_sc()
+ })),
+ )
+ };
+
+ let doc = format!(
+ "Queue of tasks ready to be dispatched at priority level {}",
+ level
+ );
+ items.push(quote!(
+ #[doc = #doc]
+ static mut #rq: #rq_ty = #rq_expr;
+ ));
+
+ if let Some(ceiling) = channel.ceiling {
+ items.push(quote!(
+ struct #rq<'a> {
+ priority: &'a rtic::export::Priority,
+ }
+ ));
- for (&level, channels) in dispatchers {
- let mut stmts = vec![];
+ items.push(util::impl_mutex(
+ extra,
+ &[],
+ false,
+ &rq,
+ rq_ty,
+ ceiling,
+ quote!(&mut #rq),
+ ));
+ }
- for (&sender, channel) in channels {
- let cfg_sender = util::cfg_core(sender, app.args.cores);
+ let arms = channel
+ .tasks
+ .iter()
+ .map(|name| {
+ let task = &app.software_tasks[name];
+ let cfgs = &task.cfgs;
+ let fq = util::fq_ident(name);
+ let inputs = util::inputs_ident(name);
+ let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
- let variants = channel
- .tasks
- .iter()
- .map(|name| {
- let cfgs = &app.software_tasks[name].cfgs;
+ let (let_instant, instant) = if app.uses_schedule() {
+ let instants = util::instants_ident(name);
- quote!(
- #(#cfgs)*
- #name
- )
- })
- .collect::<Vec<_>>();
-
- let doc = format!(
- "Software tasks spawned from core #{} to be dispatched at priority level {} by core #{}",
- sender, level, receiver,
- );
- let t = util::spawn_t_ident(receiver, level, sender);
- items.push(quote!(
- #[allow(non_camel_case_types)]
- #[derive(Clone, Copy)]
- #[doc = #doc]
- enum #t {
- #(#variants,)*
- }
- ));
-
- let n = util::capacity_typenum(channel.capacity, true);
- let rq = util::rq_ident(receiver, level, sender);
- let (rq_attr, rq_ty, rq_expr, section) = if sender == receiver {
(
- cfg_sender.clone(),
- quote!(rtic::export::SCRQ<#t, #n>),
- quote!(rtic::export::Queue(unsafe {
- rtic::export::iQueue::u8_sc()
- })),
- util::link_section("bss", sender),
+ quote!(
+ let instant =
+ #instants.get_unchecked(usize::from(index)).as_ptr().read();
+ ),
+ quote!(, instant),
)
} else {
- let shared = if cfg!(feature = "heterogeneous") {
- Some(quote!(#[rtic::export::shared]))
- } else {
- None
- };
-
- (
- shared,
- quote!(rtic::export::MCRQ<#t, #n>),
- quote!(rtic::export::Queue(rtic::export::iQueue::u8())),
- None,
- )
+ (quote!(), quote!())
};
- let doc = format!(
- "Queue of tasks sent by core #{} ready to be dispatched by core #{} at priority level {}",
- sender,
- receiver,
- level
- );
- items.push(quote!(
- #[doc = #doc]
- #rq_attr
- #section
- static mut #rq: #rq_ty = #rq_expr;
- ));
-
- if let Some(ceiling) = channel.ceiling {
- items.push(quote!(
- #cfg_sender
- struct #rq<'a> {
- priority: &'a rtic::export::Priority,
- }
- ));
-
- items.push(util::impl_mutex(
- extra,
- &[],
- cfg_sender.as_ref(),
- false,
- &rq,
- rq_ty,
- ceiling,
- quote!(&mut #rq),
- ));
- }
-
- let arms = channel
- .tasks
- .iter()
- .map(|name| {
- let task = &app.software_tasks[name];
- let cfgs = &task.cfgs;
- let fq = util::fq_ident(name, sender);
- let inputs = util::inputs_ident(name, sender);
- let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs);
-
- let (let_instant, instant) = if app.uses_schedule(receiver) {
- let instants = util::instants_ident(name, sender);
-
- (
- quote!(
- let instant =
- #instants.get_unchecked(usize::from(index)).as_ptr().read();
- ),
- quote!(, instant),
- )
- } else {
- (quote!(), quote!())
- };
-
- let locals_new = if task.locals.is_empty() {
- quote!()
- } else {
- quote!(#name::Locals::new(),)
- };
+ let locals_new = if task.locals.is_empty() {
+ quote!()
+ } else {
+ quote!(#name::Locals::new(),)
+ };
- quote!(
- #(#cfgs)*
- #t::#name => {
- let #tupled =
- #inputs.get_unchecked(usize::from(index)).as_ptr().read();
- #let_instant
- #fq.split().0.enqueue_unchecked(index);
- let priority = &rtic::export::Priority::new(PRIORITY);
- crate::#name(
- #locals_new
- #name::Context::new(priority #instant)
- #(,#pats)*
- )
- }
+ quote!(
+ #(#cfgs)*
+ #t::#name => {
+ let #tupled =
+ #inputs.get_unchecked(usize::from(index)).as_ptr().read();
+ #let_instant
+ #fq.split().0.enqueue_unchecked(index);
+ let priority = &rtic::export::Priority::new(PRIORITY);
+ crate::#name(
+ #locals_new
+ #name::Context::new(priority #instant)
+ #(,#pats)*
)
- })
- .collect::<Vec<_>>();
-
- stmts.push(quote!(
- while let Some((task, index)) = #rq.split().1.dequeue() {
- match task {
- #(#arms)*
- }
}
- ));
- }
-
- let doc = format!(
- "Interrupt handler used by core #{} to dispatch tasks at priority {}",
- receiver, level
- );
- let cfg_receiver = util::cfg_core(receiver, app.args.cores);
- let section = util::link_section("text", receiver);
- let interrupt = util::suffixed(&interrupts[&level].to_string(), receiver);
- items.push(quote!(
- #[allow(non_snake_case)]
- #[doc = #doc]
- #[no_mangle]
- #cfg_receiver
- #section
- unsafe fn #interrupt() {
- /// The priority of this interrupt handler
- const PRIORITY: u8 = #level;
-
- rtic::export::run(PRIORITY, || {
- #(#stmts)*
- });
+ )
+ })
+ .collect::<Vec<_>>();
+
+ stmts.push(quote!(
+ while let Some((task, index)) = #rq.split().1.dequeue() {
+ match task {
+ #(#arms)*
}
- ));
- }
+ }
+ ));
+
+ let doc = format!("Interrupt handler to dispatch tasks at priority {}", level);
+ let interrupt = util::suffixed(&interrupts[&level].to_string());
+ items.push(quote!(
+ #[allow(non_snake_case)]
+ #[doc = #doc]
+ #[no_mangle]
+ unsafe fn #interrupt() {
+ /// The priority of this interrupt handler
+ const PRIORITY: u8 = #level;
+
+ rtic::export::run(PRIORITY, || {
+ #(#stmts)*
+ });
+ }
+ ));
}
items
diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs
index 453dbccb..25f1df41 100644
--- a/macros/src/codegen/hardware_tasks.rs
+++ b/macros/src/codegen/hardware_tasks.rs
@@ -1,11 +1,11 @@
use proc_macro2::TokenStream as TokenStream2;
-use quote::quote;
+use quote::{format_ident, quote};
use rtic_syntax::{ast::App, Context};
use crate::{
analyze::Analysis,
check::Extra,
- codegen::{locals, module, resources_struct, util},
+ codegen::{locals, module, resources_struct},
};
/// Generate support code for hardware tasks (`#[exception]`s and `#[interrupt]`s)
@@ -14,7 +14,7 @@ pub fn codegen(
analysis: &Analysis,
extra: &Extra,
) -> (
- // const_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
+ // mod_app_hardware_tasks -- interrupt handlers and `${task}Resources` constructors
Vec<TokenStream2>,
// root_hardware_tasks -- items that must be placed in the root of the crate:
// - `${task}Locals` structs
@@ -23,16 +23,16 @@ pub fn codegen(
Vec<TokenStream2>,
// user_hardware_tasks -- the `#[task]` functions written by the user
Vec<TokenStream2>,
+ // user_hardware_tasks_imports -- the imports for `#[task]` functions written by the user
+ Vec<TokenStream2>,
) {
- let mut const_app = vec![];
+ let mut mod_app = vec![];
let mut root = vec![];
let mut user_tasks = vec![];
+ let mut hardware_tasks_imports = vec![];
for (name, task) in &app.hardware_tasks {
- let core = task.args.core;
- let cfg_core = util::cfg_core(core, app.args.cores);
-
- let (let_instant, instant) = if app.uses_schedule(core) {
+ let (let_instant, instant) = if app.uses_schedule() {
let m = extra.monotonic();
(
@@ -49,19 +49,12 @@ pub fn codegen(
quote!(#name::Locals::new(),)
};
- let symbol = if cfg!(feature = "homogeneous") {
- util::suffixed(&task.args.binds.to_string(), core)
- } else {
- task.args.binds.clone()
- };
+ let symbol = task.args.binds.clone();
let priority = task.args.priority;
- let section = util::link_section("text", core);
- const_app.push(quote!(
+ mod_app.push(quote!(
#[allow(non_snake_case)]
#[no_mangle]
- #section
- #cfg_core
unsafe fn #symbol() {
const PRIORITY: u8 = #priority;
@@ -88,9 +81,16 @@ pub fn codegen(
analysis,
);
+ // Add resources to imports
+ let name_res = format_ident!("{}Resources", name);
+ hardware_tasks_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_res;
+ ));
+
root.push(item);
- const_app.push(constructor);
+ mod_app.push(constructor);
}
root.push(module::codegen(
@@ -103,8 +103,7 @@ pub fn codegen(
// `${task}Locals`
let mut locals_pat = None;
if !task.locals.is_empty() {
- let (struct_, pat) =
- locals::codegen(Context::HardwareTask(name), &task.locals, core, app);
+ let (struct_, pat) = locals::codegen(Context::HardwareTask(name), &task.locals, app);
root.push(struct_);
locals_pat = Some(pat);
@@ -113,20 +112,23 @@ pub fn codegen(
let attrs = &task.attrs;
let context = &task.context;
let stmts = &task.stmts;
- let section = util::link_section("text", core);
- // XXX shouldn't this have a cfg_core?
let locals_pat = locals_pat.iter();
user_tasks.push(quote!(
#(#attrs)*
#[allow(non_snake_case)]
- #section
fn #name(#(#locals_pat,)* #context: #name::Context) {
use rtic::Mutex as _;
#(#stmts)*
}
));
+
+ hardware_tasks_imports.push(quote!(
+ #(#attrs)*
+ #[allow(non_snake_case)]
+ use super::#name;
+ ));
}
- (const_app, root, user_tasks)
+ (mod_app, root, user_tasks, hardware_tasks_imports)
}
diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs
index 032c8ade..2e2932d7 100644
--- a/macros/src/codegen/idle.rs
+++ b/macros/src/codegen/idle.rs
@@ -1,21 +1,20 @@
use proc_macro2::TokenStream as TokenStream2;
-use quote::quote;
+use quote::{format_ident, quote};
use rtic_syntax::{ast::App, Context};
use crate::{
analyze::Analysis,
check::Extra,
- codegen::{locals, module, resources_struct, util},
+ codegen::{locals, module, resources_struct},
};
/// Generates support code for `#[idle]` functions
pub fn codegen(
- core: u8,
app: &App,
analysis: &Analysis,
extra: &Extra,
) -> (
- // const_app_idle -- the `${idle}Resources` constructor
+ // mod_app_idle -- the `${idle}Resources` constructor
Option<TokenStream2>,
// root_idle -- items that must be placed in the root of the crate:
// - the `${idle}Locals` struct
@@ -24,52 +23,65 @@ pub fn codegen(
Vec<TokenStream2>,
// user_idle
Option<TokenStream2>,
+ // user_idle_imports
+ Vec<TokenStream2>,
// call_idle
TokenStream2,
) {
- if let Some(idle) = app.idles.get(&core) {
+ if app.idles.len() > 0 {
+ let idle = &app.idles.first().unwrap();
let mut needs_lt = false;
- let mut const_app = None;
+ let mut mod_app = None;
let mut root_idle = vec![];
let mut locals_pat = None;
let mut locals_new = None;
+ let mut user_idle_imports = vec![];
+
+ let name = &idle.name;
+
if !idle.args.resources.is_empty() {
let (item, constructor) =
- resources_struct::codegen(Context::Idle(core), 0, &mut needs_lt, app, analysis);
+ resources_struct::codegen(Context::Idle, 0, &mut needs_lt, app, analysis);
root_idle.push(item);
- const_app = Some(constructor);
+ mod_app = Some(constructor);
+
+ let name_resource = format_ident!("{}Resources", name);
+ user_idle_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_resource;
+ ));
}
- let name = &idle.name;
if !idle.locals.is_empty() {
- let (locals, pat) = locals::codegen(Context::Idle(core), &idle.locals, core, app);
+ let (locals, pat) = locals::codegen(Context::Idle, &idle.locals, app);
locals_new = Some(quote!(#name::Locals::new()));
locals_pat = Some(pat);
root_idle.push(locals);
}
- root_idle.push(module::codegen(Context::Idle(core), needs_lt, app, extra));
+ root_idle.push(module::codegen(Context::Idle, needs_lt, app, extra));
- let cfg_core = util::cfg_core(core, app.args.cores);
let attrs = &idle.attrs;
let context = &idle.context;
let stmts = &idle.stmts;
- let section = util::link_section("text", core);
let locals_pat = locals_pat.iter();
let user_idle = Some(quote!(
#(#attrs)*
#[allow(non_snake_case)]
- #cfg_core
- #section
fn #name(#(#locals_pat,)* #context: #name::Context) -> ! {
use rtic::Mutex as _;
#(#stmts)*
}
));
+ user_idle_imports.push(quote!(
+ #(#attrs)*
+ #[allow(non_snake_case)]
+ use super::#name;
+ ));
let locals_new = locals_new.iter();
let call_idle = quote!(crate::#name(
@@ -77,12 +89,13 @@ pub fn codegen(
#name::Context::new(&rtic::export::Priority::new(0))
));
- (const_app, root_idle, user_idle, call_idle)
+ (mod_app, root_idle, user_idle, user_idle_imports, call_idle)
} else {
(
None,
vec![],
None,
+ vec![],
quote!(loop {
rtic::export::wfi()
}),
diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs
index fa273fee..8942439b 100644
--- a/macros/src/codegen/init.rs
+++ b/macros/src/codegen/init.rs
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream as TokenStream2;
-use quote::quote;
+use quote::{format_ident, quote};
use rtic_syntax::{ast::App, Context};
use crate::{
@@ -10,12 +10,11 @@ use crate::{
/// Generates support code for `#[init]` functions
pub fn codegen(
- core: u8,
app: &App,
analysis: &Analysis,
extra: &Extra,
) -> (
- // const_app_idle -- the `${init}Resources` constructor
+ // mod_app_idle -- the `${init}Resources` constructor
Option<TokenStream2>,
// root_init -- items that must be placed in the root of the crate:
// - the `${init}Locals` struct
@@ -25,58 +24,55 @@ pub fn codegen(
Vec<TokenStream2>,
// user_init -- the `#[init]` function written by the user
Option<TokenStream2>,
+ // user_init_imports -- the imports for `#[init]` functio written by the user
+ Vec<TokenStream2>,
// call_init -- the call to the user `#[init]` if there's one
Option<TokenStream2>,
) {
- if let Some(init) = app.inits.get(&core) {
- let cfg_core = util::cfg_core(core, app.args.cores);
+ if app.inits.len() > 0 {
+ let init = &app.inits.first().unwrap();
let mut needs_lt = false;
let name = &init.name;
let mut root_init = vec![];
- let ret = {
- let late_fields = analysis
- .late_resources
- .get(&core)
- .map(|resources| {
- resources
- .iter()
- .map(|name| {
- let ty = &app.late_resources[name].ty;
- let cfgs = &app.late_resources[name].cfgs;
-
- quote!(
- #(#cfgs)*
- pub #name: #ty
- )
- })
- .collect::<Vec<_>>()
+ let late_fields = analysis
+ .late_resources
+ .iter()
+ .flat_map(|resources| {
+ resources.iter().map(|name| {
+ let ty = &app.late_resources[name].ty;
+ let cfgs = &app.late_resources[name].cfgs;
+
+ quote!(
+ #(#cfgs)*
+ pub #name: #ty
+ )
})
- .unwrap_or(vec![]);
+ })
+ .collect::<Vec<_>>();
- if !late_fields.is_empty() {
- let late_resources = util::late_resources_ident(&name);
+ let mut user_init_imports = vec![];
+ let late_resources = util::late_resources_ident(&name);
- root_init.push(quote!(
- /// Resources initialized at runtime
- #cfg_core
- #[allow(non_snake_case)]
- pub struct #late_resources {
- #(#late_fields),*
- }
- ));
-
- Some(quote!(-> #name::LateResources))
- } else {
- None
+ root_init.push(quote!(
+ /// Resources initialized at runtime
+ #[allow(non_snake_case)]
+ pub struct #late_resources {
+ #(#late_fields),*
}
- };
+ ));
+
+ let name_late = format_ident!("{}LateResources", name);
+ user_init_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_late;
+ ));
let mut locals_pat = None;
let mut locals_new = None;
if !init.locals.is_empty() {
- let (struct_, pat) = locals::codegen(Context::Init(core), &init.locals, core, app);
+ let (struct_, pat) = locals::codegen(Context::Init, &init.locals, app);
locals_new = Some(quote!(#name::Locals::new()));
locals_pat = Some(pat);
@@ -86,25 +82,33 @@ pub fn codegen(
let context = &init.context;
let attrs = &init.attrs;
let stmts = &init.stmts;
- let section = util::link_section("text", core);
let locals_pat = locals_pat.iter();
let user_init = Some(quote!(
#(#attrs)*
- #cfg_core
#[allow(non_snake_case)]
- #section
- fn #name(#(#locals_pat,)* #context: #name::Context) #ret {
+ fn #name(#(#locals_pat,)* #context: #name::Context) -> #name::LateResources {
#(#stmts)*
}
));
+ user_init_imports.push(quote!(
+ #(#attrs)*
+ #[allow(non_snake_case)]
+ use super::#name;
+ ));
- let mut const_app = None;
+ let mut mod_app = None;
if !init.args.resources.is_empty() {
let (item, constructor) =
- resources_struct::codegen(Context::Init(core), 0, &mut needs_lt, app, analysis);
+ resources_struct::codegen(Context::Init, 0, &mut needs_lt, app, analysis);
root_init.push(item);
- const_app = Some(constructor);
+ mod_app = Some(constructor);
+
+ let name_late = format_ident!("{}Resources", name);
+ user_init_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_late;
+ ));
}
let locals_new = locals_new.iter();
@@ -112,10 +116,10 @@ pub fn codegen(
quote!(let late = crate::#name(#(#locals_new,)* #name::Context::new(core.into()));),
);
- root_init.push(module::codegen(Context::Init(core), needs_lt, app, extra));
+ root_init.push(module::codegen(Context::Init, needs_lt, app, extra));
- (const_app, root_init, user_init, call_init)
+ (mod_app, root_init, user_init, user_init_imports, call_init)
} else {
- (None, vec![], None, None)
+ (None, vec![], None, vec![], None)
}
}
diff --git a/macros/src/codegen/locals.rs b/macros/src/codegen/locals.rs
index 127f4b09..336c0b21 100644
--- a/macros/src/codegen/locals.rs
+++ b/macros/src/codegen/locals.rs
@@ -2,7 +2,7 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::{
ast::{App, Local},
- Context, Core, Map,
+ Context, Map,
};
use crate::codegen::util;
@@ -10,7 +10,6 @@ use crate::codegen::util;
pub fn codegen(
ctxt: Context,
locals: &Map<Local>,
- core: Core,
app: &App,
) -> (
// locals
@@ -42,11 +41,6 @@ pub fn codegen(
let cfgs = &local.cfgs;
has_cfgs |= !cfgs.is_empty();
- let section = if local.shared && cfg!(feature = "heterogeneous") {
- Some(quote!(#[rtic::export::shared]))
- } else {
- util::link_section("data", core)
- };
let expr = &local.expr;
let ty = &local.ty;
fields.push(quote!(
@@ -55,7 +49,6 @@ pub fn codegen(
));
items.push(quote!(
#(#cfgs)*
- #section
static mut #name: #ty = #expr
));
values.push(quote!(
diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs
index 1b21209f..2e51e7db 100644
--- a/macros/src/codegen/module.rs
+++ b/macros/src/codegen/module.rs
@@ -11,12 +11,11 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
let name = ctxt.ident(app);
- let core = ctxt.core(app);
let mut needs_instant = false;
let mut lt = None;
match ctxt {
- Context::Init(core) => {
- if app.uses_schedule(core) {
+ Context::Init => {
+ if app.uses_schedule() {
let m = extra.monotonic();
fields.push(quote!(
@@ -37,7 +36,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
));
}
- if extra.peripherals == Some(core) {
+ if extra.peripherals {
let device = extra.device;
fields.push(quote!(
@@ -48,13 +47,21 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
values.push(quote!(device: #device::Peripherals::steal()));
}
+ lt = Some(quote!('a));
+ fields.push(quote!(
+ /// Critical section token for init
+ pub cs: rtic::export::CriticalSection<#lt>
+ ));
+
+ values.push(quote!(cs: rtic::export::CriticalSection::new()));
+
values.push(quote!(core));
}
- Context::Idle(..) => {}
+ Context::Idle => {}
Context::HardwareTask(..) => {
- if app.uses_schedule(core) {
+ if app.uses_schedule() {
let m = extra.monotonic();
fields.push(quote!(
@@ -69,7 +76,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
}
Context::SoftwareTask(..) => {
- if app.uses_schedule(core) {
+ if app.uses_schedule() {
let m = extra.monotonic();
fields.push(quote!(
@@ -205,7 +212,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
values.push(quote!(spawn: Spawn { priority }));
} else {
- let instant_field = if app.uses_schedule(core) {
+ let instant_field = if app.uses_schedule() {
let m = extra.monotonic();
needs_instant = true;
@@ -252,27 +259,25 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
}
}
- if let Context::Init(core) = ctxt {
- let init = &app.inits[&core];
- if init.returns_late_resources {
- let late_resources = util::late_resources_ident(&init.name);
+ if let Context::Init = ctxt {
+ let init = &app.inits.first().unwrap();
+ let late_resources = util::late_resources_ident(&init.name);
- items.push(quote!(
- #[doc(inline)]
- pub use super::#late_resources as LateResources;
- ));
- }
+ items.push(quote!(
+ #[doc(inline)]
+ pub use super::#late_resources as LateResources;
+ ));
}
let doc = match ctxt {
- Context::Idle(_) => "Idle loop",
- Context::Init(_) => "Initialization function",
+ Context::Idle => "Idle loop",
+ Context::Init => "Initialization function",
Context::HardwareTask(_) => "Hardware task",
Context::SoftwareTask(_) => "Software task",
};
let core = if ctxt.is_init() {
- if app.uses_schedule(core) {
+ if app.uses_schedule() {
Some(quote!(core: rtic::Peripherals,))
} else {
Some(quote!(core: rtic::export::Peripherals,))
@@ -312,12 +317,9 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) ->
));
if !items.is_empty() {
- let cfg_core = util::cfg_core(ctxt.core(app), app.args.cores);
-
quote!(
#[allow(non_snake_case)]
#[doc = #doc]
- #cfg_core
pub mod #name {
#(#items)*
}
diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs
index 0c740e85..c35c6976 100644
--- a/macros/src/codegen/post_init.rs
+++ b/macros/src/codegen/post_init.rs
@@ -2,22 +2,17 @@ use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::ast::App;
-use crate::{analyze::Analysis, check::Extra, codegen::util};
+use crate::analyze::Analysis;
/// Generates code that runs after `#[init]` returns
-pub fn codegen(
- core: u8,
- app: &App,
- analysis: &Analysis,
- extra: &Extra,
-) -> (Vec<TokenStream2>, Vec<TokenStream2>) {
- let mut const_app = vec![];
+pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> {
let mut stmts = vec![];
- // initialize late resources
- if let Some(late_resources) = analysis.late_resources.get(&core) {
- for name in late_resources {
- // if it's live
+ // Initialize late resources
+ if analysis.late_resources.len() > 0 {
+ // BTreeSet wrapped in a vector
+ for name in analysis.late_resources.first().unwrap() {
+ // If it's live
let cfgs = app.late_resources[name].cfgs.clone();
if analysis.locations.get(name).is_some() {
// Need to also include the cfgs
@@ -29,134 +24,8 @@ pub fn codegen(
}
}
- if analysis.timer_queues.is_empty() {
- // cross-initialization barriers -- notify *other* cores that their resources have been
- // initialized
- for (user, initializers) in &analysis.initialization_barriers {
- if !initializers.contains(&core) {
- continue;
- }
-
- let ib = util::init_barrier(*user);
- let shared = if cfg!(feature = "heterogeneous") {
- Some(quote!(
- #[rtic::export::shared]
- ))
- } else {
- None
- };
-
- const_app.push(quote!(
- #shared
- static #ib: rtic::export::Barrier = rtic::export::Barrier::new();
- ));
-
- stmts.push(quote!(
- #ib.release();
- ));
- }
-
- // then wait until the other cores have initialized *our* resources
- if analysis.initialization_barriers.contains_key(&core) {
- let ib = util::init_barrier(core);
-
- stmts.push(quote!(
- #ib.wait();
- ));
- }
-
- // cross-spawn barriers: wait until other cores are ready to receive messages
- for (&receiver, senders) in &analysis.spawn_barriers {
- if senders.get(&core) == Some(&false) {
- let sb = util::spawn_barrier(receiver);
-
- stmts.push(quote!(
- #sb.wait();
- ));
- }
- }
- } else {
- // if the `schedule` API is used then we'll synchronize all cores to leave the
- // `init`-ialization phase at the same time. In this case the rendezvous barrier makes the
- // cross-initialization and spawn barriers unnecessary
-
- let m = extra.monotonic();
-
- if analysis.timer_queues.len() == 1 {
- // reset the monotonic timer / counter
- stmts.push(quote!(
- <#m as rtic::Monotonic>::reset();
- ));
- } else {
- // in the multi-core case we need a rendezvous (RV) barrier between *all* the cores that
- // use the `schedule` API; otherwise one of the cores could observe the before-reset
- // value of the monotonic counter
- // (this may be easier to implement with `AtomicU8.fetch_sub` but that API is not
- // available on ARMv6-M)
-
- // this core will reset the monotonic counter
- const FIRST: u8 = 0;
-
- if core == FIRST {
- for &i in analysis.timer_queues.keys() {
- let rv = util::rendezvous_ident(i);
- let shared = if cfg!(feature = "heterogeneous") {
- Some(quote!(
- #[rtic::export::shared]
- ))
- } else {
- None
- };
-
- const_app.push(quote!(
- #shared
- static #rv: rtic::export::Barrier = rtic::export::Barrier::new();
- ));
-
- // wait until all the other cores have reached the RV point
- if i != FIRST {
- stmts.push(quote!(
- #rv.wait();
- ));
- }
- }
-
- let rv = util::rendezvous_ident(core);
- stmts.push(quote!(
- // the compiler fences are used to prevent `reset` from being re-ordering wrt to
- // the atomic operations -- we don't know if `reset` contains load or store
- // operations
-
- core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- // reset the counter
- <#m as rtic::Monotonic>::reset();
-
- core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- // now unblock all the other cores
- #rv.release();
- ));
- } else {
- let rv = util::rendezvous_ident(core);
-
- // let the first core know that we have reached the RV point
- stmts.push(quote!(
- #rv.release();
- ));
-
- let rv = util::rendezvous_ident(FIRST);
-
- // wait until the first core has reset the monotonic timer
- stmts.push(quote!(
- #rv.wait();
- ));
- }
- }
- }
-
- // enable the interrupts -- this completes the `init`-ialization phase
+ // Enable the interrupts -- this completes the `init`-ialization phase
stmts.push(quote!(rtic::export::interrupt::enable();));
- (const_app, stmts)
+ stmts
}
diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs
index 8aae5998..9c5f35ec 100644
--- a/macros/src/codegen/pre_init.rs
+++ b/macros/src/codegen/pre_init.rs
@@ -5,76 +5,52 @@ use rtic_syntax::ast::App;
use crate::{analyze::Analysis, check::Extra, codegen::util};
/// Generates code that runs before `#[init]`
-pub fn codegen(
- core: u8,
- app: &App,
- analysis: &Analysis,
- extra: &Extra,
-) -> (
- // `const_app_pre_init` -- `static` variables for barriers
- Vec<TokenStream2>,
- // `pre_init_stmts`
- Vec<TokenStream2>,
-) {
- let mut const_app = vec![];
+pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
let mut stmts = vec![];
- // disable interrupts -- `init` must run with interrupts disabled
+ // Disable interrupts -- `init` must run with interrupts disabled
stmts.push(quote!(rtic::export::interrupt::disable();));
- // populate this core `FreeQueue`s
- for (name, senders) in &analysis.free_queues {
+ // Populate the FreeQueue
+ for fq in &analysis.free_queues {
+ // Get the task name
+ let name = fq.0;
let task = &app.software_tasks[name];
let cap = task.args.capacity;
- for &sender in senders.keys() {
- if sender == core {
- let fq = util::fq_ident(name, sender);
+ let fq_ident = util::fq_ident(name);
- stmts.push(quote!(
- (0..#cap).for_each(|i| #fq.enqueue_unchecked(i));
- ));
- }
- }
- }
-
- if app.args.cores == 1 {
- stmts.push(quote!(
- // To set the variable in cortex_m so the peripherals cannot be taken multiple times
- let peripherals = cortex_m::Peripherals::steal();
- let mut core: rtic::export::Peripherals = peripherals.into();
- ));
- } else {
stmts.push(quote!(
- // NOTE(transmute) to avoid debug_assertion in multi-core mode
- // (This code will go away when we drop multi-core mode)
- let mut core: rtic::export::Peripherals = core::mem::transmute(());
+ (0..#cap).for_each(|i| #fq_ident.enqueue_unchecked(i));
));
}
+ stmts.push(quote!(
+ // To set the variable in cortex_m so the peripherals cannot be taken multiple times
+ let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into();
+ ));
+
let device = extra.device;
let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS);
- // unmask interrupts and set their priorities
+ // Unmask interrupts and set their priorities
for (&priority, name) in analysis
.interrupts
- .get(&core)
.iter()
- .flat_map(|interrupts| *interrupts)
.chain(app.hardware_tasks.values().flat_map(|task| {
if !util::is_exception(&task.args.binds) {
Some((&task.args.priority, &task.args.binds))
} else {
- // we do exceptions in another pass
+ // We do exceptions in another pass
None
}
}))
{
- // 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)];));
// NOTE this also checks that the interrupt exists in the `Interrupt` enumeration
- let interrupt = util::interrupt_ident(core, app.args.cores);
+ let interrupt = util::interrupt_ident();
stmts.push(quote!(
core.NVIC.set_priority(
#device::#interrupt::#name,
@@ -87,30 +63,7 @@ pub fn codegen(
stmts.push(quote!(rtic::export::NVIC::unmask(#device::#interrupt::#name);));
}
- // cross-spawn barriers: now that priorities have been set and the interrupts have been unmasked
- // we are ready to receive messages from *other* cores
- if analysis.spawn_barriers.contains_key(&core) {
- let sb = util::spawn_barrier(core);
- let shared = if cfg!(feature = "heterogeneous") {
- Some(quote!(
- #[rtic::export::shared]
- ))
- } else {
- None
- };
-
- const_app.push(quote!(
- #shared
- static #sb: rtic::export::Barrier = rtic::export::Barrier::new();
- ));
-
- // unblock cores that may send us a message
- stmts.push(quote!(
- #sb.release();
- ));
- }
-
- // set exception priorities
+ // Set exception priorities
for (name, priority) in app.hardware_tasks.values().filter_map(|task| {
if util::is_exception(&task.args.binds) {
Some((&task.args.binds, task.args.priority))
@@ -118,7 +71,7 @@ pub fn codegen(
None
}
}) {
- // 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!(core.SCB.set_priority(
@@ -127,11 +80,11 @@ pub fn codegen(
);));
}
- // initialize the SysTick
- if let Some(tq) = analysis.timer_queues.get(&core) {
+ // Initialize the SysTick if there exist a TimerQueue
+ if let Some(tq) = analysis.timer_queues.first() {
let priority = tq.priority;
- // 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!(core.SCB.set_priority(
@@ -146,23 +99,11 @@ pub fn codegen(
));
}
- // if there's no user `#[idle]` then optimize returning from interrupt handlers
- if app.idles.get(&core).is_none() {
+ // If there's no user `#[idle]` then optimize returning from interrupt handlers
+ if app.idles.is_empty() {
// Set SLEEPONEXIT bit to enter sleep mode when returning from ISR
stmts.push(quote!(core.SCB.scr.modify(|r| r | 1 << 1);));
}
- // cross-spawn barriers: wait until other cores are ready to receive messages
- for (&receiver, senders) in &analysis.spawn_barriers {
- // only block here if `init` can send messages to `receiver`
- if senders.get(&core) == Some(&true) {
- let sb = util::spawn_barrier(receiver);
-
- stmts.push(quote!(
- #sb.wait();
- ));
- }
- }
-
- (const_app, stmts)
+ stmts
}
diff --git a/macros/src/codegen/resources.rs b/macros/src/codegen/resources.rs
index 0bec3e5a..38ea5245 100644
--- a/macros/src/codegen/resources.rs
+++ b/macros/src/codegen/resources.rs
@@ -1,9 +1,6 @@
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
-use rtic_syntax::{
- analyze::{Location, Ownership},
- ast::App,
-};
+use rtic_syntax::{analyze::Ownership, ast::App};
use crate::{analyze::Analysis, check::Extra, codegen::util};
@@ -13,45 +10,26 @@ pub fn codegen(
analysis: &Analysis,
extra: &Extra,
) -> (
- // const_app -- the `static [mut]` variables behind the proxies
+ // mod_app -- the `static [mut]` variables behind the proxies
Vec<TokenStream2>,
// mod_resources -- the `resources` module
TokenStream2,
+ // mod_resources_imports -- the `resources` module imports
+ Vec<TokenStream2>,
) {
- let mut const_app = vec![];
+ let mut mod_app = vec![];
let mut mod_resources = vec![];
+ let mut mod_resources_imports = vec![];
- for (name, res, expr, loc) in app.resources(analysis) {
+ for (name, res, expr, _) in app.resources(analysis) {
let cfgs = &res.cfgs;
let ty = &res.ty;
{
- let (loc_attr, section) = match loc {
- Location::Owned {
- core,
- cross_initialized: false,
- } => (
- util::cfg_core(*core, app.args.cores),
- if expr.is_none() {
- util::link_section_uninit(Some(*core))
- } else {
- util::link_section("data", *core)
- },
- ),
-
- // shared `static`s and cross-initialized resources need to be in `.shared` memory
- _ => (
- if cfg!(feature = "heterogeneous") {
- Some(quote!(#[rtic::export::shared]))
- } else {
- None
- },
- if expr.is_none() {
- util::link_section_uninit(None)
- } else {
- None
- },
- ),
+ let section = if expr.is_none() {
+ util::link_section_uninit(true)
+ } else {
+ None
};
let (ty, expr) = if let Some(expr) = expr {
@@ -64,29 +42,24 @@ pub fn codegen(
};
let attrs = &res.attrs;
- const_app.push(quote!(
+ mod_app.push(quote!(
#[allow(non_upper_case_globals)]
#(#attrs)*
#(#cfgs)*
- #loc_attr
#section
static mut #name: #ty = #expr;
));
}
if let Some(Ownership::Contended { ceiling }) = analysis.ownerships.get(name) {
- let cfg_core = util::cfg_core(loc.core().expect("UNREACHABLE"), app.args.cores);
-
mod_resources.push(quote!(
#[allow(non_camel_case_types)]
#(#cfgs)*
- #cfg_core
pub struct #name<'a> {
priority: &'a Priority,
}
#(#cfgs)*
- #cfg_core
impl<'a> #name<'a> {
#[inline(always)]
pub unsafe fn new(priority: &'a Priority) -> Self {
@@ -112,10 +85,15 @@ pub fn codegen(
)
};
- const_app.push(util::impl_mutex(
+ mod_resources_imports.push(quote!(
+ #[allow(non_camel_case_types)]
+ #(#cfgs)*
+ use super::resources::#name;
+ ));
+
+ mod_app.push(util::impl_mutex(
extra,
cfgs,
- cfg_core.as_ref(),
true,
name,
quote!(#ty),
@@ -128,6 +106,11 @@ pub fn codegen(
let mod_resources = if mod_resources.is_empty() {
quote!()
} else {
+ // Also import the resource module
+ mod_resources_imports.push(quote!(
+ use super::resources;
+ ));
+
quote!(mod resources {
use rtic::export::Priority;
@@ -135,5 +118,5 @@ pub fn codegen(
})
};
- (const_app, mod_resources)
+ (mod_app, mod_resources, mod_resources_imports)
}
diff --git a/macros/src/codegen/resources_struct.rs b/macros/src/codegen/resources_struct.rs
index 994e751c..92d5b666 100644
--- a/macros/src/codegen/resources_struct.rs
+++ b/macros/src/codegen/resources_struct.rs
@@ -14,8 +14,8 @@ pub fn codegen(
let mut lt = None;
let resources = match ctxt {
- Context::Init(core) => &app.inits[&core].args.resources,
- Context::Idle(core) => &app.idles[&core].args.resources,
+ Context::Init => &app.inits.first().unwrap().args.resources,
+ Context::Idle => &app.idles.first().unwrap().args.resources,
Context::HardwareTask(name) => &app.hardware_tasks[name].args.resources,
Context::SoftwareTask(name) => &app.software_tasks[name].args.resources,
};
@@ -39,7 +39,7 @@ pub fn codegen(
if ctxt.is_init() {
if !analysis.ownerships.contains_key(name) {
- // owned by `init`
+ // Owned by `init`
fields.push(quote!(
#(#cfgs)*
pub #name: &'static #mut_ #ty
@@ -50,7 +50,7 @@ pub fn codegen(
#name: &#mut_ #name
));
} else {
- // owned by someone else
+ // Owned by someone else
lt = Some(quote!('a));
fields.push(quote!(
@@ -75,7 +75,7 @@ pub fn codegen(
pub #name: &'a #ty
));
} else {
- // resource proxy
+ // Resource proxy
lt = Some(quote!('a));
fields.push(quote!(
@@ -136,7 +136,7 @@ pub fn codegen(
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 {
fields.push(quote!(
#[doc(hidden)]
@@ -147,13 +147,9 @@ pub fn codegen(
}
}
- let core = ctxt.core(app);
- let cores = app.args.cores;
- let cfg_core = util::cfg_core(core, cores);
let doc = format!("Resources `{}` has access to", ctxt.ident(app));
let ident = util::resources_ident(ctxt, app);
let item = quote!(
- #cfg_core
#[allow(non_snake_case)]
#[doc = #doc]
pub struct #ident<#lt> {
@@ -167,10 +163,9 @@ pub fn codegen(
Some(quote!(priority: &#lt rtic::export::Priority))
};
let constructor = quote!(
- #cfg_core
impl<#lt> #ident<#lt> {
#[inline(always)]
- unsafe fn new(#arg) -> Self {
+ pub unsafe fn new(#arg) -> Self {
#ident {
#(#values,)*
}
diff --git a/macros/src/codegen/schedule.rs b/macros/src/codegen/schedule.rs
index 728d3a09..5a887496 100644
--- a/macros/src/codegen/schedule.rs
+++ b/macros/src/codegen/schedule.rs
@@ -1,4 +1,4 @@
-use std::collections::{BTreeMap, HashSet};
+use std::collections::HashSet;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
@@ -13,14 +13,11 @@ use crate::{
pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
- let mut seen = BTreeMap::<u8, HashSet<_>>::new();
+ let mut seen = HashSet::<_>::new();
for (scheduler, schedulees) in app.schedule_callers() {
let m = extra.monotonic();
let instant = quote!(<#m as rtic::Monotonic>::Instant);
- let sender = scheduler.core(app);
- let cfg_sender = util::cfg_core(sender, app.args.cores);
- let seen = seen.entry(sender).or_default();
let mut methods = vec![];
for name in schedulees {
@@ -35,29 +32,24 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
let body = schedule_body::codegen(scheduler, &name, app);
- let section = util::link_section("text", sender);
methods.push(quote!(
#(#cfgs)*
- #section
- fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
+ pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
#body
}
));
} else {
- let schedule = util::schedule_ident(name, sender);
+ let schedule = util::schedule_ident(name);
if !seen.contains(name) {
- // generate a `schedule_${name}_S${sender}` function
+ // Generate a `schedule_${name}_S${sender}` function
seen.insert(name);
let body = schedule_body::codegen(scheduler, &name, app);
- let section = util::link_section("text", sender);
items.push(quote!(
- #cfg_sender
#(#cfgs)*
- #section
- unsafe fn #schedule(
+ pub unsafe fn #schedule(
priority: &rtic::export::Priority,
instant: #instant
#(,#args)*
@@ -70,7 +62,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
methods.push(quote!(
#(#cfgs)*
#[inline(always)]
- fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
+ pub fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> {
unsafe {
#schedule(self.priority(), instant #(,#untupled)*)
}
@@ -88,7 +80,6 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec<TokenStream2> {
let scheduler = scheduler.ident(app);
debug_assert!(!methods.is_empty());
items.push(quote!(
- #cfg_sender
impl<#lt> #scheduler::Schedule<#lt> {
#(#methods)*
}
diff --git a/macros/src/codegen/schedule_body.rs b/macros/src/codegen/schedule_body.rs
index 8fd026c2..644930d7 100644
--- a/macros/src/codegen/schedule_body.rs
+++ b/macros/src/codegen/schedule_body.rs
@@ -6,12 +6,10 @@ use syn::Ident;
use crate::codegen::util;
pub fn codegen(scheduler: Context, name: &Ident, app: &App) -> TokenStream2 {
- let sender = scheduler.core(app);
let schedulee = &app.software_tasks[name];
- let receiver = schedulee.args.core;
- let fq = util::fq_ident(name, sender);
- let tq = util::tq_ident(sender);
+ let fq = util::fq_ident(name);
+ let tq = util::tq_ident();
let (dequeue, enqueue) = if scheduler.is_init() {
(quote!(#fq.dequeue()), quote!(#tq.enqueue_unchecked(nr);))
} else {
@@ -21,8 +19,8 @@ pub fn codegen(scheduler: Context, name: &Ident, app: &App) -> TokenStream2 {
)
};
- let write_instant = if app.uses_schedule(receiver) {
- let instants = util::instants_ident(name, sender);
+ let write_instant = if app.uses_schedule() {
+ let instants = util::instants_ident(name);
Some(quote!(
#instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant);
@@ -32,8 +30,8 @@ pub fn codegen(scheduler: Context, name: &Ident, app: &App) -> TokenStream2 {
};
let (_, tupled, _, _) = util::regroup_inputs(&schedulee.inputs);
- let inputs = util::inputs_ident(name, sender);
- let t = util::schedule_t_ident(sender);
+ let inputs = util::inputs_ident(name);
+ let t = util::schedule_t_ident();
quote!(
unsafe {
use rtic::Mutex as _;
diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs
index 14a57633..4ae37e4e 100644
--- a/macros/src/codegen/software_tasks.rs
+++ b/macros/src/codegen/software_tasks.rs
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream as TokenStream2;
-use quote::quote;
+use quote::{format_ident, quote};
use rtic_syntax::{ast::App, Context};
use crate::{
@@ -13,7 +13,7 @@ pub fn codegen(
analysis: &Analysis,
extra: &Extra,
) -> (
- // const_app_software_tasks -- free queues, buffers and `${task}Resources` constructors
+ // mod_app_software_tasks -- free queues, buffers and `${task}Resources` constructors
Vec<TokenStream2>,
// root_software_tasks -- items that must be placed in the root of the crate:
// - `${task}Locals` structs
@@ -22,14 +22,15 @@ pub fn codegen(
Vec<TokenStream2>,
// user_software_tasks -- the `#[task]` functions written by the user
Vec<TokenStream2>,
+ // user_software_tasks_imports -- the imports for `#[task]` functions written by the user
+ Vec<TokenStream2>,
) {
- let mut const_app = vec![];
+ let mut mod_app = vec![];
let mut root = vec![];
let mut user_tasks = vec![];
+ let mut software_tasks_imports = vec![];
for (name, task) in &app.software_tasks {
- let receiver = task.args.core;
-
let inputs = &task.inputs;
let (_, _, _, input_ty) = util::regroup_inputs(inputs);
@@ -37,103 +38,70 @@ pub fn codegen(
let cap_lit = util::capacity_literal(cap);
let cap_ty = util::capacity_typenum(cap, true);
- // create free queues and inputs / instants buffers
- if let Some(free_queues) = analysis.free_queues.get(name) {
- for (&sender, &ceiling) in free_queues {
- let cfg_sender = util::cfg_core(sender, app.args.cores);
- let fq = util::fq_ident(name, sender);
-
- let (loc, fq_ty, fq_expr, bss, mk_uninit): (
- _,
- _,
- _,
- _,
- Box<dyn Fn() -> Option<_>>,
- ) = if receiver == sender {
- (
- cfg_sender.clone(),
- quote!(rtic::export::SCFQ<#cap_ty>),
- quote!(rtic::export::Queue(unsafe {
- rtic::export::iQueue::u8_sc()
- })),
- util::link_section("bss", sender),
- Box::new(|| util::link_section_uninit(Some(sender))),
- )
- } else {
- let shared = if cfg!(feature = "heterogeneous") {
- Some(quote!(#[rtic::export::shared]))
- } else {
- None
- };
-
- (
- shared,
- quote!(rtic::export::MCFQ<#cap_ty>),
- quote!(rtic::export::Queue(rtic::export::iQueue::u8())),
- None,
- Box::new(|| util::link_section_uninit(None)),
- )
- };
- let loc = &loc;
-
- const_app.push(quote!(
- /// Queue version of a free-list that keeps track of empty slots in
- /// the following buffers
- #loc
- #bss
- static mut #fq: #fq_ty = #fq_expr;
+ // 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;
+ ));
+
+ // 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<_>>();
- // Generate a resource proxy if needed
- if let Some(ceiling) = ceiling {
- const_app.push(quote!(
- #cfg_sender
- struct #fq<'a> {
- priority: &'a rtic::export::Priority,
- }
- ));
-
- const_app.push(util::impl_mutex(
- extra,
- &[],
- cfg_sender.as_ref(),
- false,
- &fq,
- fq_ty,
- ceiling,
- quote!(&mut #fq),
- ));
- }
-
- let ref elems = (0..cap)
- .map(|_| quote!(core::mem::MaybeUninit::uninit()))
- .collect::<Vec<_>>();
-
- if app.uses_schedule(receiver) {
- let m = extra.monotonic();
- let instants = util::instants_ident(name, sender);
-
- let uninit = mk_uninit();
- const_app.push(quote!(
- #loc
- #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 app.uses_schedule() {
+ let m = extra.monotonic();
+ let instants = util::instants_ident(name);
let uninit = mk_uninit();
- let inputs = util::inputs_ident(name, sender);
- const_app.push(quote!(
- #loc
+ 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
+ static mut #instants:
+ [core::mem::MaybeUninit<<#m as rtic::Monotonic>::Instant>; #cap_lit] =
[#(#elems,)*];
));
}
+
+ 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] =
+ [#(#elems,)*];
+ ));
}
// `${task}Resources`
@@ -147,23 +115,27 @@ pub fn codegen(
analysis,
);
+ // Add resources to imports
+ let name_res = format_ident!("{}Resources", name);
+ software_tasks_imports.push(quote!(
+ #[allow(non_snake_case)]
+ use super::#name_res;
+ ));
+
root.push(item);
- const_app.push(constructor);
+ mod_app.push(constructor);
}
// `${task}Locals`
let mut locals_pat = None;
if !task.locals.is_empty() {
- let (struct_, pat) =
- locals::codegen(Context::SoftwareTask(name), &task.locals, receiver, app);
+ let (struct_, pat) = locals::codegen(Context::SoftwareTask(name), &task.locals, app);
locals_pat = Some(pat);
root.push(struct_);
}
- let cfg_receiver = util::cfg_core(receiver, app.args.cores);
- let section = util::link_section("text", receiver);
let context = &task.context;
let attrs = &task.attrs;
let cfgs = &task.cfgs;
@@ -173,14 +145,17 @@ pub fn codegen(
#(#attrs)*
#(#cfgs)*
#[allow(non_snake_case)]
- #cfg_receiver
- #section
- fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
+ pub fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
use rtic::Mutex as _;
#(#stmts)*
}
));
+ software_tasks_imports.push(quote!(
+ #(#cfgs)*
+ #[allow(non_snake_case)]
+ use super::#name;
+ ));
root.push(module::codegen(
Context::SoftwareTask(name),
@@ -190,5 +165,5 @@ pub fn codegen(
));
}
- (const_app, root, user_tasks)
+ (mod_app, root, user_tasks, software_tasks_imports)
}
diff --git a/macros/src/codegen/spawn.rs b/macros/src/codegen/spawn.rs
index 287c92a1..da281516 100644
--- a/macros/src/codegen/spawn.rs
+++ b/macros/src/codegen/spawn.rs
@@ -1,4 +1,4 @@
-use std::collections::{BTreeMap, HashSet};
+use std::collections::HashSet;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
@@ -14,16 +14,12 @@ use crate::{
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
- let mut seen = BTreeMap::<u8, HashSet<_>>::new();
+ let mut seen = HashSet::<_>::new();
for (spawner, spawnees) in app.spawn_callers() {
- let sender = spawner.core(app);
- let cfg_sender = util::cfg_core(sender, app.args.cores);
- let seen = seen.entry(sender).or_default();
let mut methods = vec![];
for name in spawnees {
let spawnee = &app.software_tasks[name];
- let receiver = spawnee.args.core;
let cfgs = &spawnee.cfgs;
let (args, _, untupled, ty) = util::regroup_inputs(&spawnee.inputs);
let args = &args;
@@ -34,7 +30,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let body = spawn_body::codegen(spawner, &name, app, analysis, extra);
- let let_instant = if app.uses_schedule(receiver) {
+ let let_instant = if app.uses_schedule() {
let m = extra.monotonic();
Some(quote!(let instant = unsafe { <#m as rtic::Monotonic>::zero() };))
@@ -42,23 +38,21 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
None
};
- let section = util::link_section("text", sender);
methods.push(quote!(
#(#cfgs)*
- #section
- fn #name(&self #(,#args)*) -> Result<(), #ty> {
+ pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
#let_instant
#body
}
));
} else {
- let spawn = util::spawn_ident(name, sender);
+ let spawn = util::spawn_ident(name);
if !seen.contains(name) {
- // generate a `spawn_${name}_S${sender}` function
+ // Generate a `spawn_${name}_S${sender}` function
seen.insert(name);
- let instant = if app.uses_schedule(receiver) {
+ let instant = if app.uses_schedule() {
let m = extra.monotonic();
Some(quote!(, instant: <#m as rtic::Monotonic>::Instant))
@@ -68,11 +62,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let body = spawn_body::codegen(spawner, &name, app, analysis, extra);
- let section = util::link_section("text", sender);
items.push(quote!(
- #cfg_sender
#(#cfgs)*
- #section
unsafe fn #spawn(
priority: &rtic::export::Priority
#instant
@@ -83,7 +74,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
));
}
- let (let_instant, instant) = if app.uses_schedule(receiver) {
+ let (let_instant, instant) = if app.uses_schedule() {
let m = extra.monotonic();
(
@@ -101,7 +92,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
methods.push(quote!(
#(#cfgs)*
#[inline(always)]
- fn #name(&self #(,#args)*) -> Result<(), #ty> {
+ pub fn #name(&self #(,#args)*) -> Result<(), #ty> {
unsafe {
#let_instant
#spawn(self.priority() #instant #(,#untupled)*)
@@ -120,7 +111,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let spawner = spawner.ident(app);
debug_assert!(!methods.is_empty());
items.push(quote!(
- #cfg_sender
impl<#lt> #spawner::Spawn<#lt> {
#(#methods)*
}
diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs
index 3433875e..4ecd0757 100644
--- a/macros/src/codegen/spawn_body.rs
+++ b/macros/src/codegen/spawn_body.rs
@@ -12,13 +12,11 @@ pub fn codegen(
analysis: &Analysis,
extra: &Extra,
) -> TokenStream2 {
- let sender = spawner.core(app);
let spawnee = &app.software_tasks[name];
let priority = spawnee.args.priority;
- let receiver = spawnee.args.core;
- let write_instant = if app.uses_schedule(receiver) {
- let instants = util::instants_ident(name, sender);
+ let write_instant = if app.uses_schedule() {
+ let instants = util::instants_ident(name);
Some(quote!(
#instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant);
@@ -27,9 +25,9 @@ pub fn codegen(
None
};
- let t = util::spawn_t_ident(receiver, priority, sender);
- let fq = util::fq_ident(name, sender);
- let rq = util::rq_ident(receiver, priority, sender);
+ let t = util::spawn_t_ident(priority);
+ let fq = util::fq_ident(name);
+ let rq = util::rq_ident(priority);
let (dequeue, enqueue) = if spawner.is_init() {
(
quote!(#fq.dequeue()),
@@ -45,20 +43,16 @@ pub fn codegen(
};
let device = extra.device;
- let enum_ = util::interrupt_ident(receiver, app.args.cores);
- let interrupt = &analysis.interrupts[&receiver][&priority];
- let pend = if sender != receiver {
- quote!(
- #device::xpend(#receiver, #device::#enum_::#interrupt);
- )
- } else {
+ let enum_ = util::interrupt_ident();
+ let interrupt = &analysis.interrupts.get(&priority);
+ let pend = {
quote!(
rtic::pend(#device::#enum_::#interrupt);
)
};
let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs);
- let inputs = util::inputs_ident(name, sender);
+ let inputs = util::inputs_ident(name);
quote!(
unsafe {
use rtic::Mutex as _;
diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs
index 56304001..030158e2 100644
--- a/macros/src/codegen/timer_queue.rs
+++ b/macros/src/codegen/timer_queue.rs
@@ -8,9 +8,8 @@ use crate::{analyze::Analysis, check::Extra, codegen::util};
pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> {
let mut items = vec![];
- for (&sender, timer_queue) in &analysis.timer_queues {
- let cfg_sender = util::cfg_core(sender, app.args.cores);
- let t = util::schedule_t_ident(sender);
+ if let Some(timer_queue) = &analysis.timer_queues.first() {
+ let t = util::schedule_t_ident();
// Enumeration of `schedule`-able tasks
{
@@ -27,9 +26,8 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
.collect::<Vec<_>>();
- let doc = format!("Tasks that can be scheduled from core #{}", sender);
+ let doc = format!("Tasks that can be scheduled");
items.push(quote!(
- #cfg_sender
#[doc = #doc]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
@@ -39,27 +37,23 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
));
}
- let tq = util::tq_ident(sender);
+ let tq = util::tq_ident();
// Static variable and resource proxy
{
- let doc = format!("Core #{} timer queue", sender);
+ let doc = format!("Timer queue");
let m = extra.monotonic();
let n = util::capacity_typenum(timer_queue.capacity, false);
let tq_ty = quote!(rtic::export::TimerQueue<#m, #t, #n>);
- let section = util::link_section("bss", sender);
items.push(quote!(
- #cfg_sender
#[doc = #doc]
- #section
static mut #tq: #tq_ty = rtic::export::TimerQueue(
rtic::export::BinaryHeap(
rtic::export::iBinaryHeap::new()
)
);
- #cfg_sender
struct #tq<'a> {
priority: &'a rtic::export::Priority,
}
@@ -68,7 +62,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
items.push(util::impl_mutex(
extra,
&[],
- cfg_sender.as_ref(),
false,
&tq,
tq_ty,
@@ -88,17 +81,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
let cfgs = &task.cfgs;
let priority = task.args.priority;
- let receiver = task.args.core;
- let rq = util::rq_ident(receiver, priority, sender);
- let rqt = util::spawn_t_ident(receiver, priority, sender);
- let enum_ = util::interrupt_ident(receiver, app.args.cores);
- let interrupt = &analysis.interrupts[&receiver][&priority];
+ let rq = util::rq_ident(priority);
+ let rqt = util::spawn_t_ident(priority);
+ let enum_ = util::interrupt_ident();
+ let interrupt = &analysis.interrupts.get(&priority);
- let pend = if sender != receiver {
- quote!(
- #device::xpend(#receiver, #device::#enum_::#interrupt);
- )
- } else {
+ let pend = {
quote!(
rtic::pend(#device::#enum_::#interrupt);
)
@@ -118,12 +106,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
.collect::<Vec<_>>();
let priority = timer_queue.priority;
- let sys_tick = util::suffixed("SysTick", sender);
- let section = util::link_section("text", sender);
+ let sys_tick = util::suffixed("SysTick");
items.push(quote!(
#[no_mangle]
- #cfg_sender
- #section
unsafe fn #sys_tick() {
use rtic::Mutex as _;
@@ -137,7 +122,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
})
// NOTE `inline(always)` produces faster and smaller code
.lock(#[inline(always)]
- |tq| tq.dequeue())
+ |tq| tq.dequeue())
{
match task {
#(#arms)*
@@ -148,6 +133,5 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
));
}
}
-
items
}
diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs
index 68aca5d1..2f9f3cce 100644
--- a/macros/src/codegen/util.rs
+++ b/macros/src/codegen/util.rs
@@ -2,7 +2,7 @@ use core::sync::atomic::{AtomicUsize, Ordering};
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
-use rtic_syntax::{ast::App, Context, Core};
+use rtic_syntax::{ast::App, Context};
use syn::{Attribute, Ident, LitInt, PatType};
use crate::check::Extra;
@@ -25,34 +25,15 @@ pub fn capacity_typenum(capacity: u8, round_up_to_power_of_two: bool) -> TokenSt
quote!(rtic::export::consts::#ident)
}
-/// Generates a `#[cfg(core = "0")]` attribute if we are in multi-core mode
-pub fn cfg_core(core: Core, cores: u8) -> Option<TokenStream2> {
- if cores == 1 {
- None
- } else if cfg!(feature = "heterogeneous") {
- let core = core.to_string();
- Some(quote!(#[cfg(core = #core)]))
- } else {
- None
- }
-}
-
/// Identifier for the free queue
-///
-/// There may be more than one free queue per task because we need one for each sender core so we
-/// include the sender (e.g. `S0`) in the name
-pub fn fq_ident(task: &Ident, sender: Core) -> Ident {
- Ident::new(
- &format!("{}_S{}_FQ", task.to_string(), sender),
- Span::call_site(),
- )
+pub fn fq_ident(task: &Ident) -> Ident {
+ Ident::new(&format!("{}_FQ", task.to_string()), Span::call_site())
}
/// Generates a `Mutex` implementation
pub fn impl_mutex(
extra: &Extra,
cfgs: &[Attribute],
- cfg_core: Option<&TokenStream2>,
resources_prefix: bool,
name: &Ident,
ty: TokenStream2,
@@ -68,7 +49,6 @@ pub fn impl_mutex(
let device = extra.device;
quote!(
#(#cfgs)*
- #cfg_core
impl<'a> rtic::Mutex for #path<'a> {
type T = #ty;
@@ -91,28 +71,19 @@ pub fn impl_mutex(
)
}
-/// Generates an identifier for a cross-initialization barrier
-pub fn init_barrier(initializer: Core) -> Ident {
- Ident::new(&format!("IB{}", initializer), Span::call_site())
-}
-
/// Generates an identifier for the `INPUTS` buffer (`spawn` & `schedule` API)
-pub fn inputs_ident(task: &Ident, sender: Core) -> Ident {
- Ident::new(&format!("{}_S{}_INPUTS", task, sender), Span::call_site())
+pub fn inputs_ident(task: &Ident) -> Ident {
+ Ident::new(&format!("{}_INPUTS", task), Span::call_site())
}
/// Generates an identifier for the `INSTANTS` buffer (`schedule` API)
-pub fn instants_ident(task: &Ident, sender: Core) -> Ident {
- Ident::new(&format!("{}_S{}_INSTANTS", task, sender), Span::call_site())
+pub fn instants_ident(task: &Ident) -> Ident {
+ Ident::new(&format!("{}_INSTANTS", task), Span::call_site())
}
-pub fn interrupt_ident(core: Core, cores: u8) -> Ident {
+pub fn interrupt_ident() -> Ident {
let span = Span::call_site();
- if cores == 1 {
- Ident::new("Interrupt", span)
- } else {
- Ident::new(&format!("Interrupt_{}", core), span)
- }
+ Ident::new("Interrupt", span)
}
/// Whether `name` is an exception with configurable priority
@@ -141,31 +112,12 @@ fn link_section_index() -> usize {
INDEX.fetch_add(1, Ordering::Relaxed)
}
-pub fn link_section(section: &str, core: Core) -> Option<TokenStream2> {
- if cfg!(feature = "homogeneous") {
- let section = format!(".{}_{}.rtic{}", section, core, link_section_index());
- Some(quote!(#[link_section = #section]))
- } else {
- None
- }
-}
-
// NOTE `None` means in shared memory
-pub fn link_section_uninit(core: Option<Core>) -> Option<TokenStream2> {
- let section = if let Some(core) = core {
+pub fn link_section_uninit(empty_expr: bool) -> Option<TokenStream2> {
+ let section = if empty_expr {
let index = link_section_index();
-
- if cfg!(feature = "homogeneous") {
- format!(".uninit_{}.rtic{}", core, index)
- } else {
- format!(".uninit.rtic{}", index)
- }
+ format!(".uninit.rtic{}", index)
} else {
- if cfg!(feature = "heterogeneous") {
- // `#[shared]` attribute sets the linker section
- return None;
- }
-
format!(".uninit.rtic{}", link_section_index())
};
@@ -175,8 +127,8 @@ pub fn link_section_uninit(core: Option<Core>) -> Option<TokenStream2> {
/// Generates a pre-reexport identifier for the "locals" struct
pub fn locals_ident(ctxt: Context, app: &App) -> Ident {
let mut s = match ctxt {
- Context::Init(core) => app.inits[&core].name.to_string(),
- Context::Idle(core) => app.idles[&core].name.to_string(),
+ Context::Init => app.inits.first().unwrap().name.to_string(),
+ Context::Idle => app.idles.first().unwrap().name.to_string(),
Context::HardwareTask(ident) | Context::SoftwareTask(ident) => ident.to_string(),
};
@@ -185,11 +137,6 @@ pub fn locals_ident(ctxt: Context, app: &App) -> Ident {
Ident::new(&s, Span::call_site())
}
-/// Generates an identifier for a rendezvous barrier
-pub fn rendezvous_ident(core: Core) -> Ident {
- Ident::new(&format!("RV{}", core), Span::call_site())
-}
-
// Regroups the inputs of a task
//
// `inputs` could be &[`input: Foo`] OR &[`mut x: i32`, `ref y: i64`]
@@ -242,8 +189,8 @@ pub fn regroup_inputs(
/// Generates a pre-reexport identifier for the "resources" struct
pub fn resources_ident(ctxt: Context, app: &App) -> Ident {
let mut s = match ctxt {
- Context::Init(core) => app.inits[&core].name.to_string(),
- Context::Idle(core) => app.idles[&core].name.to_string(),
+ Context::Init => app.inits.first().unwrap().name.to_string(),
+ Context::Idle => app.idles.first().unwrap().name.to_string(),
Context::HardwareTask(ident) | Context::SoftwareTask(ident) => ident.to_string(),
};
@@ -254,72 +201,47 @@ pub fn resources_ident(ctxt: Context, app: &App) -> Ident {
/// Generates an identifier for a ready queue
///
-/// Each core may have several task dispatchers, one for each priority level. Each task dispatcher
-/// in turn may use more than one ready queue because the queues are SPSC queues so one is needed
-/// per sender core.
-pub fn rq_ident(receiver: Core, priority: u8, sender: Core) -> Ident {
- Ident::new(
- &format!("R{}_P{}_S{}_RQ", receiver, priority, sender),
- Span::call_site(),
- )
+/// There may be several task dispatchers, one for each priority level.
+/// The ready queues are SPSC queues
+pub fn rq_ident(priority: u8) -> Ident {
+ Ident::new(&format!("P{}_RQ", priority), Span::call_site())
}
/// Generates an identifier for a "schedule" function
///
-/// The methods of the `Schedule` structs invoke these functions. As one task may be `schedule`-ed
-/// by different cores we need one "schedule" function per possible task-sender pair
-pub fn schedule_ident(name: &Ident, sender: Core) -> Ident {
- Ident::new(
- &format!("schedule_{}_S{}", name.to_string(), sender),
- Span::call_site(),
- )
+/// The methods of the `Schedule` structs invoke these functions.
+pub fn schedule_ident(name: &Ident) -> Ident {
+ Ident::new(&format!("schedule_{}", name.to_string()), Span::call_site())
}
/// Generates an identifier for the `enum` of `schedule`-able tasks
-pub fn schedule_t_ident(core: Core) -> Ident {
- Ident::new(&format!("T{}", core), Span::call_site())
-}
-
-/// Generates an identifier for a cross-spawn barrier
-pub fn spawn_barrier(receiver: Core) -> Ident {
- Ident::new(&format!("SB{}", receiver), Span::call_site())
+pub fn schedule_t_ident() -> Ident {
+ Ident::new(&format!("T"), Span::call_site())
}
/// Generates an identifier for a "spawn" function
///
-/// The methods of the `Spawn` structs invoke these functions. As one task may be `spawn`-ed by
-/// different cores we need one "spawn" function per possible task-sender pair
-pub fn spawn_ident(name: &Ident, sender: Core) -> Ident {
- Ident::new(
- &format!("spawn_{}_S{}", name.to_string(), sender),
- Span::call_site(),
- )
+/// The methods of the `Spawn` structs invoke these functions.
+pub fn spawn_ident(name: &Ident) -> Ident {
+ Ident::new(&format!("spawn_{}", name.to_string()), Span::call_site())
}
/// Generates an identifier for the `enum` of `spawn`-able tasks
///
/// This identifier needs the same structure as the `RQ` identifier because there's one ready queue
/// for each of these `T` enums
-pub fn spawn_t_ident(receiver: Core, priority: u8, sender: Core) -> Ident {
- Ident::new(
- &format!("R{}_P{}_S{}_T", receiver, priority, sender),
- Span::call_site(),
- )
+pub fn spawn_t_ident(priority: u8) -> Ident {
+ Ident::new(&format!("P{}_T", priority), Span::call_site())
}
-pub fn suffixed(name: &str, core: u8) -> Ident {
+pub fn suffixed(name: &str) -> Ident {
let span = Span::call_site();
-
- if cfg!(feature = "homogeneous") {
- Ident::new(&format!("{}_{}", name, core), span)
- } else {
- Ident::new(name, span)
- }
+ Ident::new(name, span)
}
/// Generates an identifier for a timer queue
///
-/// At most there's one timer queue per core
-pub fn tq_ident(core: Core) -> Ident {
- Ident::new(&format!("TQ{}", core), Span::call_site())
+/// At most there is one timer queue
+pub fn tq_ident() -> Ident {
+ Ident::new(&format!("TQ"), Span::call_site())
}