New monotonic trait working

This commit is contained in:
Emil Fresk 2021-10-31 10:09:40 +01:00
parent ae034aec14
commit 0dcb0c4e49
11 changed files with 66 additions and 106 deletions

View file

@ -22,7 +22,8 @@ name = "rtic"
[dependencies] [dependencies]
cortex-m = "0.7.0" cortex-m = "0.7.0"
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.3" } 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" rtic-core = "0.3.1"
heapless = "0.7.7" heapless = "0.7.7"
bare-metal = "1.0.0" bare-metal = "1.0.0"
@ -33,7 +34,7 @@ version_check = "0.9"
[dev-dependencies] [dev-dependencies]
lm3s6965 = "0.1.3" lm3s6965 = "0.1.3"
cortex-m-semihosting = "0.3.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] [dev-dependencies.panic-semihosting]
features = ["exit"] features = ["exit"]

View file

@ -10,8 +10,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] #[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app { mod app {
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use rtic::time::duration::*; use systick_monotonic::*;
use systick_monotonic::Systick;
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
@ -32,7 +31,7 @@ mod app {
hprintln!("init").ok(); hprintln!("init").ok();
// Schedule `foo` to run 1 second in the future // Schedule `foo` to run 1 second in the future
foo::spawn_after(1.seconds()).unwrap(); foo::spawn_after(1.secs()).unwrap();
( (
Shared {}, Shared {},
@ -46,8 +45,8 @@ mod app {
hprintln!("foo").ok(); hprintln!("foo").ok();
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs) // Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
let spawn_handle = baz::spawn_after(2.seconds()).unwrap(); let spawn_handle = baz::spawn_after(2.secs()).unwrap();
bar::spawn_after(1.seconds(), spawn_handle, false).unwrap(); // Change to true bar::spawn_after(1.secs(), spawn_handle, false).unwrap(); // Change to true
} }
#[task] #[task]
@ -57,7 +56,7 @@ mod app {
if do_reschedule { if do_reschedule {
// Reschedule baz 2 seconds from now, instead of the original 1 second // Reschedule baz 2 seconds from now, instead of the original 1 second
// from now. // from now.
baz_handle.reschedule_after(2.seconds()).unwrap(); baz_handle.reschedule_after(2.secs()).unwrap();
// Or baz_handle.reschedule_at(/* time */) // Or baz_handle.reschedule_at(/* time */)
} else { } else {
// Or cancel it // Or cancel it

View file

@ -10,8 +10,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] #[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
mod app { mod app {
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use rtic::time::duration::*; use systick_monotonic::*; // Implements the `Monotonic` trait
use systick_monotonic::Systick; // Implements the `Monotonic` trait // Time helpers, such as `N.seconds()`
// A monotonic timer to enable scheduling in RTIC // A monotonic timer to enable scheduling in RTIC
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
@ -41,7 +40,7 @@ mod app {
// Spawn the task `bar` 1 second after `init` finishes, this is enabled // Spawn the task `bar` 1 second after `init` finishes, this is enabled
// by the `#[monotonic(..)]` above // by the `#[monotonic(..)]` above
bar::spawn_after(1.seconds()).unwrap(); bar::spawn_after(1.secs()).unwrap();
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
@ -83,7 +82,7 @@ mod app {
hprintln!("bar").ok(); hprintln!("bar").ok();
// Run `bar` once per second // Run `bar` once per second
bar::spawn_after(1.seconds()).unwrap(); bar::spawn_after(1.secs()).unwrap();
} }
// Hardware task, bound to a hardware interrupt // Hardware task, bound to a hardware interrupt

View file

@ -10,8 +10,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] #[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app { mod app {
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use rtic::time::duration::*; use systick_monotonic::*;
use systick_monotonic::Systick;
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
@ -28,7 +27,7 @@ mod app {
let mono = Systick::new(systick, 12_000_000); 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)) (Shared {}, Local {}, init::Monotonics(mono))
} }
@ -43,6 +42,6 @@ mod app {
} }
// Periodic ever 1 seconds // Periodic ever 1 seconds
foo::spawn_after(1.seconds()).unwrap(); foo::spawn_after(1.secs()).unwrap();
} }
} }

View file

