From 76cf14c520091d00985f845203580e14c611ed14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Thu, 27 Aug 2020 11:21:56 +0000 Subject: [PATCH 1/8] Brutally yank out multicore --- Cargo.toml | 4 - macros/Cargo.toml | 5 +- macros/src/analyze.rs | 20 +- macros/src/check.rs | 110 ++++----- macros/src/codegen-verbose.rs | 226 +++++++++++++++++++ macros/src/codegen.rs | 91 +++----- macros/src/codegen/assertions.rs | 18 +- macros/src/codegen/dispatchers.rs | 300 +++++++++++-------------- macros/src/codegen/hardware_tasks.rs | 18 +- macros/src/codegen/idle.rs | 15 +- macros/src/codegen/init.rs | 23 +- macros/src/codegen/locals.rs | 7 +- macros/src/codegen/module.rs | 30 +-- macros/src/codegen/post_init.rs | 21 +- macros/src/codegen/pre_init.rs | 58 ++--- macros/src/codegen/resources.rs | 39 ++-- macros/src/codegen/resources_struct.rs | 9 +- macros/src/codegen/schedule.rs | 15 +- macros/src/codegen/schedule_body.rs | 14 +- macros/src/codegen/software_tasks.rs | 144 +++++------- macros/src/codegen/spawn.rs | 25 +-- macros/src/codegen/spawn_body.rs | 25 +-- macros/src/codegen/timer_queue.rs | 46 ++-- macros/src/codegen/util.rs | 102 ++++----- macros/src/lib.rs | 2 +- macros/src/tests.rs | 1 - macros/src/tests/multi.rs | 59 ----- macros/src/tests/single.rs | 2 +- src/export.rs | 11 +- src/lib.rs | 3 - 30 files changed, 704 insertions(+), 739 deletions(-) create mode 100644 macros/src/codegen-verbose.rs delete mode 100644 macros/src/tests/multi.rs diff --git a/Cargo.toml b/Cargo.toml index d956113951..f7567a1018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,8 +77,6 @@ version = "0.5.2" trybuild = "1" [features] -heterogeneous = ["cortex-m-rtic-macros/heterogeneous", "microamp"] -homogeneous = ["cortex-m-rtic-macros/homogeneous"] # used for testing this crate; do not use in applications __v7 =[] __min_r1_43 =[] @@ -89,8 +87,6 @@ lto = true [workspace] members = [ - "heterogeneous", - "homogeneous", "macros", ] diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 0a38d08b53..e1dbce9993 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,8 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = "0.4.0" +rtic-syntax = { git = "https://github.com/AfoHT/rtic-syntax", branch = "multiremove", version = "0.4.0" } -[features] -heterogeneous = [] -homogeneous = [] diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index af6811fa4d..c81c186d5d 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -4,14 +4,14 @@ use std::collections::{BTreeMap, BTreeSet}; use rtic_syntax::{ analyze::{self, Priority}, ast::App, - Core, P, + P, }; use syn::Ident; /// Extend the upstream `Analysis` struct with our field pub struct Analysis { parent: P, - pub interrupts: BTreeMap>, + pub interrupts: BTreeMap, } impl ops::Deref for Analysis { @@ -25,32 +25,24 @@ impl ops::Deref for Analysis { // Assign an `extern` interrupt to each priority level pub fn app(analysis: P, app: &App) -> P { let mut interrupts = BTreeMap::new(); - for core in 0..app.args.cores { let priorities = app .software_tasks .values() .filter_map(|task| { - if task.args.core == core { Some(task.args.priority) - } else { - None - } }) - .chain(analysis.timer_queues.get(&core).map(|tq| tq.priority)) + .chain(analysis.timer_queues.first().map(|tq| tq.priority)) .collect::>(); if !priorities.is_empty() { - interrupts.insert( - core, + interrupts = priorities .iter() .cloned() .rev() - .zip(app.extern_interrupts[&core].keys().cloned()) - .collect(), - ); + .zip(app.extern_interrupts.keys().cloned()) + .collect(); } - } P::new(Analysis { parent: analysis, diff --git a/macros/src/check.rs b/macros/src/check.rs index 71634446de..0bc475e579 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -4,13 +4,14 @@ use proc_macro2::Span; use rtic_syntax::{ analyze::Analysis, ast::{App, CustomArg}, + }; use syn::{parse, Path}; pub struct Extra<'a> { pub device: &'a Path, pub monotonic: Option<&'a Path>, - pub peripherals: Option, + pub peripherals: bool, } impl<'a> Extra<'a> { @@ -20,35 +21,14 @@ impl<'a> Extra<'a> { } pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { - if cfg!(feature = "homogeneous") { - // this RTIC mode uses the same namespace for all cores so we need to check that the - // identifiers used for each core `#[init]` and `#[idle]` functions don't collide - let mut seen = HashSet::new(); - - for name in app - .inits - .values() - .map(|init| &init.name) - .chain(app.idles.values().map(|idle| &idle.name)) - { - if seen.contains(name) { - return Err(parse::Error::new( - name.span(), - "this identifier is already being used by another core", - )); - } else { - seen.insert(name); - } - } - } - // check that all exceptions are valid; only exceptions with configurable priorities are // accepted for (name, task) in &app.hardware_tasks { let name_s = task.args.binds.to_string(); match &*name_s { "SysTick" => { - if analysis.timer_queues.get(&task.args.core).is_some() { + // If the timer queue is used, then SysTick is unavailable + if !analysis.timer_queues.is_empty() { return Err(parse::Error::new( name.span(), "this exception can't be used because it's being used by the runtime", @@ -72,9 +52,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { // check that external (device-specific) interrupts are not named after known (Cortex-M) // exceptions for name in app - .extern_interrupts - .iter() - .flat_map(|(_, interrupts)| interrupts.keys()) + .extern_interrupts.keys() { let name_s = name.to_string(); @@ -93,50 +71,38 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { // check that there are enough external interrupts to dispatch the software tasks and the timer // queue handler - for core in 0..app.args.cores { - let mut first = None; - let priorities = app - .software_tasks - .iter() - .filter_map(|(name, task)| { - if task.args.core == core { - first = Some(name); - Some(task.args.priority) - } else { - None - } - }) - .chain(analysis.timer_queues.get(&core).map(|tq| tq.priority)) - .collect::>(); + let mut first = None; + let priorities = app + .software_tasks + .iter() + .filter_map(|(name, task)| { + first = Some(name); + Some(task.args.priority) + }) + .chain(analysis.timer_queues.first().map(|tq| tq.priority)) + .collect::>(); - let need = priorities.len(); - let given = app - .extern_interrupts - .get(&core) - .map(|ei| ei.len()) - .unwrap_or(0); - if need > given { - let s = if app.args.cores == 1 { - format!( - "not enough `extern` interrupts to dispatch \ - all software tasks (need: {}; given: {})", - need, given - ) - } else { - format!( - "not enough `extern` interrupts to dispatch \ - all software tasks on this core (need: {}; given: {})", - need, given - ) - }; + let need = priorities.len(); + let given = app + .extern_interrupts.len(); + if need > given { + let s = { + format!( + "not enough `extern` interrupts to dispatch \ + all software tasks (need: {}; given: {})", + need, given + ) + }; - return Err(parse::Error::new(first.unwrap().span(), &s)); - } + // If not enough tasks and first still is None, may cause + // "custom attribute panicked" + // unwrap on None + return Err(parse::Error::new(first.unwrap().span(), &s)); } let mut device = None; let mut monotonic = None; - let mut peripherals = None; + let mut peripherals = false; for (k, v) in &app.args.custom { let ks = k.to_string(); @@ -165,10 +131,11 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { }, "peripherals" => match v { - CustomArg::Bool(x) if app.args.cores == 1 => { - peripherals = if *x { Some(0) } else { None } + CustomArg::Bool(x) => { + peripherals = if *x { true } else { false } } + /* CustomArg::UInt(s) if app.args.cores != 1 => { let x = s.parse::().ok(); peripherals = if x.is_some() && x.unwrap() < app.args.cores { @@ -184,15 +151,18 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { )); } } + */ _ => { return Err(parse::Error::new( k.span(), - if app.args.cores == 1 { - "unexpected argument value; this should be a boolean" + //if app.args.cores == 1 { + "unexpected argument value; this should be a boolean", + /* } else { "unexpected argument value; this should be an integer" }, + */ )); } }, @@ -203,7 +173,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { } } - if !analysis.timer_queues.is_empty() && monotonic.is_none() { + if !&analysis.timer_queues.is_empty() && monotonic.is_none() { return Err(parse::Error::new( Span::call_site(), "a `monotonic` timer must be specified to use the `schedule` API", diff --git a/macros/src/codegen-verbose.rs b/macros/src/codegen-verbose.rs new file mode 100644 index 0000000000..2b71cf5cd0 --- /dev/null +++ b/macros/src/codegen-verbose.rs @@ -0,0 +1,226 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use rtic_syntax::ast::App; + +use crate::{analyze::Analysis, check::Extra}; + +mod assertions; +mod dispatchers; +mod hardware_tasks; +mod idle; +mod init; +mod locals; +mod module; +mod post_init; +mod pre_init; +mod resources; +mod resources_struct; +mod schedule; +mod schedule_body; +mod software_tasks; +mod spawn; +mod spawn_body; +mod timer_queue; +mod util; + +// TODO document the syntax here or in `rtic-syntax` +pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { + let mut const_app = vec![]; + let mut mains = vec![]; + let mut root = vec![]; + let mut user = vec![]; + let mut imports = vec![]; + + // generate a `main` function for each core + for core in 0..app.args.cores { + let assertion_stmts = assertions::codegen(core, analysis, extra); + + let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra); + + let (const_app_init, _root_init, user_init, user_init_imports, call_init) = + init::codegen(core, app, analysis, extra); + + let (const_app_post_init, post_init_stmts) = + post_init::codegen(core, &app, analysis, extra); + + let (const_app_idle, _root_idle, user_idle, user_idle_imports, call_idle) = + idle::codegen(core, app, analysis, extra); + + user.push(quote!( + /// USER INIT + #user_init + + /// USER IDLE + #user_idle + )); + + // Stow away the imports generated for each core + imports.push(quote!( + /// USER IMPORTS + #(#user_init_imports)* + + /// USER IDLE + #(#user_idle_imports)* + )); + + root.push(quote!( + #(#_root_init)* + + #(#_root_idle)* + )); + + const_app.push(quote!( + #(#const_app_pre_init)* + + #const_app_init + + #(#const_app_post_init)* + + #const_app_idle + )); + + let cfg_core = util::cfg_core(core, app.args.cores); + let main = util::suffixed("main", core); + let section = util::link_section("text", core); + mains.push(quote!( + #[no_mangle] + #section + #cfg_core + unsafe extern "C" fn #main() -> ! { + #(#assertion_stmts)* + + #(#pre_init_stmts)* + + #call_init + + #(#post_init_stmts)* + + #call_idle + } + )); + } + + let (const_app_resources, mod_resources, mod_resources_imports) = + resources::codegen(app, analysis, extra); + + let ( + const_app_hardware_tasks, + root_hardware_tasks, + user_hardware_tasks, + user_hardware_tasks_imports, + ) = hardware_tasks::codegen(app, analysis, extra); + + let ( + const_app_software_tasks, + root_software_tasks, + user_software_tasks, + user_software_tasks_imports, + ) = software_tasks::codegen(app, analysis, extra); + + let const_app_dispatchers = dispatchers::codegen(app, analysis, extra); + + let const_app_spawn = spawn::codegen(app, analysis, extra); + + let const_app_timer_queue = timer_queue::codegen(app, analysis, extra); + + let const_app_schedule = schedule::codegen(app, extra); + + let cores = app.args.cores.to_string(); + let cfg_core = quote!(#[cfg(core = #cores)]); + let msg = format!( + "specified {} core{} but tried to compile for more than {0} core{1}", + app.args.cores, + if app.args.cores > 1 { "s" } else { "" } + ); + let check_excess_cores = quote!( + #cfg_core + compile_error!(#msg); + ); + + /* + for s in root.clone() { + println!("{}", s.to_string()); + } + */ + + let user_imports = app.user_imports.clone(); + let user_code = app.user_code.clone(); + let name = &app.name; + let device = extra.device; + let endresult = quote!( + /// USER + #(#user)* + + /// USER_HW_TASKS + #(#user_hardware_tasks)* + + /// USER_SW_TASKS + #(#user_software_tasks)* + + /// ROOT + //#(#root)* + + /// MOD_RESOURCES + #mod_resources + + /// root_hardware_tasks + #(#root_hardware_tasks)* + + /// root_software_tasks + #(#root_software_tasks)* + + /// Implementation details + mod #name { + /// Always include the device crate which contains the vector table + use #device as _; + #(#imports)* + /// User imports + #(#user_imports)* + + /// User code from within the module + #(#user_code)* + + /// User hardware tasks import + #(#user_hardware_tasks_imports)* + + /// User software_tasks + #(#user_software_tasks_imports)* + + /// Mod resources imports + #(#mod_resources_imports)* + + #check_excess_cores + + /// Const app + #(#const_app)* + + /// Const app resources + #(#const_app_resources)* + + /// Const app hw tasks + #(#const_app_hardware_tasks)* + + /// Const app sw tasks + #(#const_app_software_tasks)* + + /// Const app dispatchers + #(#const_app_dispatchers)* + + /// Const app spawn + #(#const_app_spawn)* + /// Const app spawn end + + #(#const_app_timer_queue)* + + #(#const_app_schedule)* + + /// Mains + #(#mains)* + } + ); + for s in endresult.clone() { + eprintln!("{}", s.to_string()); + } + + endresult +} diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 2433684cfb..73531c9b83 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -30,65 +30,60 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let mut root = vec![]; let mut user = vec![]; - // generate a `main` function for each core - for core in 0..app.args.cores { - let assertion_stmts = assertions::codegen(core, analysis, extra); + // generate the `main` function + let assertion_stmts = assertions::codegen(analysis); - let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra); + let pre_init_stmts = pre_init::codegen(&app, analysis, extra); - let (const_app_init, root_init, user_init, call_init) = - init::codegen(core, app, analysis, extra); + let (const_app_init, root_init, user_init, call_init) = + init::codegen(app, analysis, extra); - let (const_app_post_init, post_init_stmts) = - post_init::codegen(core, &app, analysis, extra); + let (const_app_post_init, post_init_stmts) = + post_init::codegen(&app, analysis); - let (const_app_idle, root_idle, user_idle, call_idle) = - idle::codegen(core, app, analysis, extra); + let (const_app_idle, root_idle, user_idle, call_idle) = + idle::codegen(app, analysis, extra); - user.push(quote!( - #user_init + user.push(quote!( + #user_init - #user_idle - )); + #user_idle + )); - root.push(quote!( - #(#root_init)* + root.push(quote!( + #(#root_init)* - #(#root_idle)* - )); + #(#root_idle)* + )); - const_app.push(quote!( - #(#const_app_pre_init)* + const_app.push(quote!( + #const_app_init - #const_app_init + #(#const_app_post_init)* - #(#const_app_post_init)* + #const_app_idle + )); - #const_app_idle - )); + let main = util::suffixed("main"); + let section = util::link_section("text"); + mains.push(quote!( + #[no_mangle] + #section + unsafe extern "C" fn #main() -> ! { + let _TODO: () = (); - let cfg_core = util::cfg_core(core, app.args.cores); - let main = util::suffixed("main", core); - let section = util::link_section("text", core); - mains.push(quote!( - #[no_mangle] - #section - #cfg_core - unsafe extern "C" fn #main() -> ! { - let _TODO: () = (); + #(#assertion_stmts)* - #(#assertion_stmts)* + #(#pre_init_stmts)* - #(#pre_init_stmts)* + #call_init - #call_init + #(#post_init_stmts)* - #(#post_init_stmts)* + #call_idle + } + )); - #call_idle - } - )); - } let (const_app_resources, mod_resources) = resources::codegen(app, analysis, extra); @@ -106,18 +101,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let const_app_schedule = schedule::codegen(app, extra); - let cores = app.args.cores.to_string(); - let cfg_core = quote!(#[cfg(core = #cores)]); - let msg = format!( - "specified {} core{} but tried to compile for more than {0} core{1}", - app.args.cores, - if app.args.cores > 1 { "s" } else { "" } - ); - let check_excess_cores = quote!( - #cfg_core - compile_error!(#msg); - ); - let name = &app.name; let device = extra.device; quote!( @@ -141,8 +124,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { /// Always include the device crate which contains the vector table use #device as _; - #check_excess_cores - #(#const_app)* #(#const_app_resources)* diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs index 51bbdbff30..a7c26a5ecf 100644 --- a/macros/src/codegen/assertions.rs +++ b/macros/src/codegen/assertions.rs @@ -1,33 +1,35 @@ 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 { +pub fn codegen(analysis: &Analysis) -> Vec { 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 { + //if let Some(types) = analysis.send_types { + for ty in &analysis.send_types { stmts.push(quote!(rtic::export::assert_send::<#ty>();)); } - } + //} - if let Some(types) = analysis.sync_types.get(&core) { - for ty in types { + //if let Some(types) = analysis.sync_types { + for ty in &analysis.sync_types { stmts.push(quote!(rtic::export::assert_sync::<#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>();)); } + */ stmts } diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 60b8626e38..fdeb615534 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -8,181 +8,151 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { let mut items = vec![]; - for (&receiver, dispatchers) in &analysis.channels { - let interrupts = &analysis.interrupts[&receiver]; + let interrupts = &analysis.interrupts; - for (&level, channels) in dispatchers { - let mut stmts = vec![]; + for (&level, channel) in &analysis.channels { + let mut stmts = vec![]; - for (&sender, channel) in channels { - let cfg_sender = util::cfg_core(sender, app.args.cores); + let variants = channel + .tasks + .iter() + .map(|name| { + let cfgs = &app.software_tasks[name].cfgs; - let variants = channel - .tasks - .iter() - .map(|name| { - let cfgs = &app.software_tasks[name].cfgs; + quote!( + #(#cfgs)* + #name + ) + }) + .collect::>(); - quote!( - #(#cfgs)* - #name - ) - }) - .collect::>(); - - 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), - ) - } 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, - ) - }; - - 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(),) - }; - - 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::>(); - - stmts.push(quote!( - while let Some((task, index)) = #rq.split().1.dequeue() { - match task { - #(#arms)* - } - } - )); + 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 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); + let n = util::capacity_typenum(channel.capacity, true); + let rq = util::rq_ident(level); + let (rq_ty, rq_expr, section) = { + ( + quote!(rtic::export::SCRQ<#t, #n>), + quote!(rtic::export::Queue(unsafe { + rtic::export::iQueue::u8_sc() + })), + util::link_section("bss"), + ) + }; + + let doc = format!( + "Queue of tasks ready to be dispatched at priority level {}", + level + ); + items.push(quote!( + #[doc = #doc] + #section + static mut #rq: #rq_ty = #rq_expr; + )); + + if let Some(ceiling) = channel.ceiling { 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)* - }); + struct #rq<'a> { + priority: &'a rtic::export::Priority, } )); + + items.push(util::impl_mutex( + extra, + &[], + 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); + let inputs = util::inputs_ident(name); + let (_, tupled, pats, _) = util::regroup_inputs(&task.inputs); + + let (let_instant, instant) = if app.uses_schedule() { + let instants = util::instants_ident(name); + + ( + 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(),) + }; + + 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::>(); + + 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 section = util::link_section("text"); + let interrupt = util::suffixed(&interrupts[&level].to_string()); + items.push(quote!( + #[allow(non_snake_case)] + #[doc = #doc] + #[no_mangle] + #section + 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 453dbccb00..37df33de81 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -29,10 +29,8 @@ pub fn codegen( let mut user_tasks = 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 +47,14 @@ 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); + let section = util::link_section("text"); const_app.push(quote!( #[allow(non_snake_case)] #[no_mangle] #section - #cfg_core unsafe fn #symbol() { const PRIORITY: u8 = #priority; @@ -104,7 +97,7 @@ pub fn codegen( let mut locals_pat = None; if !task.locals.is_empty() { let (struct_, pat) = - locals::codegen(Context::HardwareTask(name), &task.locals, core, app); + locals::codegen(Context::HardwareTask(name), &task.locals, app); root.push(struct_); locals_pat = Some(pat); @@ -113,8 +106,7 @@ 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 section = util::link_section("text"); let locals_pat = locals_pat.iter(); user_tasks.push(quote!( #(#attrs)* diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs index 032c8ade43..853372db1d 100644 --- a/macros/src/codegen/idle.rs +++ b/macros/src/codegen/idle.rs @@ -10,7 +10,6 @@ use crate::{ /// Generates support code for `#[idle]` functions pub fn codegen( - core: u8, app: &App, analysis: &Analysis, extra: &Extra, @@ -27,7 +26,9 @@ pub fn codegen( // call_idle TokenStream2, ) { - if let Some(idle) = app.idles.get(&core) { + //if let Some(idle) = app.idles.get(&core) { + if app.idles.len() > 0 { + let idle = &app.idles[0]; let mut needs_lt = false; let mut const_app = None; let mut root_idle = vec![]; @@ -36,7 +37,7 @@ pub fn codegen( 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); @@ -44,25 +45,23 @@ pub fn codegen( 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 section = util::link_section("text"); 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 _; diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index fa273fee86..4ae9fa624d 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -10,7 +10,6 @@ use crate::{ /// Generates support code for `#[init]` functions pub fn codegen( - core: u8, app: &App, analysis: &Analysis, extra: &Extra, @@ -28,8 +27,9 @@ pub fn codegen( // call_init -- the call to the user `#[init]` if there's one Option, ) { - if let Some(init) = app.inits.get(&core) { - let cfg_core = util::cfg_core(core, app.args.cores); + //if let Some(init) = app.inits.get(&core) { + if app.inits.len() > 0 { + let init = &app.inits[0]; let mut needs_lt = false; let name = &init.name; @@ -38,8 +38,8 @@ pub fn codegen( let ret = { let late_fields = analysis .late_resources - .get(&core) - .map(|resources| { + .iter() + .flat_map(|resources| { resources .iter() .map(|name| { @@ -51,16 +51,14 @@ pub fn codegen( pub #name: #ty ) }) - .collect::>() }) - .unwrap_or(vec![]); + .collect::>(); if !late_fields.is_empty() { 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),* @@ -76,7 +74,7 @@ pub fn codegen( 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,11 +84,10 @@ pub fn codegen( let context = &init.context; let attrs = &init.attrs; let stmts = &init.stmts; - let section = util::link_section("text", core); + let section = util::link_section("text"); 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 { @@ -101,7 +98,7 @@ pub fn codegen( let mut const_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); @@ -112,7 +109,7 @@ 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) } else { diff --git a/macros/src/codegen/locals.rs b/macros/src/codegen/locals.rs index 127f4b09e7..b3c593a2b2 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, - core: Core, app: &App, ) -> ( // locals @@ -42,11 +41,13 @@ 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 +56,7 @@ pub fn codegen( )); items.push(quote!( #(#cfgs)* - #section + //#section static mut #name: #ty = #expr )); values.push(quote!( diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index 1b21209f7f..ad20f1393e 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -11,12 +11,12 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> let name = ctxt.ident(app); - let core = ctxt.core(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 +37,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!( @@ -51,10 +51,10 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> 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 +69,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 +205,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,8 +252,8 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> } } - if let Context::Init(core) = ctxt { - let init = &app.inits[&core]; + if let Context::Init = ctxt { + let init = &app.inits[0]; if init.returns_late_resources { let late_resources = util::late_resources_ident(&init.name); @@ -265,14 +265,14 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> } 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 +312,12 @@ 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); + //let cfg_core = util::cfg_core(ctxt.core(app), app.args.cores); quote!( #[allow(non_snake_case)] #[doc = #doc] - #cfg_core + //#cfg_core pub mod #name { #(#items)* } diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs index 0c740e85ff..098d1cc9ab 100644 --- a/macros/src/codegen/post_init.rs +++ b/macros/src/codegen/post_init.rs @@ -2,21 +2,24 @@ 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, Vec) { - let mut const_app = vec![]; + //#TODO remove + let const_app = vec![]; let mut stmts = vec![]; // initialize late resources - if let Some(late_resources) = analysis.late_resources.get(&core) { - for name in late_resources { + //if let Some(late_resources) = analysis.late_resources { + //for name in late_resources { + if analysis.late_resources.len() > 0 { + // #TODO, check soundness of this, why the wrapping + // BTreeSet wrapped in a vector + for name in &analysis.late_resources[0] { // if it's live let cfgs = app.late_resources[name].cfgs.clone(); if analysis.locations.get(name).is_some() { @@ -29,7 +32,9 @@ 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 { @@ -55,7 +60,9 @@ pub fn codegen( #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); @@ -75,6 +82,7 @@ pub fn codegen( )); } } + */ } 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 @@ -154,6 +162,7 @@ pub fn codegen( } } } + */ // enable the interrupts -- this completes the `init`-ialization phase stmts.push(quote!(rtic::export::interrupt::enable();)); diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index f89dec9667..7b57739037 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -6,60 +6,44 @@ 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, +) -> // `pre_init_stmts` - Vec, -) { - let mut const_app = vec![]; + Vec +{ let mut stmts = vec![]; // 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 mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().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 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)) @@ -73,7 +57,7 @@ pub fn codegen( 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, @@ -88,6 +72,7 @@ pub fn codegen( // 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") { @@ -108,6 +93,7 @@ pub fn codegen( #sb.release(); )); } + */ // set exception priorities for (name, priority) in app.hardware_tasks.values().filter_map(|task| { @@ -126,8 +112,8 @@ 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 @@ -146,11 +132,12 @@ pub fn codegen( } // if there's no user `#[idle]` then optimize returning from interrupt handlers - if app.idles.get(&core).is_none() { + 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` @@ -162,6 +149,7 @@ pub fn codegen( )); } } + */ - (const_app, stmts) + stmts } diff --git a/macros/src/codegen/resources.rs b/macros/src/codegen/resources.rs index 0bec3e5ae6..07e01cb1eb 100644 --- a/macros/src/codegen/resources.rs +++ b/macros/src/codegen/resources.rs @@ -1,7 +1,7 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use rtic_syntax::{ - analyze::{Location, Ownership}, + analyze::Ownership, ast::App, }; @@ -21,38 +21,29 @@ pub fn codegen( let mut const_app = vec![]; let mut mod_resources = 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])) + //let loc_attr = None; + let section = if expr.is_none() { + util::link_section_uninit(true) } else { None - }, + }; + /* + let (loc_attr, section) = match loc { + Location::Owned => ( + None, if expr.is_none() { - util::link_section_uninit(None) + util::link_section_uninit(true) } else { None }, ), }; + */ let (ty, expr) = if let Some(expr) = expr { (quote!(#ty), quote!(#expr)) @@ -68,25 +59,22 @@ pub fn codegen( #[allow(non_upper_case_globals)] #(#attrs)* #(#cfgs)* - #loc_attr + //#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 { @@ -115,7 +103,6 @@ pub fn codegen( const_app.push(util::impl_mutex( extra, cfgs, - cfg_core.as_ref(), true, name, quote!(#ty), diff --git a/macros/src/codegen/resources_struct.rs b/macros/src/codegen/resources_struct.rs index 994e751c8d..bd92a59916 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[0].args.resources, + Context::Idle => &app.idles[0].args.resources, Context::HardwareTask(name) => &app.hardware_tasks[name].args.resources, Context::SoftwareTask(name) => &app.software_tasks[name].args.resources, }; @@ -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,7 +163,6 @@ 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 { diff --git a/macros/src/codegen/schedule.rs b/macros/src/codegen/schedule.rs index 728d3a0933..b6cb6b9aa4 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 { let mut items = vec![]; - let mut seen = BTreeMap::>::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,7 +32,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { let body = schedule_body::codegen(scheduler, &name, app); - let section = util::link_section("text", sender); + let section = util::link_section("text"); methods.push(quote!( #(#cfgs)* #section @@ -44,7 +41,7 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { } )); } 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 @@ -52,9 +49,8 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { let body = schedule_body::codegen(scheduler, &name, app); - let section = util::link_section("text", sender); + let section = util::link_section("text"); items.push(quote!( - #cfg_sender #(#cfgs)* #section unsafe fn #schedule( @@ -88,7 +84,6 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { 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 8fd026c215..644930d7d7 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 14a57633ea..25662801a6 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -28,8 +28,6 @@ pub fn codegen( let mut user_tasks = vec![]; for (name, task) in &app.software_tasks { - let receiver = task.args.core; - let inputs = &task.inputs; let (_, _, _, input_ty) = util::regroup_inputs(inputs); @@ -38,102 +36,73 @@ pub fn codegen( 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); + //if let Some(free_queues) = analysis.free_queues.get(name) { + //for (&sender, &ceiling) in free_queues { + if let Some(&ceiling) = analysis.free_queues.get(name) { + let fq = util::fq_ident(name); - let (loc, fq_ty, fq_expr, bss, mk_uninit): ( - _, - _, - _, - _, - Box 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; + let (fq_ty, fq_expr, bss, mk_uninit): (_, _, _, Box Option<_>>) = { + ( + quote!(rtic::export::SCFQ<#cap_ty>), + quote!(rtic::export::Queue(unsafe { + rtic::export::iQueue::u8_sc() + })), + util::link_section("bss"), + Box::new(|| util::link_section_uninit(true)), + ) + }; + const_app.push(quote!( + /// Queue version of a free-list that keeps track of empty slots in + /// the following buffers + #bss + static mut #fq: #fq_ty = #fq_expr; + )); + // Generate a resource proxy if needed + if let Some(ceiling) = ceiling { 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; + struct #fq<'a> { + priority: &'a rtic::export::Priority, + } )); - // 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, + &[], + false, + &fq, + fq_ty, + ceiling, + quote!(&mut #fq), + )); + } - 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::>(); - let ref elems = (0..cap) - .map(|_| quote!(core::mem::MaybeUninit::uninit())) - .collect::>(); - - 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 #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); + const_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` @@ -155,15 +124,13 @@ pub fn codegen( // `${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 section = util::link_section("text"); let context = &task.context; let attrs = &task.attrs; let cfgs = &task.cfgs; @@ -173,7 +140,6 @@ pub fn codegen( #(#attrs)* #(#cfgs)* #[allow(non_snake_case)] - #cfg_receiver #section fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) { use rtic::Mutex as _; diff --git a/macros/src/codegen/spawn.rs b/macros/src/codegen/spawn.rs index 287c92a1cc..6cad809b5b 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,13 @@ use crate::{ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { let mut items = vec![]; - let mut seen = BTreeMap::>::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 receiver = spawnee.args.core; let cfgs = &spawnee.cfgs; let (args, _, untupled, ty) = util::regroup_inputs(&spawnee.inputs); let args = &args; @@ -34,7 +31,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec::zero() };)) @@ -42,7 +39,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec::Instant)) @@ -68,9 +65,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Vec #spawner::Spawn<#lt> { #(#methods)* } diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs index 3433875e90..3c2e8a0392 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,15 @@ 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 { - quote!( + 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 56304001e0..41f5520ec9 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -8,9 +8,9 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { 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 cfg_sender = util::cfg_core(sender, app.args.cores); + let t = util::schedule_t_ident(); // Enumeration of `schedule`-able tasks { @@ -27,9 +27,9 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> 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 + //#cfg_sender #[doc = #doc] #[allow(non_camel_case_types)] #[derive(Clone, Copy)] @@ -39,18 +39,18 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec); - let section = util::link_section("bss", sender); + let section = util::link_section("bss"); items.push(quote!( - #cfg_sender + //#cfg_sender #[doc = #doc] #section static mut #tq: #tq_ty = rtic::export::TimerQueue( @@ -59,7 +59,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { priority: &'a rtic::export::Priority, } @@ -68,7 +68,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec 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"); + let section = util::link_section("text"); items.push(quote!( #[no_mangle] - #cfg_sender + //#cfg_sender #section unsafe fn #sys_tick() { use rtic::Mutex as _; @@ -137,7 +132,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec 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 { if cores == 1 { @@ -36,14 +37,15 @@ pub fn cfg_core(core: Core, cores: u8) -> Option { 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 { +pub fn fq_ident(task: &Ident) -> Ident { Ident::new( - &format!("{}_S{}_FQ", task.to_string(), sender), + &format!("{}_FQ", task.to_string()), Span::call_site(), ) } @@ -52,7 +54,7 @@ pub fn fq_ident(task: &Ident, sender: Core) -> Ident { pub fn impl_mutex( extra: &Extra, cfgs: &[Attribute], - cfg_core: Option<&TokenStream2>, + //cfg_core: Option<&TokenStream2>, resources_prefix: bool, name: &Ident, ty: TokenStream2, @@ -68,7 +70,7 @@ pub fn impl_mutex( let device = extra.device; quote!( #(#cfgs)* - #cfg_core + //#cfg_core impl<'a> rtic::Mutex for #path<'a> { type T = #ty; @@ -91,28 +93,26 @@ 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) - } } /// Whether `name` is an exception with configurable priority @@ -141,31 +141,24 @@ fn link_section_index() -> usize { INDEX.fetch_add(1, Ordering::Relaxed) } -pub fn link_section(section: &str, core: Core) -> Option { +pub fn link_section(_section: &str) -> Option { + /* if cfg!(feature = "homogeneous") { let section = format!(".{}_{}.rtic{}", section, core, link_section_index()); Some(quote!(#[link_section = #section])) } else { None } + */ + None } // NOTE `None` means in shared memory -pub fn link_section_uninit(core: Option) -> Option { - let section = if let Some(core) = core { +pub fn link_section_uninit(empty_expr: bool) -> Option { + 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 +168,8 @@ pub fn link_section_uninit(core: Option) -> Option { /// 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[0].name.to_string(), + Context::Idle => app.idles[0].name.to_string(), Context::HardwareTask(ident) | Context::SoftwareTask(ident) => ident.to_string(), }; @@ -185,10 +178,12 @@ 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()) +pub fn rendezvous_ident() -> Ident { + Ident::new(&format!("RV"), Span::call_site()) } +*/ // Regroups the inputs of a task // @@ -242,8 +237,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[0].name.to_string(), + Context::Idle => app.idles[0].name.to_string(), Context::HardwareTask(ident) | Context::SoftwareTask(ident) => ident.to_string(), }; @@ -257,9 +252,9 @@ pub fn resources_ident(ctxt: Context, app: &App) -> Ident { /// 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 { +pub fn rq_ident(priority: u8) -> Ident { Ident::new( - &format!("R{}_P{}_S{}_RQ", receiver, priority, sender), + &format!("P{}_RQ", priority), Span::call_site(), ) } @@ -268,30 +263,32 @@ pub fn rq_ident(receiver: Core, priority: u8, sender: Core) -> Ident { /// /// 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 { +pub fn schedule_ident(name: &Ident) -> Ident { Ident::new( - &format!("schedule_{}_S{}", name.to_string(), sender), + &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()) +pub fn schedule_t_ident() -> Ident { + Ident::new(&format!("T"), 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 spawn_barrier() -> Ident { + Ident::new(&format!("SB"), 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 { +pub fn spawn_ident(name: &Ident) -> Ident { Ident::new( - &format!("spawn_{}_S{}", name.to_string(), sender), + &format!("spawn_{}", name.to_string()), Span::call_site(), ) } @@ -300,26 +297,21 @@ pub fn spawn_ident(name: &Ident, sender: Core) -> Ident { /// /// 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 { +pub fn spawn_t_ident(priority: u8) -> Ident { Ident::new( - &format!("R{}_P{}_S{}_T", receiver, priority, sender), + &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()) +pub fn tq_ident() -> Ident { + Ident::new(&format!("TQ"), Span::call_site()) } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index b580362860..7b72c7fb13 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -201,12 +201,12 @@ mod tests; /// /// Attributes can be applied to the functions inside this block. These attributes will be forwarded /// to the interrupt handlers generated by the `app` attribute. + #[proc_macro_attribute] pub fn app(args: TokenStream, input: TokenStream) -> TokenStream { let mut settings = Settings::default(); settings.optimize_priorities = true; settings.parse_binds = true; - settings.parse_cores = cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous"); settings.parse_extern_interrupt = true; settings.parse_schedule = true; diff --git a/macros/src/tests.rs b/macros/src/tests.rs index 94969d1af7..e9e3326ee9 100644 --- a/macros/src/tests.rs +++ b/macros/src/tests.rs @@ -1,5 +1,4 @@ // NOTE these tests are specific to the Cortex-M port; `rtic-syntax` has a more extensive test suite // that tests functionality common to all the RTIC ports -mod multi; mod single; diff --git a/macros/src/tests/multi.rs b/macros/src/tests/multi.rs deleted file mode 100644 index 366789bed5..0000000000 --- a/macros/src/tests/multi.rs +++ /dev/null @@ -1,59 +0,0 @@ -use quote::quote; -use rtic_syntax::Settings; - -#[test] -fn analyze() { - let mut settings = Settings::default(); - settings.parse_cores = true; - settings.parse_extern_interrupt = true; - - let (app, analysis) = rtic_syntax::parse2( - quote!(device = pac, cores = 2), - quote!( - const APP: () = { - #[task(core = 0, priority = 1)] - fn a(_: a::Context) {} - - #[task(core = 0, priority = 2)] - fn b(_: b::Context) {} - - #[task(core = 1, priority = 1)] - fn c(_: c::Context) {} - - #[task(core = 1, priority = 2)] - fn d(_: d::Context) {} - - // first interrupt is assigned to the highest priority dispatcher - extern "C" { - #[core = 0] - fn B(); - - #[core = 0] - fn A(); - - #[core = 1] - fn A(); - - #[core = 1] - fn C(); - } - }; - ), - settings, - ) - .unwrap(); - - let analysis = crate::analyze::app(analysis, &app); - - // first core - let interrupts0 = &analysis.interrupts[&0]; - assert_eq!(interrupts0.len(), 2); - assert_eq!(interrupts0[&2].to_string(), "B"); - assert_eq!(interrupts0[&1].to_string(), "A"); - - // second core - let interrupts1 = &analysis.interrupts[&1]; - assert_eq!(interrupts1.len(), 2); - assert_eq!(interrupts1[&2].to_string(), "A"); - assert_eq!(interrupts1[&1].to_string(), "C"); -} diff --git a/macros/src/tests/single.rs b/macros/src/tests/single.rs index 497d1da716..6d4fb23a7b 100644 --- a/macros/src/tests/single.rs +++ b/macros/src/tests/single.rs @@ -27,7 +27,7 @@ fn analyze() { .unwrap(); let analysis = crate::analyze::app(analysis, &app); - let interrupts = &analysis.interrupts[&0]; + let interrupts = &analysis.interrupts; assert_eq!(interrupts.len(), 2); assert_eq!(interrupts[&2].to_string(), "B"); assert_eq!(interrupts[&1].to_string(), "A"); diff --git a/src/export.rs b/src/export.rs index e23b8f3a8b..8e5ef433b2 100644 --- a/src/export.rs +++ b/src/export.rs @@ -12,14 +12,12 @@ pub use cortex_m::{ peripheral::{scb::SystemHandler, syst::SystClkSource, DWT, NVIC}, Peripherals, }; -use heapless::spsc::{MultiCore, SingleCore}; +use heapless::spsc::SingleCore; pub use heapless::{consts, i::Queue as iQueue, spsc::Queue}; pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap}; #[cfg(feature = "heterogeneous")] pub use microamp::shared; -pub type MCFQ = Queue; -pub type MCRQ = Queue<(T, u8), N, u8, MultiCore>; pub type SCFQ = Queue; pub type SCRQ = Queue<(T, u8), N, u8, SingleCore>; @@ -108,13 +106,6 @@ where { } -#[inline(always)] -pub fn assert_multicore() -where - T: super::MultiCore, -{ -} - #[cfg(armv7m)] #[inline(always)] pub unsafe fn lock( diff --git a/src/lib.rs b/src/lib.rs index 5003653168..1c50f78fa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,9 +161,6 @@ pub trait Monotonic { fn zero() -> Self::Instant; } -/// A marker trait that indicates that it is correct to use this type in multi-core context -pub trait MultiCore {} - /// Sets the given `interrupt` as pending /// /// This is a convenience function around From 26f19ae771f9eaa5e205b448b9a4f0299d8cad8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 14:33:31 +0000 Subject: [PATCH 2/8] Do not test homogeneous multicore --- .github/workflows/build.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ec72bb1cb..7a076d9dd1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -156,13 +156,6 @@ jobs: command: check args: --examples --target=${{ matrix.target }} --features __min_r1_43 - - name: cargo check -p homogeneous - uses: actions-rs/cargo@v1 - with: - use-cross: false - command: check - args: -p homogeneous --examples --target=${{ matrix.target }} - # Use precompiled binutils - name: cargo install cargo-binutils uses: actions-rs/install@v0.1 From fea6d2facfc871111cef64e906bd74e3b6b66aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 14:38:25 +0000 Subject: [PATCH 3/8] Remove the multicore tests --- .github/workflows/build.yml | 54 ------------------------------------- 1 file changed, 54 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a076d9dd1..8df63d099c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -474,57 +474,6 @@ jobs: command: test args: --test single - # Verify all multicore examples - checkmulticore: - name: checkmulticore - runs-on: ubuntu-20.04 - strategy: - matrix: - target: - - x86_64-unknown-linux-gnu - toolchain: - - nightly - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install Rust ${{ matrix.toolchain }} with x86_64-unknown-linux-gnu - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - target: x86_64-unknown-linux-gnu - override: true - - name: Install Rust ${{ matrix.toolchain }} with thumbv7m-none-eabi - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - target: thumbv7m-none-eabi - override: true - - name: Install Rust ${{ matrix.toolchain }} with thumbv6m-none-eabi - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - target: thumbv6m-none-eabi - override: true - - uses: actions-rs/cargo@v1 - with: - command: install - args: microamp-tools --version 0.1.0-alpha.3 - - - name: Check multi-core examples - run: | - cd heterogeneous - exs=( - smallest - x-init-2 - x-init - x-schedule - x-spawn - ) - for ex in ${exs[@]}; do - cargo-microamp --example=$ex --target thumbv7m-none-eabi,thumbv6m-none-eabi --check - done - # Build documentation, check links docs: name: docs @@ -654,7 +603,6 @@ jobs: - checkmacros - testv7 - testv6 - - checkmulticore - docs - mdbook # Only run this when pushing to master branch @@ -758,7 +706,6 @@ jobs: - checkmacros - testv7 - testv6 - - checkmulticore - docs - mdbook runs-on: ubuntu-20.04 @@ -775,7 +722,6 @@ jobs: - checkmacros - testv7 - testv6 - - checkmulticore - docs - mdbook runs-on: ubuntu-20.04 From f151d5871c559012173356259030c1dd36a442cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 14:39:05 +0000 Subject: [PATCH 4/8] Cargo fmt --- macros/src/analyze.rs | 31 +++++++++++++--------------- macros/src/check.rs | 17 +++++---------- macros/src/codegen.rs | 10 +++------ macros/src/codegen/assertions.rs | 12 +++++------ macros/src/codegen/hardware_tasks.rs | 4 +--- macros/src/codegen/init.rs | 18 +++++++--------- macros/src/codegen/post_init.rs | 7 ++----- macros/src/codegen/pre_init.rs | 9 +------- macros/src/codegen/resources.rs | 14 +++++-------- macros/src/codegen/spawn_body.rs | 3 ++- macros/src/codegen/util.rs | 27 ++++++------------------ 11 files changed, 53 insertions(+), 99 deletions(-) diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index c81c186d5d..38018c8c5d 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -25,24 +25,21 @@ impl ops::Deref for Analysis { // Assign an `extern` interrupt to each priority level pub fn app(analysis: P, app: &App) -> P { let mut interrupts = BTreeMap::new(); - let priorities = app - .software_tasks - .values() - .filter_map(|task| { - Some(task.args.priority) - }) - .chain(analysis.timer_queues.first().map(|tq| tq.priority)) - .collect::>(); + let priorities = app + .software_tasks + .values() + .filter_map(|task| Some(task.args.priority)) + .chain(analysis.timer_queues.first().map(|tq| tq.priority)) + .collect::>(); - if !priorities.is_empty() { - interrupts = - priorities - .iter() - .cloned() - .rev() - .zip(app.extern_interrupts.keys().cloned()) - .collect(); - } + if !priorities.is_empty() { + interrupts = priorities + .iter() + .cloned() + .rev() + .zip(app.extern_interrupts.keys().cloned()) + .collect(); + } P::new(Analysis { parent: analysis, diff --git a/macros/src/check.rs b/macros/src/check.rs index 0bc475e579..f9d1c989a7 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -4,7 +4,6 @@ use proc_macro2::Span; use rtic_syntax::{ analyze::Analysis, ast::{App, CustomArg}, - }; use syn::{parse, Path}; @@ -51,9 +50,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { // check that external (device-specific) interrupts are not named after known (Cortex-M) // exceptions - for name in app - .extern_interrupts.keys() - { + for name in app.extern_interrupts.keys() { let name_s = name.to_string(); match &*name_s { @@ -83,8 +80,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { .collect::>(); let need = priorities.len(); - let given = app - .extern_interrupts.len(); + let given = app.extern_interrupts.len(); if need > given { let s = { format!( @@ -131,9 +127,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { }, "peripherals" => match v { - CustomArg::Bool(x) => { - peripherals = if *x { true } else { false } - } + CustomArg::Bool(x) => peripherals = if *x { true } else { false }, /* CustomArg::UInt(s) if app.args.cores != 1 => { @@ -152,13 +146,12 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { } } */ - _ => { return Err(parse::Error::new( k.span(), //if app.args.cores == 1 { - "unexpected argument value; this should be a boolean", - /* + "unexpected argument value; this should be a boolean", + /* } else { "unexpected argument value; this should be an integer" }, diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 73531c9b83..35a44bea87 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -35,14 +35,11 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let pre_init_stmts = pre_init::codegen(&app, analysis, extra); - let (const_app_init, root_init, user_init, call_init) = - init::codegen(app, analysis, extra); + let (const_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra); - let (const_app_post_init, post_init_stmts) = - post_init::codegen(&app, analysis); + let (const_app_post_init, post_init_stmts) = post_init::codegen(&app, analysis); - let (const_app_idle, root_idle, user_idle, call_idle) = - idle::codegen(app, analysis, extra); + let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra); user.push(quote!( #user_init @@ -84,7 +81,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { } )); - let (const_app_resources, mod_resources) = resources::codegen(app, analysis, extra); let (const_app_hardware_tasks, root_hardware_tasks, user_hardware_tasks) = diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs index a7c26a5ecf..ab1b26cd5e 100644 --- a/macros/src/codegen/assertions.rs +++ b/macros/src/codegen/assertions.rs @@ -11,15 +11,15 @@ pub fn codegen(analysis: &Analysis) -> Vec { // type only on some core (e.g. `#[cfg(core = "0")] use some::Type;`) //if let Some(types) = analysis.send_types { - for ty in &analysis.send_types { - stmts.push(quote!(rtic::export::assert_send::<#ty>();)); - } + for ty in &analysis.send_types { + stmts.push(quote!(rtic::export::assert_send::<#ty>();)); + } //} //if let Some(types) = analysis.sync_types { - for ty in &analysis.sync_types { - stmts.push(quote!(rtic::export::assert_sync::<#ty>();)); - } + for ty in &analysis.sync_types { + stmts.push(quote!(rtic::export::assert_sync::<#ty>();)); + } //} // if the `schedule` API is used in more than one core then we need to check that the diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index 37df33de81..eb86c8d81e 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -29,7 +29,6 @@ pub fn codegen( let mut user_tasks = vec![]; for (name, task) in &app.hardware_tasks { - let (let_instant, instant) = if app.uses_schedule() { let m = extra.monotonic(); @@ -96,8 +95,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, app); + let (struct_, pat) = locals::codegen(Context::HardwareTask(name), &task.locals, app); root.push(struct_); locals_pat = Some(pat); diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index 4ae9fa624d..01074db675 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -40,17 +40,15 @@ pub fn codegen( .late_resources .iter() .flat_map(|resources| { - resources - .iter() - .map(|name| { - let ty = &app.late_resources[name].ty; - let cfgs = &app.late_resources[name].cfgs; + resources.iter().map(|name| { + let ty = &app.late_resources[name].ty; + let cfgs = &app.late_resources[name].cfgs; - quote!( - #(#cfgs)* - pub #name: #ty - ) - }) + quote!( + #(#cfgs)* + pub #name: #ty + ) + }) }) .collect::>(); diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs index 098d1cc9ab..93d570493d 100644 --- a/macros/src/codegen/post_init.rs +++ b/macros/src/codegen/post_init.rs @@ -5,17 +5,14 @@ use rtic_syntax::ast::App; use crate::analyze::Analysis; /// Generates code that runs after `#[init]` returns -pub fn codegen( - app: &App, - analysis: &Analysis, -) -> (Vec, Vec) { +pub fn codegen(app: &App, analysis: &Analysis) -> (Vec, Vec) { //#TODO remove let const_app = vec![]; let mut stmts = vec![]; // initialize late resources //if let Some(late_resources) = analysis.late_resources { - //for name in late_resources { + //for name in late_resources { if analysis.late_resources.len() > 0 { // #TODO, check soundness of this, why the wrapping // BTreeSet wrapped in a vector diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index 7b57739037..80849aea8a 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -5,14 +5,7 @@ use rtic_syntax::ast::App; use crate::{analyze::Analysis, check::Extra, codegen::util}; /// Generates code that runs before `#[init]` -pub fn codegen( - app: &App, - analysis: &Analysis, - extra: &Extra, -) -> - // `pre_init_stmts` - Vec -{ +pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { let mut stmts = vec![]; // disable interrupts -- `init` must run with interrupts disabled diff --git a/macros/src/codegen/resources.rs b/macros/src/codegen/resources.rs index 07e01cb1eb..51467618a3 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::Ownership, - ast::App, -}; +use rtic_syntax::{analyze::Ownership, ast::App}; use crate::{analyze::Analysis, check::Extra, codegen::util}; @@ -28,10 +25,10 @@ pub fn codegen( { //let loc_attr = None; let section = if expr.is_none() { - util::link_section_uninit(true) - } else { - None - }; + util::link_section_uninit(true) + } else { + None + }; /* let (loc_attr, section) = match loc { Location::Owned => ( @@ -66,7 +63,6 @@ pub fn codegen( } if let Some(Ownership::Contended { ceiling }) = analysis.ownerships.get(name) { - mod_resources.push(quote!( #[allow(non_camel_case_types)] #(#cfgs)* diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs index 3c2e8a0392..4ecd075767 100644 --- a/macros/src/codegen/spawn_body.rs +++ b/macros/src/codegen/spawn_body.rs @@ -45,7 +45,8 @@ pub fn codegen( let device = extra.device; let enum_ = util::interrupt_ident(); let interrupt = &analysis.interrupts.get(&priority); - let pend = {quote!( + let pend = { + quote!( rtic::pend(#device::#enum_::#interrupt); ) }; diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index c375e4eb55..369025f3f0 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -44,10 +44,7 @@ pub fn cfg_core(core: Core, cores: u8) -> Option { /// 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) -> Ident { - Ident::new( - &format!("{}_FQ", task.to_string()), - Span::call_site(), - ) + Ident::new(&format!("{}_FQ", task.to_string()), Span::call_site()) } /// Generates a `Mutex` implementation @@ -112,7 +109,7 @@ pub fn instants_ident(task: &Ident) -> Ident { pub fn interrupt_ident() -> Ident { let span = Span::call_site(); - Ident::new("Interrupt", span) + Ident::new("Interrupt", span) } /// Whether `name` is an exception with configurable priority @@ -253,10 +250,7 @@ pub fn resources_ident(ctxt: Context, app: &App) -> Ident { /// 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(priority: u8) -> Ident { - Ident::new( - &format!("P{}_RQ", priority), - Span::call_site(), - ) + Ident::new(&format!("P{}_RQ", priority), Span::call_site()) } /// Generates an identifier for a "schedule" function @@ -264,10 +258,7 @@ pub fn rq_ident(priority: u8) -> Ident { /// 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) -> Ident { - Ident::new( - &format!("schedule_{}", name.to_string()), - Span::call_site(), - ) + Ident::new(&format!("schedule_{}", name.to_string()), Span::call_site()) } /// Generates an identifier for the `enum` of `schedule`-able tasks @@ -287,10 +278,7 @@ pub fn spawn_barrier() -> Ident { /// 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) -> Ident { - Ident::new( - &format!("spawn_{}", name.to_string()), - Span::call_site(), - ) + Ident::new(&format!("spawn_{}", name.to_string()), Span::call_site()) } /// Generates an identifier for the `enum` of `spawn`-able tasks @@ -298,10 +286,7 @@ pub fn spawn_ident(name: &Ident) -> Ident { /// 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(priority: u8) -> Ident { - Ident::new( - &format!("P{}_T", priority), - Span::call_site(), - ) + Ident::new(&format!("P{}_T", priority), Span::call_site()) } pub fn suffixed(name: &str) -> Ident { From d8c9476372e25799224d0225bb12c9a9fe043743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 16:12:42 +0000 Subject: [PATCH 5/8] Since there only will be one init/idle use .first().unwrap(), matching rtic-syntax --- macros/src/codegen/idle.rs | 3 +-- macros/src/codegen/init.rs | 3 +-- macros/src/codegen/module.rs | 2 +- macros/src/codegen/resources_struct.rs | 4 ++-- macros/src/codegen/util.rs | 15 ++++----------- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/macros/src/codegen/idle.rs b/macros/src/codegen/idle.rs index 853372db1d..cd97764e2a 100644 --- a/macros/src/codegen/idle.rs +++ b/macros/src/codegen/idle.rs @@ -26,9 +26,8 @@ pub fn codegen( // call_idle TokenStream2, ) { - //if let Some(idle) = app.idles.get(&core) { if app.idles.len() > 0 { - let idle = &app.idles[0]; + let idle = &app.idles.first().unwrap(); let mut needs_lt = false; let mut const_app = None; let mut root_idle = vec![]; diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index 01074db675..94f57afb36 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -27,9 +27,8 @@ pub fn codegen( // call_init -- the call to the user `#[init]` if there's one Option, ) { - //if let Some(init) = app.inits.get(&core) { if app.inits.len() > 0 { - let init = &app.inits[0]; + let init = &app.inits.first().unwrap(); let mut needs_lt = false; let name = &init.name; diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index ad20f1393e..4b3d0cf71e 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -253,7 +253,7 @@ pub fn codegen(ctxt: Context, resources_tick: bool, app: &App, extra: &Extra) -> } if let Context::Init = ctxt { - let init = &app.inits[0]; + let init = &app.inits.first().unwrap(); if init.returns_late_resources { let late_resources = util::late_resources_ident(&init.name); diff --git a/macros/src/codegen/resources_struct.rs b/macros/src/codegen/resources_struct.rs index bd92a59916..0c5efd3a10 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 => &app.inits[0].args.resources, - Context::Idle => &app.idles[0].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, }; diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 369025f3f0..f4dbca3978 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -165,8 +165,8 @@ pub fn link_section_uninit(empty_expr: bool) -> Option { /// 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 => app.inits[0].name.to_string(), - Context::Idle => app.idles[0].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(), }; @@ -234,8 +234,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 => app.inits[0].name.to_string(), - Context::Idle => app.idles[0].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(), }; @@ -266,13 +266,6 @@ pub fn schedule_t_ident() -> Ident { Ident::new(&format!("T"), Span::call_site()) } -/* -/// Generates an identifier for a cross-spawn barrier -pub fn spawn_barrier() -> Ident { - Ident::new(&format!("SB"), 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 From d06cf91acc1126e66002f8884b1e7b7a65a9b24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 17:04:55 +0000 Subject: [PATCH 6/8] Remove stale code, fix comment styling --- macros/src/check.rs | 33 +--- macros/src/codegen-verbose.rs | 226 ------------------------- macros/src/codegen.rs | 10 +- macros/src/codegen/assertions.rs | 16 -- macros/src/codegen/dispatchers.rs | 6 +- macros/src/codegen/hardware_tasks.rs | 6 +- macros/src/codegen/idle.rs | 4 +- macros/src/codegen/init.rs | 2 - macros/src/codegen/locals.rs | 8 - macros/src/codegen/module.rs | 4 - macros/src/codegen/post_init.rs | 149 +--------------- macros/src/codegen/pre_init.rs | 59 ++----- macros/src/codegen/resources.rs | 14 -- macros/src/codegen/resources_struct.rs | 8 +- macros/src/codegen/schedule.rs | 6 +- macros/src/codegen/software_tasks.rs | 10 +- macros/src/codegen/spawn.rs | 9 +- macros/src/codegen/timer_queue.rs | 10 -- macros/src/codegen/util.rs | 58 +------ macros/src/tests/single.rs | 2 +- src/cyccnt.rs | 4 - src/export.rs | 4 +- src/lib.rs | 8 - src/tq.rs | 6 +- 24 files changed, 45 insertions(+), 617 deletions(-) delete mode 100644 macros/src/codegen-verbose.rs diff --git a/macros/src/check.rs b/macros/src/check.rs index f9d1c989a7..0e57bb7323 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -20,7 +20,7 @@ impl<'a> Extra<'a> { } pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { - // check that all exceptions are valid; only exceptions with configurable priorities are + // Check that all exceptions are valid; only exceptions with configurable priorities are // accepted for (name, task) in &app.hardware_tasks { let name_s = task.args.binds.to_string(); @@ -48,7 +48,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { } } - // check that external (device-specific) interrupts are not named after known (Cortex-M) + // Check that external (device-specific) interrupts are not named after known (Cortex-M) // exceptions for name in app.extern_interrupts.keys() { let name_s = name.to_string(); @@ -66,7 +66,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { } } - // check that there are enough external interrupts to dispatch the software tasks and the timer + // Check that there are enough external interrupts to dispatch the software tasks and the timer // queue handler let mut first = None; let priorities = app @@ -91,8 +91,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { }; // If not enough tasks and first still is None, may cause - // "custom attribute panicked" - // unwrap on None + // "custom attribute panicked" due to unwrap on None return Err(parse::Error::new(first.unwrap().span(), &s)); } @@ -128,34 +127,10 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { "peripherals" => match v { CustomArg::Bool(x) => peripherals = if *x { true } else { false }, - - /* - CustomArg::UInt(s) if app.args.cores != 1 => { - let x = s.parse::().ok(); - peripherals = if x.is_some() && x.unwrap() < app.args.cores { - Some(x.unwrap()) - } else { - return Err(parse::Error::new( - k.span(), - &format!( - "unexpected argument value; \ - this should be an integer in the range 0..={}", - app.args.cores - ), - )); - } - } - */ _ => { return Err(parse::Error::new( k.span(), - //if app.args.cores == 1 { "unexpected argument value; this should be a boolean", - /* - } else { - "unexpected argument value; this should be an integer" - }, - */ )); } }, diff --git a/macros/src/codegen-verbose.rs b/macros/src/codegen-verbose.rs deleted file mode 100644 index 2b71cf5cd0..0000000000 --- a/macros/src/codegen-verbose.rs +++ /dev/null @@ -1,226 +0,0 @@ -use proc_macro2::TokenStream as TokenStream2; -use quote::quote; -use rtic_syntax::ast::App; - -use crate::{analyze::Analysis, check::Extra}; - -mod assertions; -mod dispatchers; -mod hardware_tasks; -mod idle; -mod init; -mod locals; -mod module; -mod post_init; -mod pre_init; -mod resources; -mod resources_struct; -mod schedule; -mod schedule_body; -mod software_tasks; -mod spawn; -mod spawn_body; -mod timer_queue; -mod util; - -// TODO document the syntax here or in `rtic-syntax` -pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { - let mut const_app = vec![]; - let mut mains = vec![]; - let mut root = vec![]; - let mut user = vec![]; - let mut imports = vec![]; - - // generate a `main` function for each core - for core in 0..app.args.cores { - let assertion_stmts = assertions::codegen(core, analysis, extra); - - let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra); - - let (const_app_init, _root_init, user_init, user_init_imports, call_init) = - init::codegen(core, app, analysis, extra); - - let (const_app_post_init, post_init_stmts) = - post_init::codegen(core, &app, analysis, extra); - - let (const_app_idle, _root_idle, user_idle, user_idle_imports, call_idle) = - idle::codegen(core, app, analysis, extra); - - user.push(quote!( - /// USER INIT - #user_init - - /// USER IDLE - #user_idle - )); - - // Stow away the imports generated for each core - imports.push(quote!( - /// USER IMPORTS - #(#user_init_imports)* - - /// USER IDLE - #(#user_idle_imports)* - )); - - root.push(quote!( - #(#_root_init)* - - #(#_root_idle)* - )); - - const_app.push(quote!( - #(#const_app_pre_init)* - - #const_app_init - - #(#const_app_post_init)* - - #const_app_idle - )); - - let cfg_core = util::cfg_core(core, app.args.cores); - let main = util::suffixed("main", core); - let section = util::link_section("text", core); - mains.push(quote!( - #[no_mangle] - #section - #cfg_core - unsafe extern "C" fn #main() -> ! { - #(#assertion_stmts)* - - #(#pre_init_stmts)* - - #call_init - - #(#post_init_stmts)* - - #call_idle - } - )); - } - - let (const_app_resources, mod_resources, mod_resources_imports) = - resources::codegen(app, analysis, extra); - - let ( - const_app_hardware_tasks, - root_hardware_tasks, - user_hardware_tasks, - user_hardware_tasks_imports, - ) = hardware_tasks::codegen(app, analysis, extra); - - let ( - const_app_software_tasks, - root_software_tasks, - user_software_tasks, - user_software_tasks_imports, - ) = software_tasks::codegen(app, analysis, extra); - - let const_app_dispatchers = dispatchers::codegen(app, analysis, extra); - - let const_app_spawn = spawn::codegen(app, analysis, extra); - - let const_app_timer_queue = timer_queue::codegen(app, analysis, extra); - - let const_app_schedule = schedule::codegen(app, extra); - - let cores = app.args.cores.to_string(); - let cfg_core = quote!(#[cfg(core = #cores)]); - let msg = format!( - "specified {} core{} but tried to compile for more than {0} core{1}", - app.args.cores, - if app.args.cores > 1 { "s" } else { "" } - ); - let check_excess_cores = quote!( - #cfg_core - compile_error!(#msg); - ); - - /* - for s in root.clone() { - println!("{}", s.to_string()); - } - */ - - let user_imports = app.user_imports.clone(); - let user_code = app.user_code.clone(); - let name = &app.name; - let device = extra.device; - let endresult = quote!( - /// USER - #(#user)* - - /// USER_HW_TASKS - #(#user_hardware_tasks)* - - /// USER_SW_TASKS - #(#user_software_tasks)* - - /// ROOT - //#(#root)* - - /// MOD_RESOURCES - #mod_resources - - /// root_hardware_tasks - #(#root_hardware_tasks)* - - /// root_software_tasks - #(#root_software_tasks)* - - /// Implementation details - mod #name { - /// Always include the device crate which contains the vector table - use #device as _; - #(#imports)* - /// User imports - #(#user_imports)* - - /// User code from within the module - #(#user_code)* - - /// User hardware tasks import - #(#user_hardware_tasks_imports)* - - /// User software_tasks - #(#user_software_tasks_imports)* - - /// Mod resources imports - #(#mod_resources_imports)* - - #check_excess_cores - - /// Const app - #(#const_app)* - - /// Const app resources - #(#const_app_resources)* - - /// Const app hw tasks - #(#const_app_hardware_tasks)* - - /// Const app sw tasks - #(#const_app_software_tasks)* - - /// Const app dispatchers - #(#const_app_dispatchers)* - - /// Const app spawn - #(#const_app_spawn)* - /// Const app spawn end - - #(#const_app_timer_queue)* - - #(#const_app_schedule)* - - /// Mains - #(#mains)* - } - ); - for s in endresult.clone() { - eprintln!("{}", s.to_string()); - } - - endresult -} diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 35a44bea87..fe4d59a6b7 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -30,14 +30,14 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let mut root = vec![]; let mut user = vec![]; - // generate the `main` function + // Generate the `main` function let assertion_stmts = assertions::codegen(analysis); let pre_init_stmts = pre_init::codegen(&app, analysis, extra); let (const_app_init, root_init, user_init, call_init) = init::codegen(app, analysis, extra); - let (const_app_post_init, post_init_stmts) = post_init::codegen(&app, analysis); + let post_init_stmts = post_init::codegen(&app, analysis); let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(app, analysis, extra); @@ -56,16 +56,12 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { const_app.push(quote!( #const_app_init - #(#const_app_post_init)* - #const_app_idle )); let main = util::suffixed("main"); - let section = util::link_section("text"); mains.push(quote!( #[no_mangle] - #section unsafe extern "C" fn #main() -> ! { let _TODO: () = (); @@ -115,7 +111,7 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { #(#root_software_tasks)* /// Implementation details - // the user can't access the items within this `const` item + // The user can't access the items within this `const` item const #name: () = { /// Always include the device crate which contains the vector table use #device as _; diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs index ab1b26cd5e..4d9aae4725 100644 --- a/macros/src/codegen/assertions.rs +++ b/macros/src/codegen/assertions.rs @@ -7,29 +7,13 @@ use crate::analyze::Analysis; pub fn codegen(analysis: &Analysis) -> Vec { 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 { for ty in &analysis.send_types { stmts.push(quote!(rtic::export::assert_send::<#ty>();)); } - //} - //if let Some(types) = analysis.sync_types { for ty in &analysis.sync_types { stmts.push(quote!(rtic::export::assert_sync::<#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>();)); - } - */ stmts } diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index fdeb615534..300aa996e0 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -42,13 +42,12 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec), quote!(rtic::export::Queue(unsafe { rtic::export::iQueue::u8_sc() })), - util::link_section("bss"), ) }; @@ -58,7 +57,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec ! { use rtic::Mutex as _; diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index 94f57afb36..e0b7d69972 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -81,12 +81,10 @@ pub fn codegen( let context = &init.context; let attrs = &init.attrs; let stmts = &init.stmts; - let section = util::link_section("text"); let locals_pat = locals_pat.iter(); let user_init = Some(quote!( #(#attrs)* #[allow(non_snake_case)] - #section fn #name(#(#locals_pat,)* #context: #name::Context) #ret { #(#stmts)* } diff --git a/macros/src/codegen/locals.rs b/macros/src/codegen/locals.rs index b3c593a2b2..336c0b214f 100644 --- a/macros/src/codegen/locals.rs +++ b/macros/src/codegen/locals.rs @@ -41,13 +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!( @@ -56,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 4b3d0cf71e..863f6c5b73 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -11,7 +11,6 @@ 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 { @@ -312,12 +311,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 93d570493d..c35c697635 100644 --- a/macros/src/codegen/post_init.rs +++ b/macros/src/codegen/post_init.rs @@ -5,19 +5,14 @@ use rtic_syntax::ast::App; use crate::analyze::Analysis; /// Generates code that runs after `#[init]` returns -pub fn codegen(app: &App, analysis: &Analysis) -> (Vec, Vec) { - //#TODO remove - let const_app = vec![]; +pub fn codegen(app: &App, analysis: &Analysis) -> Vec { let mut stmts = vec![]; - // initialize late resources - //if let Some(late_resources) = analysis.late_resources { - //for name in late_resources { + // Initialize late resources if analysis.late_resources.len() > 0 { - // #TODO, check soundness of this, why the wrapping // BTreeSet wrapped in a vector - for name in &analysis.late_resources[0] { - // if it's live + 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,140 +24,8 @@ pub fn codegen(app: &App, analysis: &Analysis) -> (Vec, Vec::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 80849aea8a..9c5f35ec37 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -8,10 +8,10 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec { 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 the FreeQueue + // Populate the FreeQueue for fq in &analysis.free_queues { // Get the task name let name = fq.0; @@ -33,7 +33,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Vec Vec Vec Vec ( - None, - if expr.is_none() { - util::link_section_uninit(true) - } else { - None - }, - ), - }; - */ let (ty, expr) = if let Some(expr) = expr { (quote!(#ty), quote!(#expr)) @@ -56,7 +43,6 @@ pub fn codegen( #[allow(non_upper_case_globals)] #(#attrs)* #(#cfgs)* - //#loc_attr #section static mut #name: #ty = #expr; )); diff --git a/macros/src/codegen/resources_struct.rs b/macros/src/codegen/resources_struct.rs index 0c5efd3a10..dbbba30e0f 100644 --- a/macros/src/codegen/resources_struct.rs +++ b/macros/src/codegen/resources_struct.rs @@ -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)] diff --git a/macros/src/codegen/schedule.rs b/macros/src/codegen/schedule.rs index b6cb6b9aa4..46b0f38494 100644 --- a/macros/src/codegen/schedule.rs +++ b/macros/src/codegen/schedule.rs @@ -32,10 +32,8 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { let body = schedule_body::codegen(scheduler, &name, app); - let section = util::link_section("text"); methods.push(quote!( #(#cfgs)* - #section fn #name(&self, instant: #instant #(,#args)*) -> Result<(), #ty> { #body } @@ -44,15 +42,13 @@ pub fn codegen(app: &App, extra: &Extra) -> Vec { 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"); items.push(quote!( #(#cfgs)* - #section unsafe fn #schedule( priority: &rtic::export::Priority, instant: #instant diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 25662801a6..b56db4199d 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -35,26 +35,22 @@ 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 { + // 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, bss, mk_uninit): (_, _, _, Box Option<_>>) = { + let (fq_ty, fq_expr, mk_uninit): (_, _, Box Option<_>>) = { ( quote!(rtic::export::SCFQ<#cap_ty>), quote!(rtic::export::Queue(unsafe { rtic::export::iQueue::u8_sc() })), - util::link_section("bss"), Box::new(|| util::link_section_uninit(true)), ) }; const_app.push(quote!( /// Queue version of a free-list that keeps track of empty slots in /// the following buffers - #bss static mut #fq: #fq_ty = #fq_expr; )); @@ -130,7 +126,6 @@ pub fn codegen( root.push(struct_); } - let section = util::link_section("text"); let context = &task.context; let attrs = &task.attrs; let cfgs = &task.cfgs; @@ -140,7 +135,6 @@ pub fn codegen( #(#attrs)* #(#cfgs)* #[allow(non_snake_case)] - #section fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) { use rtic::Mutex as _; diff --git a/macros/src/codegen/spawn.rs b/macros/src/codegen/spawn.rs index 6cad809b5b..4b824f56ab 100644 --- a/macros/src/codegen/spawn.rs +++ b/macros/src/codegen/spawn.rs @@ -20,7 +20,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Result<(), #ty> { #let_instant #body @@ -52,7 +49,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Vec #spawner::Spawn<#lt> { #(#methods)* } diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index 41f5520ec9..030158e205 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -9,7 +9,6 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec Vec); - let section = util::link_section("bss"); 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 Vec 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 { - 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) -> Ident { Ident::new(&format!("{}_FQ", task.to_string()), Span::call_site()) } @@ -51,7 +34,6 @@ pub fn fq_ident(task: &Ident) -> Ident { pub fn impl_mutex( extra: &Extra, cfgs: &[Attribute], - //cfg_core: Option<&TokenStream2>, resources_prefix: bool, name: &Ident, ty: TokenStream2, @@ -67,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; @@ -90,13 +71,6 @@ 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) -> Ident { Ident::new(&format!("{}_INPUTS", task), Span::call_site()) @@ -138,18 +112,6 @@ fn link_section_index() -> usize { INDEX.fetch_add(1, Ordering::Relaxed) } -pub fn link_section(_section: &str) -> Option { - /* - if cfg!(feature = "homogeneous") { - let section = format!(".{}_{}.rtic{}", section, core, link_section_index()); - Some(quote!(#[link_section = #section])) - } else { - None - } - */ - None -} - // NOTE `None` means in shared memory pub fn link_section_uninit(empty_expr: bool) -> Option { let section = if empty_expr { @@ -175,13 +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() -> Ident { - Ident::new(&format!("RV"), Span::call_site()) -} -*/ - // Regroups the inputs of a task // // `inputs` could be &[`input: Foo`] OR &[`mut x: i32`, `ref y: i64`] @@ -246,17 +201,15 @@ 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. +/// 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 +/// 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()) } @@ -268,8 +221,7 @@ pub fn schedule_t_ident() -> Ident { /// 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 +/// 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()) } @@ -289,7 +241,7 @@ pub fn suffixed(name: &str) -> Ident { /// Generates an identifier for a timer queue /// -/// At most there's one timer queue per core +/// At most there is one timer queue pub fn tq_ident() -> Ident { Ident::new(&format!("TQ"), Span::call_site()) } diff --git a/macros/src/tests/single.rs b/macros/src/tests/single.rs index 6d4fb23a7b..d6693882a3 100644 --- a/macros/src/tests/single.rs +++ b/macros/src/tests/single.rs @@ -15,7 +15,7 @@ fn analyze() { #[task(priority = 2)] fn b(_: b::Context) {} - // first interrupt is assigned to the highest priority dispatcher + // First interrupt is assigned to the highest priority dispatcher extern "C" { fn B(); fn A(); diff --git a/src/cyccnt.rs b/src/cyccnt.rs index 6bc2ef0ab0..8e07b00170 100644 --- a/src/cyccnt.rs +++ b/src/cyccnt.rs @@ -19,10 +19,6 @@ use crate::Fraction; /// Adding or subtracting a `Duration` of more than `(1 << 31)` cycles to an `Instant` effectively /// makes it "wrap around" and creates an incorrect value. This is also true if the operation is /// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 30)` ticks. -/// -/// In multi-core contexts: this value is tied to the CYCCNT of *one* core so sending it a different -/// core makes it lose its meaning -- each Cortex-M core has its own CYCCNT counter and these are -/// usually unsynchronized and may even be running at different frequencies. #[derive(Clone, Copy, Eq, PartialEq)] pub struct Instant { inner: i32, diff --git a/src/export.rs b/src/export.rs index 8e5ef433b2..8a5d4e3e56 100644 --- a/src/export.rs +++ b/src/export.rs @@ -28,7 +28,7 @@ where F: FnOnce(), { if priority == 1 { - // if the priority of this interrupt is `1` then BASEPRI can only be `0` + // If the priority of this interrupt is `1` then BASEPRI can only be `0` f(); unsafe { basepri::write(0) } } else { @@ -80,7 +80,7 @@ impl Priority { } } - // these two methods are used by `lock` (see below) but can't be used from the RTIC application + // 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) diff --git a/src/lib.rs b/src/lib.rs index 1c50f78fa7..a7d399cd45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,13 +28,6 @@ //! release. //! //! [SemVer]: https://semver.org/spec/v2.0.0.html -//! -//! # Cargo features -//! -//! - `heterogeneous`. This opt-in feature enables the *experimental* heterogeneous multi-core -//! support. This feature depends on unstable feature and requires the use of the nightly channel. -//! -//! - `homogeneous`. This opt-in feature enables the *experimental* homogeneous multi-core support. #![deny(missing_docs)] #![deny(rust_2018_compatibility)] @@ -48,7 +41,6 @@ use cortex_m::{ interrupt::Nr, peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU}, }; -#[cfg(all(not(feature = "heterogeneous"), not(feature = "homogeneous")))] use cortex_m_rt as _; // vector table pub use cortex_m_rtic_macros::app; pub use rtic_core::{Exclusive, Mutex}; diff --git a/src/tq.rs b/src/tq.rs index 21beeb9cff..9300dbfcb6 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -40,7 +40,7 @@ where mem::transmute::<_, SYST>(()).enable_interrupt(); } - // set SysTick pending + // Set SysTick pending SCB::set_pendst(); } @@ -79,13 +79,13 @@ where }; mem::transmute::<_, SYST>(()).set_reload(dur); - // start counting down from the new reload + // Start counting down from the new reload mem::transmute::<_, SYST>(()).clear_current(); None } } else { - // the queue is empty + // The queue is empty mem::transmute::<_, SYST>(()).disable_interrupt(); None From d2151ccbf935da23d44c183f1ddb185c7ad83bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Tue, 1 Sep 2020 17:09:25 +0000 Subject: [PATCH 7/8] Remove all of heterogeneous and homogeneous modules --- heterogeneous/Cargo.toml | 18 ----- heterogeneous/README.md | 1 - heterogeneous/examples/smallest.rs | 7 -- heterogeneous/examples/x-init-2.rs | 39 ----------- heterogeneous/examples/x-init.rs | 26 -------- heterogeneous/examples/x-schedule.rs | 36 ---------- heterogeneous/examples/x-spawn.rs | 20 ------ heterogeneous/src/lib.rs | 99 ---------------------------- homogeneous/Cargo.toml | 17 ----- homogeneous/README.md | 1 - homogeneous/examples/smallest.rs | 7 -- homogeneous/examples/x-init-2.rs | 39 ----------- homogeneous/examples/x-init.rs | 26 -------- homogeneous/examples/x-schedule.rs | 36 ---------- homogeneous/examples/x-spawn.rs | 20 ------ homogeneous/src/lib.rs | 99 ---------------------------- 16 files changed, 491 deletions(-) delete mode 100644 heterogeneous/Cargo.toml delete mode 100644 heterogeneous/README.md delete mode 100644 heterogeneous/examples/smallest.rs delete mode 100644 heterogeneous/examples/x-init-2.rs delete mode 100644 heterogeneous/examples/x-init.rs delete mode 100644 heterogeneous/examples/x-schedule.rs delete mode 100644 heterogeneous/examples/x-spawn.rs delete mode 100644 heterogeneous/src/lib.rs delete mode 100644 homogeneous/Cargo.toml delete mode 100644 homogeneous/README.md delete mode 100644 homogeneous/examples/smallest.rs delete mode 100644 homogeneous/examples/x-init-2.rs delete mode 100644 homogeneous/examples/x-init.rs delete mode 100644 homogeneous/examples/x-schedule.rs delete mode 100644 homogeneous/examples/x-spawn.rs delete mode 100644 homogeneous/src/lib.rs diff --git a/heterogeneous/Cargo.toml b/heterogeneous/Cargo.toml deleted file mode 100644 index 54808a2fe3..0000000000 --- a/heterogeneous/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -authors = ["Jorge Aparicio "] -edition = "2018" -name = "heterogeneous" -# this crate is only used for testing -publish = false -version = "0.0.0-alpha.0" - -[dependencies] -bare-metal = "0.2.4" - -[dependencies.cortex-m-rtic] -path = ".." -features = ["heterogeneous"] - -[dev-dependencies] -panic-halt = "0.2.0" -microamp = "0.1.0-alpha.1" diff --git a/heterogeneous/README.md b/heterogeneous/README.md deleted file mode 100644 index 8e49ff8bea..0000000000 --- a/heterogeneous/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory contains *heterogeneous* multi-core compile pass tests. diff --git a/heterogeneous/examples/smallest.rs b/heterogeneous/examples/smallest.rs deleted file mode 100644 index 2074e7dce2..0000000000 --- a/heterogeneous/examples/smallest.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = heterogeneous)] -const APP: () = {}; diff --git a/heterogeneous/examples/x-init-2.rs b/heterogeneous/examples/x-init-2.rs deleted file mode 100644 index e6ec7fcab3..0000000000 --- a/heterogeneous/examples/x-init-2.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! [compile-pass] Cross initialization of late resources - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = heterogeneous)] -const APP: () = { - struct Resources { - // owned by core #1 but initialized by core #0 - x: u32, - - // owned by core #0 but initialized by core #1 - y: u32, - } - - #[init(core = 0, late = [x])] - fn a(_: a::Context) -> a::LateResources { - a::LateResources { x: 0 } - } - - #[idle(core = 0, resources = [y])] - fn b(_: b::Context) -> ! { - loop {} - } - - #[init(core = 1)] - fn c(_: c::Context) -> c::LateResources { - c::LateResources { y: 0 } - } - - #[idle(core = 1, resources = [x])] - fn d(_: d::Context) -> ! { - loop {} - } -}; diff --git a/heterogeneous/examples/x-init.rs b/heterogeneous/examples/x-init.rs deleted file mode 100644 index 20601b1a3f..0000000000 --- a/heterogeneous/examples/x-init.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! [compile-pass] Split initialization of late resources - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = heterogeneous)] -const APP: () = { - struct Resources { - x: u32, - y: u32, - } - - #[init(core = 0, late = [x])] - fn a(_: a::Context) -> a::LateResources { - a::LateResources { x: 0 } - } - - #[init(core = 1)] - fn b(_: b::Context) -> b::LateResources { - b::LateResources { y: 0 } - } -}; diff --git a/heterogeneous/examples/x-schedule.rs b/heterogeneous/examples/x-schedule.rs deleted file mode 100644 index 98a5f74122..0000000000 --- a/heterogeneous/examples/x-schedule.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = heterogeneous, monotonic = heterogeneous::MT)] -const APP: () = { - #[init(core = 0, spawn = [ping])] - fn init(c: init::Context) { - c.spawn.ping().ok(); - } - - #[task(core = 0, schedule = [ping])] - fn pong(c: pong::Context) { - c.schedule.ping(c.scheduled + 1_000_000).ok(); - } - - #[task(core = 1, schedule = [pong])] - fn ping(c: ping::Context) { - c.schedule.pong(c.scheduled + 1_000_000).ok(); - } - - extern "C" { - #[core = 0] - fn I0(); - - #[core = 0] - fn I1(); - - #[core = 1] - fn I0(); - - #[core = 1] - fn I1(); - } -}; diff --git a/heterogeneous/examples/x-spawn.rs b/heterogeneous/examples/x-spawn.rs deleted file mode 100644 index e2586210d1..0000000000 --- a/heterogeneous/examples/x-spawn.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = heterogeneous)] -const APP: () = { - #[init(core = 0, spawn = [foo])] - fn init(c: init::Context) { - c.spawn.foo().ok(); - } - - #[task(core = 1)] - fn foo(_: foo::Context) {} - - extern "C" { - #[core = 1] - fn I0(); - } -}; diff --git a/heterogeneous/src/lib.rs b/heterogeneous/src/lib.rs deleted file mode 100644 index 1bda7c851b..0000000000 --- a/heterogeneous/src/lib.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! Fake multi-core PAC - -#![no_std] - -use core::{ - cmp::Ordering, - ops::{Add, Sub}, -}; - -use bare_metal::Nr; -use rtic::{Fraction, Monotonic, MultiCore}; - -// both cores have the exact same interrupts -pub use Interrupt_0 as Interrupt_1; - -// Fake priority bits -pub const NVIC_PRIO_BITS: u8 = 3; - -pub fn xpend(_core: u8, _interrupt: impl Nr) {} - -/// Fake monotonic timer -pub struct MT; - -impl Monotonic for MT { - type Instant = Instant; - - fn ratio() -> Fraction { - Fraction { - numerator: 1, - denominator: 1, - } - } - - unsafe fn reset() { - (0xE0001004 as *mut u32).write_volatile(0) - } - - fn now() -> Instant { - unsafe { Instant((0xE0001004 as *const u32).read_volatile() as i32) } - } - - fn zero() -> Instant { - Instant(0) - } -} - -impl MultiCore for MT {} - -#[derive(Clone, Copy, Eq, PartialEq)] -pub struct Instant(i32); - -impl Add for Instant { - type Output = Instant; - - fn add(self, rhs: u32) -> Self { - Instant(self.0.wrapping_add(rhs as i32)) - } -} - -impl Sub for Instant { - type Output = u32; - - fn sub(self, rhs: Self) -> u32 { - self.0.checked_sub(rhs.0).unwrap() as u32 - } -} - -impl Ord for Instant { - fn cmp(&self, rhs: &Self) -> Ordering { - self.0.wrapping_sub(rhs.0).cmp(&0) - } -} - -impl PartialOrd for Instant { - fn partial_cmp(&self, rhs: &Self) -> Option { - Some(self.cmp(rhs)) - } -} - -// Fake interrupts -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum Interrupt_0 { - I0 = 0, - I1 = 1, - I2 = 2, - I3 = 3, - I4 = 4, - I5 = 5, - I6 = 6, - I7 = 7, -} - -unsafe impl Nr for Interrupt_0 { - fn nr(&self) -> u8 { - *self as u8 - } -} diff --git a/homogeneous/Cargo.toml b/homogeneous/Cargo.toml deleted file mode 100644 index 111fe5dfb3..0000000000 --- a/homogeneous/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -authors = ["Jorge Aparicio "] -edition = "2018" -name = "homogeneous" -# this crate is only used for testing -publish = false -version = "0.0.0-alpha.0" - -[dependencies] -bare-metal = "0.2.4" - -[dependencies.cortex-m-rtic] -path = ".." -features = ["homogeneous"] - -[dev-dependencies] -panic-halt = "0.2.0" diff --git a/homogeneous/README.md b/homogeneous/README.md deleted file mode 100644 index 17e9c6e11a..0000000000 --- a/homogeneous/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory contains *homogeneous* multi-core compile pass tests. diff --git a/homogeneous/examples/smallest.rs b/homogeneous/examples/smallest.rs deleted file mode 100644 index 913e489f43..0000000000 --- a/homogeneous/examples/smallest.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = homogeneous)] -const APP: () = {}; diff --git a/homogeneous/examples/x-init-2.rs b/homogeneous/examples/x-init-2.rs deleted file mode 100644 index 11caacd4d2..0000000000 --- a/homogeneous/examples/x-init-2.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! [compile-pass] Cross initialization of late resources - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = homogeneous)] -const APP: () = { - struct Resources { - // owned by core #1 but initialized by core #0 - x: u32, - - // owned by core #0 but initialized by core #1 - y: u32, - } - - #[init(core = 0, late = [x])] - fn a(_: a::Context) -> a::LateResources { - a::LateResources { x: 0 } - } - - #[idle(core = 0, resources = [y])] - fn b(_: b::Context) -> ! { - loop {} - } - - #[init(core = 1)] - fn c(_: c::Context) -> c::LateResources { - c::LateResources { y: 0 } - } - - #[idle(core = 1, resources = [x])] - fn d(_: d::Context) -> ! { - loop {} - } -}; diff --git a/homogeneous/examples/x-init.rs b/homogeneous/examples/x-init.rs deleted file mode 100644 index 0574279cbd..0000000000 --- a/homogeneous/examples/x-init.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! [compile-pass] Split initialization of late resources - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = homogeneous)] -const APP: () = { - struct Resources { - x: u32, - y: u32, - } - - #[init(core = 0, late = [x])] - fn a(_: a::Context) -> a::LateResources { - a::LateResources { x: 0 } - } - - #[init(core = 1)] - fn b(_: b::Context) -> b::LateResources { - b::LateResources { y: 0 } - } -}; diff --git a/homogeneous/examples/x-schedule.rs b/homogeneous/examples/x-schedule.rs deleted file mode 100644 index 7c0b3840a8..0000000000 --- a/homogeneous/examples/x-schedule.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = homogeneous, monotonic = homogeneous::MT)] -const APP: () = { - #[init(core = 0, spawn = [ping])] - fn init(c: init::Context) { - c.spawn.ping().ok(); - } - - #[task(core = 0, schedule = [ping])] - fn pong(c: pong::Context) { - c.schedule.ping(c.scheduled + 1_000_000).ok(); - } - - #[task(core = 1, schedule = [pong])] - fn ping(c: ping::Context) { - c.schedule.pong(c.scheduled + 1_000_000).ok(); - } - - extern "C" { - #[core = 0] - fn I0(); - - #[core = 0] - fn I1(); - - #[core = 1] - fn I0(); - - #[core = 1] - fn I1(); - } -}; diff --git a/homogeneous/examples/x-spawn.rs b/homogeneous/examples/x-spawn.rs deleted file mode 100644 index 45bc90030c..0000000000 --- a/homogeneous/examples/x-spawn.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtic::app(cores = 2, device = homogeneous)] -const APP: () = { - #[init(core = 0, spawn = [foo])] - fn init(c: init::Context) { - c.spawn.foo().ok(); - } - - #[task(core = 1)] - fn foo(_: foo::Context) {} - - extern "C" { - #[core = 1] - fn I0(); - } -}; diff --git a/homogeneous/src/lib.rs b/homogeneous/src/lib.rs deleted file mode 100644 index 1bda7c851b..0000000000 --- a/homogeneous/src/lib.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! Fake multi-core PAC - -#![no_std] - -use core::{ - cmp::Ordering, - ops::{Add, Sub}, -}; - -use bare_metal::Nr; -use rtic::{Fraction, Monotonic, MultiCore}; - -// both cores have the exact same interrupts -pub use Interrupt_0 as Interrupt_1; - -// Fake priority bits -pub const NVIC_PRIO_BITS: u8 = 3; - -pub fn xpend(_core: u8, _interrupt: impl Nr) {} - -/// Fake monotonic timer -pub struct MT; - -impl Monotonic for MT { - type Instant = Instant; - - fn ratio() -> Fraction { - Fraction { - numerator: 1, - denominator: 1, - } - } - - unsafe fn reset() { - (0xE0001004 as *mut u32).write_volatile(0) - } - - fn now() -> Instant { - unsafe { Instant((0xE0001004 as *const u32).read_volatile() as i32) } - } - - fn zero() -> Instant { - Instant(0) - } -} - -impl MultiCore for MT {} - -#[derive(Clone, Copy, Eq, PartialEq)] -pub struct Instant(i32); - -impl Add for Instant { - type Output = Instant; - - fn add(self, rhs: u32) -> Self { - Instant(self.0.wrapping_add(rhs as i32)) - } -} - -impl Sub for Instant { - type Output = u32; - - fn sub(self, rhs: Self) -> u32 { - self.0.checked_sub(rhs.0).unwrap() as u32 - } -} - -impl Ord for Instant { - fn cmp(&self, rhs: &Self) -> Ordering { - self.0.wrapping_sub(rhs.0).cmp(&0) - } -} - -impl PartialOrd for Instant { - fn partial_cmp(&self, rhs: &Self) -> Option { - Some(self.cmp(rhs)) - } -} - -// Fake interrupts -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum Interrupt_0 { - I0 = 0, - I1 = 1, - I2 = 2, - I3 = 3, - I4 = 4, - I5 = 5, - I6 = 6, - I7 = 7, -} - -unsafe impl Nr for Interrupt_0 { - fn nr(&self) -> u8 { - *self as u8 - } -} From ad2b80907899cc335edcebfc77ae4b4b51272b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Fri, 4 Sep 2020 07:32:53 +0000 Subject: [PATCH 8/8] Use rtic-rs master --- macros/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macros/Cargo.toml b/macros/Cargo.toml index e1dbce9993..610890bbfb 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -21,5 +21,5 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = "1" -rtic-syntax = { git = "https://github.com/AfoHT/rtic-syntax", branch = "multiremove", version = "0.4.0" } +rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.4.0" }