From 0dcb0c4e497b23bf68b7ac0d3d918ab3d3c209be Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 31 Oct 2021 10:09:40 +0100 Subject: [PATCH 1/2] New monotonic trait working --- Cargo.toml | 5 ++- examples/cancel-reschedule.rs | 11 +++--- examples/common.rs | 7 ++-- examples/periodic.rs | 7 ++-- examples/schedule.rs | 9 ++--- examples/t-schedule.rs | 57 ++++++++++++---------------- macros/src/codegen.rs | 15 ++------ macros/src/codegen/module.rs | 30 ++++++--------- macros/src/codegen/software_tasks.rs | 2 +- src/lib.rs | 2 +- src/tq.rs | 27 +++---------- 11 files changed, 66 insertions(+), 106 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index baf287cc10..7cdf7f94c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ name = "rtic" [dependencies] cortex-m = "0.7.0" cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.3" } -rtic-monotonic = "0.1.0-rc.1" +# rtic-monotonic = "0.1.0-rc.1" +rtic-monotonic = { git = "https://github.com/rtic-rs/rtic-monotonic.git", branch = "master" } rtic-core = "0.3.1" heapless = "0.7.7" bare-metal = "1.0.0" @@ -33,7 +34,7 @@ version_check = "0.9" [dev-dependencies] lm3s6965 = "0.1.3" cortex-m-semihosting = "0.3.3" -systick-monotonic = "0.1.0-rc.1" +systick-monotonic = { git = "https://github.com/rtic-rs/systick-monotonic.git", branch = "new-trait-and-time-lib" } [dev-dependencies.panic-semihosting] features = ["exit"] diff --git a/examples/cancel-reschedule.rs b/examples/cancel-reschedule.rs index c5ef2e739d..e0bdaae80e 100644 --- a/examples/cancel-reschedule.rs +++ b/examples/cancel-reschedule.rs @@ -10,8 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; - use rtic::time::duration::*; - use systick_monotonic::Systick; + use systick_monotonic::*; #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<100>; // 100 Hz / 10 ms granularity @@ -32,7 +31,7 @@ mod app { hprintln!("init").ok(); // Schedule `foo` to run 1 second in the future - foo::spawn_after(1.seconds()).unwrap(); + foo::spawn_after(1.secs()).unwrap(); ( Shared {}, @@ -46,8 +45,8 @@ mod app { hprintln!("foo").ok(); // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) - let spawn_handle = baz::spawn_after(2.seconds()).unwrap(); - bar::spawn_after(1.seconds(), spawn_handle, false).unwrap(); // Change to true + let spawn_handle = baz::spawn_after(2.secs()).unwrap(); + bar::spawn_after(1.secs(), spawn_handle, false).unwrap(); // Change to true } #[task] @@ -57,7 +56,7 @@ mod app { if do_reschedule { // Reschedule baz 2 seconds from now, instead of the original 1 second // from now. - baz_handle.reschedule_after(2.seconds()).unwrap(); + baz_handle.reschedule_after(2.secs()).unwrap(); // Or baz_handle.reschedule_at(/* time */) } else { // Or cancel it diff --git a/examples/common.rs b/examples/common.rs index 770a0ae557..26a5c8fb33 100644 --- a/examples/common.rs +++ b/examples/common.rs @@ -10,8 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; - use rtic::time::duration::*; - use systick_monotonic::Systick; // Implements the `Monotonic` trait // Time helpers, such as `N.seconds()` + use systick_monotonic::*; // Implements the `Monotonic` trait // A monotonic timer to enable scheduling in RTIC #[monotonic(binds = SysTick, default = true)] @@ -41,7 +40,7 @@ mod app { // Spawn the task `bar` 1 second after `init` finishes, this is enabled // by the `#[monotonic(..)]` above - bar::spawn_after(1.seconds()).unwrap(); + bar::spawn_after(1.secs()).unwrap(); debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator @@ -83,7 +82,7 @@ mod app { hprintln!("bar").ok(); // Run `bar` once per second - bar::spawn_after(1.seconds()).unwrap(); + bar::spawn_after(1.secs()).unwrap(); } // Hardware task, bound to a hardware interrupt diff --git a/examples/periodic.rs b/examples/periodic.rs index 3066def722..495054ea42 100644 --- a/examples/periodic.rs +++ b/examples/periodic.rs @@ -10,8 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; - use rtic::time::duration::*; - use systick_monotonic::Systick; + use systick_monotonic::*; #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<100>; // 100 Hz / 10 ms granularity @@ -28,7 +27,7 @@ mod app { let mono = Systick::new(systick, 12_000_000); - foo::spawn_after(1.seconds()).unwrap(); + foo::spawn_after(1.secs()).unwrap(); (Shared {}, Local {}, init::Monotonics(mono)) } @@ -43,6 +42,6 @@ mod app { } // Periodic ever 1 seconds - foo::spawn_after(1.seconds()).unwrap(); + foo::spawn_after(1.secs()).unwrap(); } } diff --git a/examples/schedule.rs b/examples/schedule.rs index 669c67c967..446a382892 100644 --- a/examples/schedule.rs +++ b/examples/schedule.rs @@ -10,8 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; - use rtic::time::duration::*; - use systick_monotonic::Systick; + use systick_monotonic::*; #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<100>; // 100 Hz / 10 ms granularity @@ -32,7 +31,7 @@ mod app { hprintln!("init").ok(); // Schedule `foo` to run 1 second in the future - foo::spawn_after(1.seconds()).unwrap(); + foo::spawn_after(1.secs()).unwrap(); ( Shared {}, @@ -46,7 +45,7 @@ mod app { hprintln!("foo").ok(); // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) - bar::spawn_after(1.seconds()).unwrap(); + bar::spawn_after(1.secs()).unwrap(); } #[task] @@ -54,7 +53,7 @@ mod app { hprintln!("bar").ok(); // Schedule `baz` to run 1 seconds from now, but with a specific time instant. - baz::spawn_at(monotonics::now() + 1.seconds()).unwrap(); + baz::spawn_at(monotonics::now() + 1.secs()).unwrap(); } #[task] diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs index 5530ec6a8b..6ee08afbe9 100644 --- a/examples/t-schedule.rs +++ b/examples/t-schedule.rs @@ -10,8 +10,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::debug; - use rtic::time::duration::Seconds; - use systick_monotonic::Systick; + use systick_monotonic::*; #[monotonic(binds = SysTick, default = true)] type MyMono = Systick<100>; // 100 Hz / 10 ms granularity @@ -40,27 +39,26 @@ mod app { // Not default let _: Result = foo::MyMono::spawn_at(monotonics::MyMono::now()); - let handle: Result = foo::MyMono::spawn_after(Seconds(1_u32)); - let _: Result = - handle.unwrap().reschedule_after(Seconds(1_u32)); + let handle: Result = foo::MyMono::spawn_after(1.secs()); + let _: Result = handle.unwrap().reschedule_after(1.secs()); - let handle: Result = foo::MyMono::spawn_after(Seconds(1_u32)); + let handle: Result = foo::MyMono::spawn_after(1.secs()); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); - let handle: Result = foo::MyMono::spawn_after(Seconds(1_u32)); + let handle: Result = foo::MyMono::spawn_after(1.secs()); let _: Result<(), ()> = handle.unwrap().cancel(); // Using default let _: Result = foo::spawn_at(monotonics::now()); - let handle: Result = foo::spawn_after(Seconds(1_u32)); - let _: Result = handle.unwrap().reschedule_after(Seconds(1_u32)); + let handle: Result = foo::spawn_after(1.secs()); + let _: Result = handle.unwrap().reschedule_after(1.secs()); - let handle: Result = foo::spawn_after(Seconds(1_u32)); + let handle: Result = foo::spawn_after(1.secs()); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); - let handle: Result = foo::spawn_after(Seconds(1_u32)); + let handle: Result = foo::spawn_after(1.secs()); let _: Result<(), ()> = handle.unwrap().cancel(); // Task with single message passing @@ -68,30 +66,26 @@ mod app { // Not default let _: Result = bar::MyMono::spawn_at(monotonics::MyMono::now(), 0); - let handle: Result = - bar::MyMono::spawn_after(Seconds(1_u32), 0); - let _: Result = - handle.unwrap().reschedule_after(Seconds(1_u32)); + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().reschedule_after(1.secs()); - let handle: Result = - bar::MyMono::spawn_after(Seconds(1_u32), 0); + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); - let handle: Result = - bar::MyMono::spawn_after(Seconds(1_u32), 0); + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); let _: Result = handle.unwrap().cancel(); // Using default let _: Result = bar::spawn_at(monotonics::MyMono::now(), 0); - let handle: Result = bar::spawn_after(Seconds(1_u32), 0); - let _: Result = handle.unwrap().reschedule_after(Seconds(1_u32)); + let handle: Result = bar::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().reschedule_after(1.secs()); - let handle: Result = bar::spawn_after(Seconds(1_u32), 0); + let handle: Result = bar::spawn_after(1.secs(), 1); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); - let handle: Result = bar::spawn_after(Seconds(1_u32), 0); + let handle: Result = bar::spawn_after(1.secs(), 1); let _: Result = handle.unwrap().cancel(); // Task with multiple message passing @@ -100,30 +94,29 @@ mod app { let _: Result = baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1); let handle: Result = - baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); - let _: Result = - handle.unwrap().reschedule_after(Seconds(1_u32)); + baz::MyMono::spawn_after(1.secs(), 1, 2); + let _: Result = handle.unwrap().reschedule_after(1.secs()); let handle: Result = - baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); + baz::MyMono::spawn_after(1.secs(), 1, 2); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); let handle: Result = - baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); + baz::MyMono::spawn_after(1.secs(), 1, 2); let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); // Using default let _: Result = baz::spawn_at(monotonics::MyMono::now(), 0, 1); - let handle: Result = baz::spawn_after(Seconds(1_u32), 0, 1); - let _: Result = handle.unwrap().reschedule_after(Seconds(1_u32)); + let handle: Result = baz::spawn_after(1.secs(), 1, 2); + let _: Result = handle.unwrap().reschedule_after(1.secs()); - let handle: Result = baz::spawn_after(Seconds(1_u32), 0, 1); + let handle: Result = baz::spawn_after(1.secs(), 1, 2); let _: Result = handle.unwrap().reschedule_at(monotonics::MyMono::now()); - let handle: Result = baz::spawn_after(Seconds(1_u32), 0, 1); + let handle: Result = baz::spawn_after(1.secs(), 1, 2); let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); loop { diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index f07326ba47..422de5f37c 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -108,10 +108,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let name = &monotonic.ident; let name_str = &name.to_string(); let ident = util::monotonic_ident(&name_str); - let panic_str = &format!( - "Use of monotonic '{}' before it was passed to the runtime", - name_str - ); let doc = &format!( "This module holds the static implementation for `{}::now()`", name_str @@ -131,18 +127,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { pub mod #name { /// Read the current time from this monotonic - pub fn now() -> rtic::time::Instant { + pub fn now() -> ::Instant { rtic::export::interrupt::free(|_| { use rtic::Monotonic as _; - use rtic::time::Clock as _; if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } { - if let Ok(v) = m.try_now() { - v - } else { - unreachable!("Your monotonic is not infallible!") - } + m.now() } else { - panic!(#panic_str); + ::zero() } }) } diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index c59a814c6e..996af64175 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -266,7 +266,6 @@ pub fn codegen( let tq = util::tq_ident(&monotonic.ident.to_string()); let t = util::schedule_t_ident(); let m = &monotonic.ident; - let mono_type = &monotonic.ident; let m_ident = util::monotonic_ident(&monotonic_name); let m_isr = &monotonic.args.binds; let enum_ = util::interrupt_ident(); @@ -349,15 +348,17 @@ pub fn codegen( } #[inline] - pub fn reschedule_after(self, duration: D) -> Result - where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#mono_type as rtic::time::Clock>::T>, - { + pub fn reschedule_after( + self, + duration: <#m as rtic::Monotonic>::Duration + ) -> Result { self.reschedule_at(monotonics::#m::now() + duration) } - pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result - { + pub fn reschedule_at( + self, + instant: <#m as rtic::Monotonic>::Instant + ) -> Result { rtic::export::interrupt::free(|_| unsafe { let marker = #tq_marker.get().read(); #tq_marker.get_mut().write(marker.wrapping_add(1)); @@ -375,19 +376,12 @@ pub fn codegen( /// This will use the time `Instant::new(0)` as baseline if called in `#[init]`, /// so if you use a non-resetable timer use `spawn_at` when in `#[init]` #[allow(non_snake_case)] - pub fn #internal_spawn_after_ident( - duration: D + pub fn #internal_spawn_after_ident( + duration: <#m as rtic::Monotonic>::Duration #(,#args)* ) -> Result<#name::#m::SpawnHandle, #ty> - where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, - D::T: Into<<#mono_type as rtic::time::Clock>::T>, { - - let instant = if rtic::export::interrupt::free(|_| unsafe { (&*#m_ident.get()).is_none() }) { - rtic::time::Instant::new(0) - } else { - monotonics::#m::now() - }; + let instant = monotonics::#m::now(); #internal_spawn_at_ident(instant + duration #(,#untupled)*) } @@ -396,7 +390,7 @@ pub fn codegen( /// Spawns the task at a fixed time instant #[allow(non_snake_case)] pub fn #internal_spawn_at_ident( - instant: rtic::time::Instant<#mono_type> + instant: <#m as rtic::Monotonic>::Instant #(,#args)* ) -> Result<#name::#m::SpawnHandle, #ty> { unsafe { diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 1669a3fb1e..2008b6c98a 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -73,7 +73,7 @@ pub fn codegen( #[allow(non_upper_case_globals)] #[doc(hidden)] static #instants: - rtic::RacyCell<[core::mem::MaybeUninit>; #cap_lit]> = + rtic::RacyCell<[core::mem::MaybeUninit<<#mono_type as rtic::Monotonic>::Instant>; #cap_lit]> = rtic::RacyCell::new([#(#elems,)*]); )); } diff --git a/src/lib.rs b/src/lib.rs index 8463442acf..c96b53c7f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; pub use cortex_m_rtic_macros::app; pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex}; -pub use rtic_monotonic::{self, embedded_time as time, Monotonic}; +pub use rtic_monotonic::{self, Monotonic}; #[doc(hidden)] pub mod export; diff --git a/src/tq.rs b/src/tq.rs index 44f8dd4cbb..0121de5fe7 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -1,19 +1,7 @@ -use crate::{ - time::{Clock, Instant}, - Monotonic, -}; +use crate::Monotonic; use core::cmp::Ordering; use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList}; -#[inline(always)] -fn unwrapper(val: Result) -> T { - if let Ok(v) = val { - v - } else { - unreachable!("Your monotonic is not infallible") - } -} - pub struct TimerQueue( pub SortedLinkedList, LinkedIndexU16, Min, N>, ) @@ -87,7 +75,7 @@ where &mut self, marker: u32, new_marker: u32, - instant: Instant, + instant: Mono::Instant, pend_handler: F, ) -> Result<(), ()> { if let Some(mut val) = self.0.find_mut(|nr| nr.marker == marker) { @@ -111,23 +99,20 @@ where mono.clear_compare_flag(); if let Some(instant) = self.0.peek().map(|p| p.instant) { - let now = unwrapper(Clock::try_now(mono)); - // This if statement is like this and not <= due to a bug in embedded-time - if instant < now || instant == now { + if instant <= mono.now() { // task became ready let nr = unsafe { self.0.pop_unchecked() }; Some((nr.task, nr.index)) } else { // Set compare - mono.set_compare(&instant); + mono.set_compare(instant); // Double check that the instant we set is really in the future, else // dequeue. If the monotonic is fast enough it can happen that from the // read of now to the set of the compare, the time can overflow. This is to // guard against this. - let now = unwrapper(Clock::try_now(mono)); - if instant < now || instant == now { + if instant <= mono.now() { let nr = unsafe { self.0.pop_unchecked() }; Some((nr.task, nr.index)) @@ -153,7 +138,7 @@ where Mono: Monotonic, { pub index: u8, - pub instant: Instant, + pub instant: Mono::Instant, pub task: Task, pub marker: u32, } From 5ab5112271a9dbef6d875ad89706fc726e126b95 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 9 Nov 2021 10:35:58 +0100 Subject: [PATCH 2/2] Update versions and changelog --- CHANGELOG.md | 6 +++++- Cargo.toml | 9 ++++----- macros/Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c86bb03e07..9ee854ff4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v0.6.0-rc.4] - 2021-11-09 + +- Updated to use the new generic `Monotonic` trait ## [v0.6.0-rc.3] - 2021-11-08 @@ -444,7 +447,8 @@ Yanked due to a soundness issue in `init`; the issue has been mostly fixed in v0 - Initial release -[Unreleased]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.3...HEAD +[Unreleased]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.4...HEAD +[v0.6.0-rc.4]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.3...v0.6.0-rc.4 [v0.6.0-rc.3]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.2...v0.6.0-rc.3 [v0.6.0-rc.2]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.1...v0.6.0-rc.2 [v0.6.0-rc.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.6.0-rc.0...v0.6.0-rc.1 diff --git a/Cargo.toml b/Cargo.toml index 7cdf7f94c4..ed6efbaadd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,16 +14,15 @@ name = "cortex-m-rtic" readme = "README.md" repository = "https://github.com/rtic-rs/cortex-m-rtic" -version = "0.6.0-rc.3" +version = "0.6.0-rc.4" [lib] name = "rtic" [dependencies] cortex-m = "0.7.0" -cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.3" } -# rtic-monotonic = "0.1.0-rc.1" -rtic-monotonic = { git = "https://github.com/rtic-rs/rtic-monotonic.git", branch = "master" } +cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.4" } +rtic-monotonic = "0.1.0-rc.2" rtic-core = "0.3.1" heapless = "0.7.7" bare-metal = "1.0.0" @@ -34,7 +33,7 @@ version_check = "0.9" [dev-dependencies] lm3s6965 = "0.1.3" cortex-m-semihosting = "0.3.3" -systick-monotonic = { git = "https://github.com/rtic-rs/systick-monotonic.git", branch = "new-trait-and-time-lib" } +systick-monotonic = "0.1.0-rc.2" [dev-dependencies.panic-semihosting] features = ["exit"] diff --git a/macros/Cargo.toml b/macros/Cargo.toml index de335bc444..394c17753f 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0" name = "cortex-m-rtic-macros" readme = "../README.md" repository = "https://github.com/rtic-rs/cortex-m-rtic" -version = "0.6.0-rc.3" +version = "0.6.0-rc.4" [lib] proc-macro = true