From 81275bfa4f41e2066770087f3a33cad4227eab41 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 13 Jun 2019 23:56:59 +0200 Subject: rtfm-syntax refactor + heterogeneous multi-core support --- macros/src/codegen/spawn_body.rs | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 macros/src/codegen/spawn_body.rs (limited to 'macros/src/codegen/spawn_body.rs') diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs new file mode 100644 index 00000000..83cb5c0a --- /dev/null +++ b/macros/src/codegen/spawn_body.rs @@ -0,0 +1,81 @@ +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use rtfm_syntax::{ast::App, Context}; +use syn::Ident; + +use crate::{analyze::Analysis, check::Extra, codegen::util}; + +pub fn codegen( + spawner: Context, + name: &Ident, + app: &App, + 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); + + Some(quote!( + #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant); + )) + } else { + 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 (dequeue, enqueue) = if spawner.is_init() { + ( + quote!(#fq.dequeue()), + quote!(#rq.enqueue_unchecked((#t::#name, index));), + ) + } else { + ( + quote!((#fq { priority }.lock(|fq| fq.split().1.dequeue()))), + quote!((#rq { priority }.lock(|rq| { + rq.split().0.enqueue_unchecked((#t::#name, index)) + }));), + ) + }; + + let device = extra.device; + let interrupt = &analysis.interrupts[&receiver][&priority]; + let pend = if sender != receiver { + quote!( + #device::xpend(#receiver, #device::Interrupt::#interrupt); + ) + } else { + quote!( + rtfm::pend(#device::Interrupt::#interrupt); + ) + }; + + let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs); + let inputs = util::inputs_ident(name, sender); + quote!( + unsafe { + use rtfm::Mutex as _; + + let input = #tupled; + if let Some(index) = #dequeue { + #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input); + + #write_instant + + #enqueue + + #pend + + Ok(()) + } else { + Err(input) + } + } + ) +} -- cgit v1.2.3 From 9897728709528a02545523bea72576abce89dc4c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 18 Jun 2019 10:31:31 +0200 Subject: add homogeneous multi-core support --- Cargo.toml | 4 +- ci/script.sh | 4 +- 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 | 94 ++++++++++++++++++++++++++++++++++ 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 | 94 ++++++++++++++++++++++++++++++++++ macros/Cargo.toml | 1 + macros/src/check.rs | 22 ++++++++ macros/src/codegen.rs | 3 +- macros/src/codegen/dispatchers.rs | 10 +++- macros/src/codegen/hardware_tasks.rs | 6 ++- macros/src/codegen/post_init.rs | 18 ++++++- macros/src/codegen/pre_init.rs | 17 +++++-- macros/src/codegen/resources.rs | 8 ++- macros/src/codegen/software_tasks.rs | 8 ++- macros/src/codegen/spawn_body.rs | 5 +- macros/src/codegen/timer_queue.rs | 8 +-- macros/src/codegen/util.rs | 23 ++++++++- macros/src/lib.rs | 2 +- mc/Cargo.toml | 18 ------- mc/README.md | 1 - mc/examples/smallest.rs | 7 --- mc/examples/x-init-2.rs | 39 -------------- mc/examples/x-init.rs | 26 ---------- mc/examples/x-schedule.rs | 36 ------------- mc/examples/x-spawn.rs | 20 -------- mc/src/lib.rs | 99 ------------------------------------ src/lib.rs | 2 +- 40 files changed, 600 insertions(+), 268 deletions(-) create mode 100644 heterogeneous/Cargo.toml create mode 100644 heterogeneous/README.md create mode 100644 heterogeneous/examples/smallest.rs create mode 100644 heterogeneous/examples/x-init-2.rs create mode 100644 heterogeneous/examples/x-init.rs create mode 100644 heterogeneous/examples/x-schedule.rs create mode 100644 heterogeneous/examples/x-spawn.rs create mode 100644 heterogeneous/src/lib.rs create mode 100644 homogeneous/Cargo.toml create mode 100644 homogeneous/README.md create mode 100644 homogeneous/examples/smallest.rs create mode 100644 homogeneous/examples/x-init-2.rs create mode 100644 homogeneous/examples/x-init.rs create mode 100644 homogeneous/examples/x-schedule.rs create mode 100644 homogeneous/examples/x-spawn.rs create mode 100644 homogeneous/src/lib.rs delete mode 100644 mc/Cargo.toml delete mode 100644 mc/README.md delete mode 100644 mc/examples/smallest.rs delete mode 100644 mc/examples/x-init-2.rs delete mode 100644 mc/examples/x-init.rs delete mode 100644 mc/examples/x-schedule.rs delete mode 100644 mc/examples/x-spawn.rs delete mode 100644 mc/src/lib.rs (limited to 'macros/src/codegen/spawn_body.rs') diff --git a/Cargo.toml b/Cargo.toml index 81ca256c..ef45be85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,7 @@ compiletest_rs = "0.3.22" [features] heterogeneous = ["cortex-m-rtfm-macros/heterogeneous", "microamp"] +homogeneous = ["cortex-m-rtfm-macros/homogeneous", "microamp"] # used for testing this crate; do not use in applications __v7 =[] @@ -83,6 +84,7 @@ lto = true [workspace] members = [ + "heterogeneous", + "homogeneous", "macros", - "mc", ] diff --git a/ci/script.sh b/ci/script.sh index a6485cf7..1b3d5615 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -43,7 +43,7 @@ main() { cargo test --test multi --features heterogeneous --target $T # multi-core compile-pass tests - pushd mc + pushd heterogeneous local exs=( smallest x-init-2 @@ -91,6 +91,8 @@ main() { cargo check --target $T --examples --features __v7 fi + cargo check -p homogeneous --target $T --examples + # run-pass tests case $T in thumbv6m-none-eabi | thumbv7m-none-eabi) diff --git a/heterogeneous/Cargo.toml b/heterogeneous/Cargo.toml new file mode 100644 index 00000000..fd05d07e --- /dev/null +++ b/heterogeneous/Cargo.toml @@ -0,0 +1,18 @@ +[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-rtfm] +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 new file mode 100644 index 00000000..8e49ff8b --- /dev/null +++ b/heterogeneous/README.md @@ -0,0 +1 @@ +This directory contains *heterogeneous* multi-core compile pass tests. diff --git a/heterogeneous/examples/smallest.rs b/heterogeneous/examples/smallest.rs new file mode 100644 index 00000000..9b6bb82d --- /dev/null +++ b/heterogeneous/examples/smallest.rs @@ -0,0 +1,7 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = heterogeneous)] +const APP: () = {}; diff --git a/heterogeneous/examples/x-init-2.rs b/heterogeneous/examples/x-init-2.rs new file mode 100644 index 00000000..b9c39197 --- /dev/null +++ b/heterogeneous/examples/x-init-2.rs @@ -0,0 +1,39 @@ +//! [compile-pass] Cross initialization of late resources + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = heterogeneous)] +const APP: () = { + extern "C" { + // owned by core #1 but initialized by core #0 + static mut X: u32; + + // owned by core #0 but initialized by core #1 + static mut 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 new file mode 100644 index 00000000..53e73805 --- /dev/null +++ b/heterogeneous/examples/x-init.rs @@ -0,0 +1,26 @@ +//! [compile-pass] Split initialization of late resources + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = heterogeneous)] +const APP: () = { + extern "C" { + static mut X: u32; + static mut 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 new file mode 100644 index 00000000..cbfc01f9 --- /dev/null +++ b/heterogeneous/examples/x-schedule.rs @@ -0,0 +1,36 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::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 new file mode 100644 index 00000000..3fc64f6f --- /dev/null +++ b/heterogeneous/examples/x-spawn.rs @@ -0,0 +1,20 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::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 new file mode 100644 index 00000000..a4f0ec57 --- /dev/null +++ b/heterogeneous/src/lib.rs @@ -0,0 +1,94 @@ +//! Fake multi-core PAC + +#![no_std] + +use core::{ + cmp::Ordering, + ops::{Add, Sub}, +}; + +use bare_metal::Nr; +use rtfm::Monotonic; + +// 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; + +unsafe impl Monotonic for MT { + type Instant = Instant; + + fn ratio() -> u32 { + 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) + } +} + +#[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 new file mode 100644 index 00000000..210ee2e8 --- /dev/null +++ b/homogeneous/Cargo.toml @@ -0,0 +1,17 @@ +[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-rtfm] +path = ".." +features = ["homogeneous"] + +[dev-dependencies] +panic-halt = "0.2.0" diff --git a/homogeneous/README.md b/homogeneous/README.md new file mode 100644 index 00000000..17e9c6e1 --- /dev/null +++ b/homogeneous/README.md @@ -0,0 +1 @@ +This directory contains *homogeneous* multi-core compile pass tests. diff --git a/homogeneous/examples/smallest.rs b/homogeneous/examples/smallest.rs new file mode 100644 index 00000000..b99476c7 --- /dev/null +++ b/homogeneous/examples/smallest.rs @@ -0,0 +1,7 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = homogeneous)] +const APP: () = {}; diff --git a/homogeneous/examples/x-init-2.rs b/homogeneous/examples/x-init-2.rs new file mode 100644 index 00000000..f51e2f6e --- /dev/null +++ b/homogeneous/examples/x-init-2.rs @@ -0,0 +1,39 @@ +//! [compile-pass] Cross initialization of late resources + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = homogeneous)] +const APP: () = { + extern "C" { + // owned by core #1 but initialized by core #0 + static mut X: u32; + + // owned by core #0 but initialized by core #1 + static mut 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 new file mode 100644 index 00000000..5089e385 --- /dev/null +++ b/homogeneous/examples/x-init.rs @@ -0,0 +1,26 @@ +//! [compile-pass] Split initialization of late resources + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(cores = 2, device = homogeneous)] +const APP: () = { + extern "C" { + static mut X: u32; + static mut 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 new file mode 100644 index 00000000..12b5cb80 --- /dev/null +++ b/homogeneous/examples/x-schedule.rs @@ -0,0 +1,36 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::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 new file mode 100644 index 00000000..a76ac61c --- /dev/null +++ b/homogeneous/examples/x-spawn.rs @@ -0,0 +1,20 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::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 new file mode 100644 index 00000000..a4f0ec57 --- /dev/null +++ b/homogeneous/src/lib.rs @@ -0,0 +1,94 @@ +//! Fake multi-core PAC + +#![no_std] + +use core::{ + cmp::Ordering, + ops::{Add, Sub}, +}; + +use bare_metal::Nr; +use rtfm::Monotonic; + +// 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; + +unsafe impl Monotonic for MT { + type Instant = Instant; + + fn ratio() -> u32 { + 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) + } +} + +#[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/macros/Cargo.toml b/macros/Cargo.toml index 2854dad4..c4e897fa 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -24,3 +24,4 @@ git = "https://github.com/japaric/rtfm-syntax" [features] heterogeneous = [] +homogeneous = [] diff --git a/macros/src/check.rs b/macros/src/check.rs index c22a0f1f..619ec8fb 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -20,6 +20,28 @@ impl<'a> Extra<'a> { } pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result> { + if cfg!(feature = "homogeneous") { + // this RTFM 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 diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 86b4a67e..92766260 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -67,10 +67,11 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { )); let cfg_core = util::cfg_core(core, app.args.cores); + let main = util::suffixed("main", core); mains.push(quote!( #[no_mangle] #cfg_core - unsafe fn main() -> ! { + unsafe extern "C" fn #main() -> ! { #(#assertion_stmts)* #(#pre_init_stmts)* diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index 65d25c78..988e3c84 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -55,8 +55,14 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec), quote!(rtfm::export::Queue(rtfm::export::iQueue::u8())), ) @@ -156,7 +162,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec util::cfg_core(*core, app.args.cores), // shared `static`s and cross-initialized resources need to be in `.shared` memory - _ => Some(quote!(#[rtfm::export::shared])), + _ => { + if cfg!(feature = "heterogeneous") { + Some(quote!(#[rtfm::export::shared])) + } else { + None + } + } }; let (ty, expr) = if let Some(expr) = expr { diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 8b2c0cd5..383a5d82 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -52,8 +52,14 @@ pub fn codegen( })), ) } else { + let shared = if cfg!(feature = "heterogeneous") { + Some(quote!(#[rtfm::export::shared])) + } else { + None + }; + ( - Some(quote!(#[rtfm::export::shared])), + shared, quote!(rtfm::export::MCFQ<#cap_ty>), quote!(rtfm::export::Queue(rtfm::export::iQueue::u8())), ) diff --git a/macros/src/codegen/spawn_body.rs b/macros/src/codegen/spawn_body.rs index 83cb5c0a..98bce074 100644 --- a/macros/src/codegen/spawn_body.rs +++ b/macros/src/codegen/spawn_body.rs @@ -45,14 +45,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::Interrupt::#interrupt); + #device::xpend(#receiver, #device::#enum_::#interrupt); ) } else { quote!( - rtfm::pend(#device::Interrupt::#interrupt); + rtfm::pend(#device::#enum_::#interrupt); ) }; diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index cb845774..d306ed5b 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -89,15 +89,16 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec Vec>(); let priority = timer_queue.priority; + let sys_tick = util::suffixed("SysTick", sender); items.push(quote!( #cfg_sender #[no_mangle] - unsafe fn SysTick() { + unsafe fn #sys_tick() { use rtfm::Mutex as _; /// The priority of this handler diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 203fcee8..8c43b350 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -27,9 +27,11 @@ pub fn capacity_typenum(capacity: u8, round_up_to_power_of_two: bool) -> TokenSt pub fn cfg_core(core: Core, cores: u8) -> Option { if cores == 1 { None - } else { + } else if cfg!(feature = "heterogeneous") { let core = core.to_string(); Some(quote!(#[cfg(core = #core)])) + } else { + None } } @@ -102,6 +104,15 @@ pub fn instants_ident(task: &Ident, sender: Core) -> Ident { Ident::new(&format!("{}_S{}_INSTANTS", task, sender), Span::call_site()) } +pub fn interrupt_ident(core: Core, cores: u8) -> Ident { + let span = Span::call_site(); + if cores == 1 { + Ident::new("Interrupt", span) + } else { + Ident::new(&format!("Interrupt_{}", core), span) + } +} + /// Generates a pre-reexport identifier for the "late resources" struct pub fn late_resources_ident(init: &Ident) -> Ident { Ident::new( @@ -245,6 +256,16 @@ pub fn spawn_t_ident(receiver: Core, priority: u8, sender: Core) -> Ident { ) } +pub fn suffixed(name: &str, core: u8) -> Ident { + let span = Span::call_site(); + + if cfg!(feature = "homogeneous") { + Ident::new(&format!("{}_{}", name, core), span) + } else { + Ident::new(name, span) + } +} + /// Generates an identifier for a timer queue /// /// At most there's one timer queue per core diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 6e1a7978..6502d9ca 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -20,7 +20,7 @@ pub fn app(args: TokenStream, input: TokenStream) -> TokenStream { args, input, Settings { - parse_cores: cfg!(feature = "heterogeneous"), + parse_cores: cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous"), parse_exception: true, parse_extern_interrupt: true, parse_interrupt: true, diff --git a/mc/Cargo.toml b/mc/Cargo.toml deleted file mode 100644 index 7c75335d..00000000 --- a/mc/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -authors = ["Jorge Aparicio "] -edition = "2018" -name = "mc" -# this crate is only used for testing -publish = false -version = "0.0.0-alpha.0" - -[dependencies] -cortex-m = "0.6.0" - -[dependencies.cortex-m-rtfm] -path = ".." -features = ["heterogeneous"] - -[dev-dependencies] -panic-halt = "0.2.0" -microamp = "0.1.0-alpha.1" diff --git a/mc/README.md b/mc/README.md deleted file mode 100644 index e1335bbf..00000000 --- a/mc/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory contains multi-core compile pass tests. diff --git a/mc/examples/smallest.rs b/mc/examples/smallest.rs deleted file mode 100644 index 792935a8..00000000 --- a/mc/examples/smallest.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtfm::app(cores = 2, device = mc)] -const APP: () = {}; diff --git a/mc/examples/x-init-2.rs b/mc/examples/x-init-2.rs deleted file mode 100644 index ff48b110..00000000 --- a/mc/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 _; - -#[rtfm::app(cores = 2, device = mc)] -const APP: () = { - extern "C" { - // owned by core #1 but initialized by core #0 - static mut X: u32; - - // owned by core #0 but initialized by core #1 - static mut 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/mc/examples/x-init.rs b/mc/examples/x-init.rs deleted file mode 100644 index 3f26c5c9..00000000 --- a/mc/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 _; - -#[rtfm::app(cores = 2, device = mc)] -const APP: () = { - extern "C" { - static mut X: u32; - static mut 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/mc/examples/x-schedule.rs b/mc/examples/x-schedule.rs deleted file mode 100644 index 76e70acf..00000000 --- a/mc/examples/x-schedule.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtfm::app(cores = 2, device = mc, monotonic = mc::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/mc/examples/x-spawn.rs b/mc/examples/x-spawn.rs deleted file mode 100644 index 749918fd..00000000 --- a/mc/examples/x-spawn.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![no_main] -#![no_std] - -use panic_halt as _; - -#[rtfm::app(cores = 2, device = mc)] -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/mc/src/lib.rs b/mc/src/lib.rs deleted file mode 100644 index d86c0e8e..00000000 --- a/mc/src/lib.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! Fake multi-core PAC - -#![no_std] - -use core::{ - cmp::Ordering, - ops::{Add, Sub}, -}; - -use cortex_m::interrupt::Nr; -use rtfm::Monotonic; - -// Fake priority bits -pub const NVIC_PRIO_BITS: u8 = 3; - -pub struct CrossPend; - -pub fn xpend(_core: u8, _interrupt: impl Nr) {} - -/// Fake monotonic timer -pub struct MT; - -unsafe impl Monotonic for MT { - type Instant = Instant; - - fn ratio() -> u32 { - 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) - } -} - -#[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 -pub enum Interrupt { - I0, - I1, - I2, - I3, - I4, - I5, - I6, - I7, -} - -unsafe impl Nr for Interrupt { - fn nr(&self) -> u8 { - match self { - Interrupt::I0 => 0, - Interrupt::I1 => 1, - Interrupt::I2 => 2, - Interrupt::I3 => 3, - Interrupt::I4 => 4, - Interrupt::I5 => 5, - Interrupt::I6 => 6, - Interrupt::I7 => 7, - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 73e6e200..acb3a63d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,7 @@ use cortex_m::{ interrupt::Nr, peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU}, }; -#[cfg(not(feature = "heterogeneous"))] +#[cfg(all(not(feature = "heterogeneous"), not(feature = "homogeneous")))] use cortex_m_rt as _; // vector table pub use cortex_m_rtfm_macros::app; pub use rtfm_core::{Exclusive, Mutex}; -- cgit v1.2.3