From 596cf585ea8dc278d88e0652dffbacbc75de04c6 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 24 Jun 2019 14:09:12 +0200 Subject: [PATCH] Monotonic trait is safe; add MultiCore trait --- heterogeneous/src/lib.rs | 6 ++++-- homogeneous/src/lib.rs | 6 ++++-- macros/src/codegen.rs | 2 +- macros/src/codegen/assertions.rs | 11 +++++++++-- src/cyccnt.rs | 7 ++++++- src/export.rs | 7 +++++++ src/lib.rs | 5 ++++- 7 files changed, 35 insertions(+), 9 deletions(-) diff --git a/heterogeneous/src/lib.rs b/heterogeneous/src/lib.rs index a4f0ec570e..3288bfe012 100644 --- a/heterogeneous/src/lib.rs +++ b/heterogeneous/src/lib.rs @@ -8,7 +8,7 @@ use core::{ }; use bare_metal::Nr; -use rtfm::Monotonic; +use rtfm::{Monotonic, MultiCore}; // both cores have the exact same interrupts pub use Interrupt_0 as Interrupt_1; @@ -21,7 +21,7 @@ pub fn xpend(_core: u8, _interrupt: impl Nr) {} /// Fake monotonic timer pub struct MT; -unsafe impl Monotonic for MT { +impl Monotonic for MT { type Instant = Instant; fn ratio() -> u32 { @@ -41,6 +41,8 @@ unsafe impl Monotonic for MT { } } +impl MultiCore for MT {} + #[derive(Clone, Copy, Eq, PartialEq)] pub struct Instant(i32); diff --git a/homogeneous/src/lib.rs b/homogeneous/src/lib.rs index a4f0ec570e..3288bfe012 100644 --- a/homogeneous/src/lib.rs +++ b/homogeneous/src/lib.rs @@ -8,7 +8,7 @@ use core::{ }; use bare_metal::Nr; -use rtfm::Monotonic; +use rtfm::{Monotonic, MultiCore}; // both cores have the exact same interrupts pub use Interrupt_0 as Interrupt_1; @@ -21,7 +21,7 @@ pub fn xpend(_core: u8, _interrupt: impl Nr) {} /// Fake monotonic timer pub struct MT; -unsafe impl Monotonic for MT { +impl Monotonic for MT { type Instant = Instant; fn ratio() -> u32 { @@ -41,6 +41,8 @@ unsafe impl Monotonic for MT { } } +impl MultiCore for MT {} + #[derive(Clone, Copy, Eq, PartialEq)] pub struct Instant(i32); diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 927662606c..a3515994bf 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -32,7 +32,7 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { // generate a `main` function for each core for core in 0..app.args.cores { - let assertion_stmts = assertions::codegen(core, analysis); + let assertion_stmts = assertions::codegen(core, analysis, extra); let (const_app_pre_init, pre_init_stmts) = pre_init::codegen(core, &app, analysis, extra); diff --git a/macros/src/codegen/assertions.rs b/macros/src/codegen/assertions.rs index 95268a2cf4..4a77352f57 100644 --- a/macros/src/codegen/assertions.rs +++ b/macros/src/codegen/assertions.rs @@ -1,10 +1,10 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use crate::analyze::Analysis; +use crate::{analyze::Analysis, check::Extra}; /// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits -pub fn codegen(core: u8, analysis: &Analysis) -> Vec { +pub fn codegen(core: u8, analysis: &Analysis, extra: &Extra) -> Vec { let mut stmts = vec![]; // we don't generate *all* assertions on all cores because the user could conditionally import a @@ -22,5 +22,12 @@ pub fn codegen(core: u8, analysis: &Analysis) -> Vec { } } + // 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!(rtfm::export::assert_multicore::<#monotonic>();)); + } + stmts } diff --git a/src/cyccnt.rs b/src/cyccnt.rs index a2b216c179..468aa712b6 100644 --- a/src/cyccnt.rs +++ b/src/cyccnt.rs @@ -116,6 +116,11 @@ pub struct Duration { } impl Duration { + /// Creates a new `Duration` from the specified number of clock cycles + pub fn from_cycles(cycles: u32) -> Self { + Duration { inner: cycles } + } + /// Returns the total number of clock cycles contained by this `Duration` pub fn as_cycles(&self) -> u32 { self.inner @@ -181,7 +186,7 @@ impl U32Ext for u32 { pub struct CYCCNT; #[cfg(not(feature = "heterogeneous"))] -unsafe impl crate::Monotonic for CYCCNT { +impl crate::Monotonic for CYCCNT { type Instant = Instant; fn ratio() -> u32 { diff --git a/src/export.rs b/src/export.rs index 7646e3c504..572068ce22 100644 --- a/src/export.rs +++ b/src/export.rs @@ -108,6 +108,13 @@ 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 acb3a63db3..decd2da1b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,7 +117,7 @@ impl From for Peripherals { } /// A monotonic clock / counter -pub unsafe trait Monotonic { +pub trait Monotonic { /// A measurement of this clock type Instant: Copy + Ord + Sub; @@ -134,6 +134,9 @@ pub unsafe 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