@ -10,8 +10,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] #[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app { mod app {
use cortex_m_semihosting::{debug, hprintln}; use cortex_m_semihosting::{debug, hprintln};
use rtic::time::duration::*; use systick_monotonic::*;
use systick_monotonic::Systick;
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
@ -32,7 +31,7 @@ mod app {
hprintln!("init").ok(); hprintln!("init").ok();
// Schedule `foo` to run 1 second in the future // Schedule `foo` to run 1 second in the future
foo::spawn_after(1.seconds()).unwrap(); foo::spawn_after(1.secs()).unwrap();
( (
Shared {}, Shared {},
@ -46,7 +45,7 @@ mod app {
hprintln!("foo").ok(); hprintln!("foo").ok();
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs) // 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] #[task]
@ -54,7 +53,7 @@ mod app {
hprintln!("bar").ok(); hprintln!("bar").ok();
// Schedule `baz` to run 1 seconds from now, but with a specific time instant. // 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] #[task]

View file

@ -10,8 +10,7 @@ use panic_semihosting as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] #[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app { mod app {
use cortex_m_semihosting::debug; use cortex_m_semihosting::debug;
use rtic::time::duration::Seconds; use systick_monotonic::*;
use systick_monotonic::Systick;
#[monotonic(binds = SysTick, default = true)] #[monotonic(binds = SysTick, default = true)]
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
@ -40,27 +39,26 @@ mod app {
// Not default // Not default
let _: Result<foo::MyMono::SpawnHandle, ()> = let _: Result<foo::MyMono::SpawnHandle, ()> =
foo::MyMono::spawn_at(monotonics::MyMono::now()); foo::MyMono::spawn_at(monotonics::MyMono::now());
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32)); let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
let _: Result<foo::MyMono::SpawnHandle, ()> = let _: Result<foo::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
handle.unwrap().reschedule_after(Seconds(1_u32));
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32)); let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
let _: Result<foo::MyMono::SpawnHandle, ()> = let _: Result<foo::MyMono::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32)); let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
let _: Result<(), ()> = handle.unwrap().cancel(); let _: Result<(), ()> = handle.unwrap().cancel();
// Using default // Using default
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::now()); let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::now());
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32)); let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32)); let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32)); let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
let _: Result<foo::SpawnHandle, ()> = let _: Result<foo::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32)); let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
let _: Result<(), ()> = handle.unwrap().cancel(); let _: Result<(), ()> = handle.unwrap().cancel();
// Task with single message passing // Task with single message passing
@ -68,30 +66,26 @@ mod app {
// Not default // Not default
let _: Result<bar::MyMono::SpawnHandle, u32> = let _: Result<bar::MyMono::SpawnHandle, u32> =
bar::MyMono::spawn_at(monotonics::MyMono::now(), 0); bar::MyMono::spawn_at(monotonics::MyMono::now(), 0);
let handle: Result<bar::MyMono::SpawnHandle, u32> = let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
bar::MyMono::spawn_after(Seconds(1_u32), 0); let _: Result<bar::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
let _: Result<bar::MyMono::SpawnHandle, ()> =
handle.unwrap().reschedule_after(Seconds(1_u32));
let handle: Result<bar::MyMono::SpawnHandle, u32> = let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
bar::MyMono::spawn_after(Seconds(1_u32), 0);
let _: Result<bar::MyMono::SpawnHandle, ()> = let _: Result<bar::MyMono::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<bar::MyMono::SpawnHandle, u32> = let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
bar::MyMono::spawn_after(Seconds(1_u32), 0);
let _: Result<u32, ()> = handle.unwrap().cancel(); let _: Result<u32, ()> = handle.unwrap().cancel();
// Using default // Using default
let _: Result<bar::SpawnHandle, u32> = bar::spawn_at(monotonics::MyMono::now(), 0); let _: Result<bar::SpawnHandle, u32> = bar::spawn_at(monotonics::MyMono::now(), 0);
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0); let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32)); let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0); let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
let _: Result<bar::SpawnHandle, ()> = let _: Result<bar::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0); let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
let _: Result<u32, ()> = handle.unwrap().cancel(); let _: Result<u32, ()> = handle.unwrap().cancel();
// Task with multiple message passing // Task with multiple message passing
@ -100,30 +94,29 @@ mod app {
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> = let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1); baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1);
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> = let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); baz::MyMono::spawn_after(1.secs(), 1, 2);
let _: Result<baz::MyMono::SpawnHandle, ()> = let _: Result<baz::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
handle.unwrap().reschedule_after(Seconds(1_u32));
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> = let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); baz::MyMono::spawn_after(1.secs(), 1, 2);
let _: Result<baz::MyMono::SpawnHandle, ()> = let _: Result<baz::MyMono::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> = let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); baz::MyMono::spawn_after(1.secs(), 1, 2);
let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
// Using default // Using default
let _: Result<baz::SpawnHandle, (u32, u32)> = let _: Result<baz::SpawnHandle, (u32, u32)> =
baz::spawn_at(monotonics::MyMono::now(), 0, 1); baz::spawn_at(monotonics::MyMono::now(), 0, 1);
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1); let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(1.secs(), 1, 2);
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32)); let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1); let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(1.secs(), 1, 2);
let _: Result<baz::SpawnHandle, ()> = let _: Result<baz::SpawnHandle, ()> =
handle.unwrap().reschedule_at(monotonics::MyMono::now()); handle.unwrap().reschedule_at(monotonics::MyMono::now());
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1); let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(1.secs(), 1, 2);
let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
loop { loop {

View file

@ -108,10 +108,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let name = &monotonic.ident; let name = &monotonic.ident;
let name_str = &name.to_string(); let name_str = &name.to_string();
let ident = util::monotonic_ident(&name_str); 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!( let doc = &format!(
"This module holds the static implementation for `{}::now()`", "This module holds the static implementation for `{}::now()`",
name_str name_str
@ -131,18 +127,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
pub mod #name { pub mod #name {
/// Read the current time from this monotonic /// Read the current time from this monotonic
pub fn now() -> rtic::time::Instant<super::super::#name> { pub fn now() -> <super::super::#name as rtic::Monotonic>::Instant {
rtic::export::interrupt::free(|_| { rtic::export::interrupt::free(|_| {
use rtic::Monotonic as _; use rtic::Monotonic as _;
use rtic::time::Clock as _;
if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } { if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } {
if let Ok(v) = m.try_now() { m.now()
v
} else {
unreachable!("Your monotonic is not infallible!")
}
} else { } else {
panic!(#panic_str); <super::super::#name as rtic::Monotonic>::zero()
} }
}) })
} }

View file

@ -266,7 +266,6 @@ pub fn codegen(
let tq = util::tq_ident(&monotonic.ident.to_string()); let tq = util::tq_ident(&monotonic.ident.to_string());
let t = util::schedule_t_ident(); let t = util::schedule_t_ident();
let m = &monotonic.ident; let m = &monotonic.ident;
let mono_type = &monotonic.ident;
let m_ident = util::monotonic_ident(&monotonic_name); let m_ident = util::monotonic_ident(&monotonic_name);
let m_isr = &monotonic.args.binds; let m_isr = &monotonic.args.binds;
let enum_ = util::interrupt_ident(); let enum_ = util::interrupt_ident();
@ -349,15 +348,17 @@ pub fn codegen(
} }
#[inline] #[inline]
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()> pub fn reschedule_after(
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, self,
D::T: Into<<#mono_type as rtic::time::Clock>::T>, duration: <#m as rtic::Monotonic>::Duration
{ ) -> Result<Self, ()> {
self.reschedule_at(monotonics::#m::now() + duration) self.reschedule_at(monotonics::#m::now() + duration)
} }
pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result<Self, ()> pub fn reschedule_at(
{ self,
instant: <#m as rtic::Monotonic>::Instant
) -> Result<Self, ()> {
rtic::export::interrupt::free(|_| unsafe { rtic::export::interrupt::free(|_| unsafe {
let marker = #tq_marker.get().read(); let marker = #tq_marker.get().read();
#tq_marker.get_mut().write(marker.wrapping_add(1)); #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]`, /// 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]` /// so if you use a non-resetable timer use `spawn_at` when in `#[init]`
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn #internal_spawn_after_ident<D>( pub fn #internal_spawn_after_ident(
duration: D duration: <#m as rtic::Monotonic>::Duration
#(,#args)* #(,#args)*
) -> Result<#name::#m::SpawnHandle, #ty> ) -> 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 = monotonics::#m::now();
let instant = if rtic::export::interrupt::free(|_| unsafe { (&*#m_ident.get()).is_none() }) {
rtic::time::Instant::new(0)
} else {
monotonics::#m::now()
};
#internal_spawn_at_ident(instant + duration #(,#untupled)*) #internal_spawn_at_ident(instant + duration #(,#untupled)*)
} }
@ -396,7 +390,7 @@ pub fn codegen(
/// Spawns the task at a fixed time instant /// Spawns the task at a fixed time instant
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn #internal_spawn_at_ident( pub fn #internal_spawn_at_ident(
instant: rtic::time::Instant<#mono_type> instant: <#m as rtic::Monotonic>::Instant
#(,#args)* #(,#args)*
) -> Result<#name::#m::SpawnHandle, #ty> { ) -> Result<#name::#m::SpawnHandle, #ty> {
unsafe { unsafe {

View file

@ -73,7 +73,7 @@ pub fn codegen(
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
#[doc(hidden)] #[doc(hidden)]
static #instants: static #instants:
rtic::RacyCell<[core::mem::MaybeUninit<rtic::time::Instant<#mono_type>>; #cap_lit]> = rtic::RacyCell<[core::mem::MaybeUninit<<#mono_type as rtic::Monotonic>::Instant>; #cap_lit]> =
rtic::RacyCell::new([#(#elems,)*]); rtic::RacyCell::new([#(#elems,)*]);
)); ));
} }

View file

@ -38,7 +38,7 @@
use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
pub use cortex_m_rtic_macros::app; pub use cortex_m_rtic_macros::app;
pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex}; 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)] #[doc(hidden)]
pub mod export; pub mod export;

View file

@ -1,19 +1,7 @@
use crate::{ use crate::Monotonic;
time::{Clock, Instant},
Monotonic,
};
use core::cmp::Ordering; use core::cmp::Ordering;
use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList}; use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList};
#[inline(always)]
fn unwrapper<T, E>(val: Result<T, E>) -> T {
if let Ok(v) = val {
v
} else {
unreachable!("Your monotonic is not infallible")
}
}
pub struct TimerQueue<Mono, Task, const N: usize>( pub struct TimerQueue<Mono, Task, const N: usize>(
pub SortedLinkedList<NotReady<Mono, Task>, LinkedIndexU16, Min, N>, pub SortedLinkedList<NotReady<Mono, Task>, LinkedIndexU16, Min, N>,
) )
@ -87,7 +75,7 @@ where
&mut self, &mut self,
marker: u32, marker: u32,
new_marker: u32, new_marker: u32,
instant: Instant<Mono>, instant: Mono::Instant,
pend_handler: F, pend_handler: F,
) -> Result<(), ()> { ) -> Result<(), ()> {
if let Some(mut val) = self.0.find_mut(|nr| nr.marker == marker) { if let Some(mut val) = self.0.find_mut(|nr| nr.marker == marker) {
@ -111,23 +99,20 @@ where
mono.clear_compare_flag(); mono.clear_compare_flag();
if let Some(instant) = self.0.peek().map(|p| p.instant) { if let Some(instant) = self.0.peek().map(|p| p.instant) {
let now = unwrapper(Clock::try_now(mono)); if instant <= mono.now() {
// This if statement is like this and not <= due to a bug in embedded-time
if instant < now || instant == now {
// task became ready // task became ready
let nr = unsafe { self.0.pop_unchecked() }; let nr = unsafe { self.0.pop_unchecked() };
Some((nr.task, nr.index)) Some((nr.task, nr.index))
} else { } else {
// Set compare // Set compare
mono.set_compare(&instant); mono.set_compare(instant);
// Double check that the instant we set is really in the future, else // 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 // 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 // read of now to the set of the compare, the time can overflow. This is to
// guard against this. // guard against this.
let now = unwrapper(Clock::try_now(mono)); if instant <= mono.now() {
if instant < now || instant == now {
let nr = unsafe { self.0.pop_unchecked() }; let nr = unsafe { self.0.pop_unchecked() };
Some((nr.task, nr.index)) Some((nr.task, nr.index))
@ -153,7 +138,7 @@ where
Mono: Monotonic, Mono: Monotonic,
{ {
pub index: u8, pub index: u8,
pub instant: Instant<Mono>, pub instant: Mono::Instant,
pub task: Task, pub task: Task,
pub marker: u32, pub marker: u32,
} }