From 3b4c10e790e63ac328a7bdb98451ac11d5935731 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 26 Nov 2020 18:07:22 +0100 Subject: Removed monotonic trait, moved to rtic-core --- src/lib.rs | 44 -------------------------------------------- 1 file changed, 44 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index f1fb550..385b5ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -108,50 +108,6 @@ impl From for Peripherals { } } -/// A fraction -pub struct Fraction { - /// The numerator - pub numerator: u32, - - /// The denominator - pub denominator: u32, -} - -/// A monotonic clock / counter -pub trait Monotonic { - /// A measurement of this clock, use `CYCCNT` as a reference implementation for `Instant`. - /// Note that the Instant must be a signed value such as `i32`. - type Instant: Copy + Ord + Sub; - - /// The ratio between the system timer (SysTick) frequency and this clock frequency, i.e. - /// `Monotonic clock * Fraction = System clock` - /// - /// The ratio must be expressed in *reduced* `Fraction` form to prevent overflows. That is - /// `2 / 3` instead of `4 / 6` - fn ratio() -> Fraction; - - /// Returns the current time - /// - /// # Correctness - /// - /// This function is *allowed* to return nonsensical values if called before `reset` is invoked - /// by the runtime. Therefore application authors should *not* call this function during the - /// `#[init]` phase. - fn now() -> Self::Instant; - - /// Resets the counter to *zero* - /// - /// # Safety - /// - /// This function will be called *exactly once* by the RTIC runtime after `#[init]` returns and - /// before tasks can start; this is also the case in multi-core applications. User code must - /// *never* call this function. - unsafe fn reset(); - - /// A `Self::Instant` that represents a count of *zero* - fn zero() -> Self::Instant; -} - /// Sets the given `interrupt` as pending /// /// This is a convenience function around -- cgit v1.2.3 From ef50aeb2e8245b69843280fabb62589c0716ffdd Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 3 Dec 2020 21:04:06 +0100 Subject: Save, init generation fixed --- src/export.rs | 2 +- src/lib.rs | 68 +------------ src/tq.rs | 312 +++++++++++++++++++++++++++++----------------------------- 3 files changed, 160 insertions(+), 222 deletions(-) (limited to 'src') diff --git a/src/export.rs b/src/export.rs index 72d954a..46793aa 100644 --- a/src/export.rs +++ b/src/export.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -pub use crate::tq::{NotReady, TimerQueue}; +//pub use crate::tq::{NotReady, TimerQueue}; pub use bare_metal::CriticalSection; #[cfg(armv7m)] pub use cortex_m::register::basepri; diff --git a/src/lib.rs b/src/lib.rs index 385b5ea..c1930b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,82 +32,20 @@ #![deny(missing_docs)] #![deny(rust_2018_compatibility)] #![deny(rust_2018_idioms)] -#![deny(warnings)] +// #![deny(warnings)] #![no_std] use core::ops::Sub; -use cortex_m::{ - interrupt::Nr, - peripheral::{CBP, CPUID, DCB, DWT, FPB, FPU, ITM, MPU, NVIC, SCB, TPIU}, -}; +use cortex_m::{interrupt::Nr, peripheral::NVIC}; 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, monotonic::Monotonic, Mutex}; -#[cfg(armv7m)] -pub mod cyccnt; #[doc(hidden)] pub mod export; #[doc(hidden)] mod tq; -/// `cortex_m::Peripherals` minus `SYST` -#[allow(non_snake_case)] -pub struct Peripherals { - /// Cache and branch predictor maintenance operations (not present on Cortex-M0 variants) - pub CBP: CBP, - - /// CPUID - pub CPUID: CPUID, - - /// Debug Control Block - pub DCB: DCB, - - /// Data Watchpoint and Trace unit - pub DWT: DWT, - - /// Flash Patch and Breakpoint unit (not present on Cortex-M0 variants) - pub FPB: FPB, - - /// Floating Point Unit (only present on `thumbv7em-none-eabihf`) - pub FPU: FPU, - - /// Instrumentation Trace Macrocell (not present on Cortex-M0 variants) - pub ITM: ITM, - - /// Memory Protection Unit - pub MPU: MPU, - - /// Nested Vector Interrupt Controller - pub NVIC: NVIC, - - /// System Control Block - pub SCB: SCB, - - // SysTick: System Timer - // pub SYST: SYST, - /// Trace Port Interface Unit (not present on Cortex-M0 variants) - pub TPIU: TPIU, -} - -impl From for Peripherals { - fn from(p: cortex_m::Peripherals) -> Self { - Self { - CBP: p.CBP, - CPUID: p.CPUID, - DCB: p.DCB, - DWT: p.DWT, - FPB: p.FPB, - FPU: p.FPU, - ITM: p.ITM, - MPU: p.MPU, - NVIC: p.NVIC, - SCB: p.SCB, - TPIU: p.TPIU, - } - } -} - /// Sets the given `interrupt` as pending /// /// This is a convenience function around diff --git a/src/tq.rs b/src/tq.rs index b2a84c8..f2539a9 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -1,156 +1,156 @@ -use core::{ - cmp::{self, Ordering}, - convert::TryInto, - mem, - ops::Sub, -}; - -use cortex_m::peripheral::{SCB, SYST}; -use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; - -use crate::Monotonic; - -pub struct TimerQueue(pub BinaryHeap, N, Min>) -where - M: Monotonic, - ::Output: TryInto, - N: ArrayLength>, - T: Copy; - -impl TimerQueue -where - M: Monotonic, - ::Output: TryInto, - N: ArrayLength>, - T: Copy, -{ - /// # Safety - /// - /// Writing to memory with a transmute in order to enable - /// interrupts of the SysTick timer - /// - /// Enqueue a task without checking if it is full - #[inline] - pub unsafe fn enqueue_unchecked(&mut self, nr: NotReady) { - let mut is_empty = true; - // Check if the top contains a non-empty element and if that element is - // greater than nr - let if_heap_max_greater_than_nr = self - .0 - .peek() - .map(|head| { - is_empty = false; - nr.instant < head.instant - }) - .unwrap_or(true); - if if_heap_max_greater_than_nr { - if is_empty { - mem::transmute::<_, SYST>(()).enable_interrupt(); - } - - // Set SysTick pending - SCB::set_pendst(); - } - - self.0.push_unchecked(nr); - } - - /// Dequeue a task from the TimerQueue - #[inline] - pub fn dequeue(&mut self) -> Option<(T, u8)> { - unsafe { - if let Some(instant) = self.0.peek().map(|p| p.instant) { - let now = M::now(); - - if instant < now { - // task became ready - let nr = self.0.pop_unchecked(); - - Some((nr.task, nr.index)) - } else { - // set a new timeout - const MAX: u32 = 0x00ffffff; - - let ratio = M::ratio(); - let dur = match (instant - now).try_into().ok().and_then(|x| { - x.checked_mul(ratio.numerator) - .map(|x| x / ratio.denominator) - }) { - None => MAX, - - // ARM Architecture Reference Manual says: - // "Setting SYST_RVR to zero has the effect of - // disabling the SysTick counter independently - // of the counter enable bit." - Some(0) => 1, - - Some(x) => cmp::min(MAX, x), - }; - mem::transmute::<_, SYST>(()).set_reload(dur); - - // Start counting down from the new reload - mem::transmute::<_, SYST>(()).clear_current(); - - None - } - } else { - // The queue is empty - mem::transmute::<_, SYST>(()).disable_interrupt(); - - None - } - } - } -} - -pub struct NotReady -where - T: Copy, - M: Monotonic, - ::Output: TryInto, -{ - pub index: u8, - pub instant: M::Instant, - pub task: T, -} - -impl Eq for NotReady -where - T: Copy, - M: Monotonic, - ::Output: TryInto, -{ -} - -impl Ord for NotReady -where - T: Copy, - M: Monotonic, - ::Output: TryInto, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.instant.cmp(&other.instant) - } -} - -impl PartialEq for NotReady -where - T: Copy, - M: Monotonic, - ::Output: TryInto, -{ - fn eq(&self, other: &Self) -> bool { - self.instant == other.instant - } -} - -impl PartialOrd for NotReady -where - T: Copy, - M: Monotonic, - ::Output: TryInto, -{ - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(&other)) - } -} +// use core::{ +// cmp::{self, Ordering}, +// convert::TryInto, +// mem, +// ops::Sub, +// }; +// +// use cortex_m::peripheral::{SCB, SYST}; +// use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; +// +// use crate::Monotonic; +// +// pub struct TimerQueue(pub BinaryHeap, N, Min>) +// where +// M: Monotonic, +// ::Output: TryInto, +// N: ArrayLength>, +// T: Copy; +// +// impl TimerQueue +// where +// M: Monotonic, +// ::Output: TryInto, +// N: ArrayLength>, +// T: Copy, +// { +// /// # Safety +// /// +// /// Writing to memory with a transmute in order to enable +// /// interrupts of the SysTick timer +// /// +// /// Enqueue a task without checking if it is full +// #[inline] +// pub unsafe fn enqueue_unchecked(&mut self, nr: NotReady) { +// let mut is_empty = true; +// // Check if the top contains a non-empty element and if that element is +// // greater than nr +// let if_heap_max_greater_than_nr = self +// .0 +// .peek() +// .map(|head| { +// is_empty = false; +// nr.instant < head.instant +// }) +// .unwrap_or(true); +// if if_heap_max_greater_than_nr { +// if is_empty { +// mem::transmute::<_, SYST>(()).enable_interrupt(); +// } +// +// // Set SysTick pending +// SCB::set_pendst(); +// } +// +// self.0.push_unchecked(nr); +// } +// +// /// Dequeue a task from the TimerQueue +// #[inline] +// pub fn dequeue(&mut self) -> Option<(T, u8)> { +// unsafe { +// if let Some(instant) = self.0.peek().map(|p| p.instant) { +// let now = M::now(); +// +// if instant < now { +// // task became ready +// let nr = self.0.pop_unchecked(); +// +// Some((nr.task, nr.index)) +// } else { +// // set a new timeout +// const MAX: u32 = 0x00ffffff; +// +// let ratio = M::ratio(); +// let dur = match (instant - now).try_into().ok().and_then(|x| { +// x.checked_mul(ratio.numerator) +// .map(|x| x / ratio.denominator) +// }) { +// None => MAX, +// +// // ARM Architecture Reference Manual says: +// // "Setting SYST_RVR to zero has the effect of +// // disabling the SysTick counter independently +// // of the counter enable bit." +// Some(0) => 1, +// +// Some(x) => cmp::min(MAX, x), +// }; +// mem::transmute::<_, SYST>(()).set_reload(dur); +// +// // Start counting down from the new reload +// mem::transmute::<_, SYST>(()).clear_current(); +// +// None +// } +// } else { +// // The queue is empty +// mem::transmute::<_, SYST>(()).disable_interrupt(); +// +// None +// } +// } +// } +// } +// +// pub struct NotReady +// where +// T: Copy, +// M: Monotonic, +// ::Output: TryInto, +// { +// pub index: u8, +// pub instant: M::Instant, +// pub task: T, +// } +// +// impl Eq for NotReady +// where +// T: Copy, +// M: Monotonic, +// ::Output: TryInto, +// { +// } +// +// impl Ord for NotReady +// where +// T: Copy, +// M: Monotonic, +// ::Output: TryInto, +// { +// fn cmp(&self, other: &Self) -> Ordering { +// self.instant.cmp(&other.instant) +// } +// } +// +// impl PartialEq for NotReady +// where +// T: Copy, +// M: Monotonic, +// ::Output: TryInto, +// { +// fn eq(&self, other: &Self) -> bool { +// self.instant == other.instant +// } +// } +// +// impl PartialOrd for NotReady +// where +// T: Copy, +// M: Monotonic, +// ::Output: TryInto, +// { +// fn partial_cmp(&self, other: &Self) -> Option { +// Some(self.cmp(&other)) +// } +// } -- cgit v1.2.3 From b23bb1192c8dc1f2e8f157db2147b1737abc1033 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Tue, 8 Dec 2020 20:49:13 +0100 Subject: TQ handlers being generated --- src/export.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/export.rs b/src/export.rs index 46793aa..dedff2f 100644 --- a/src/export.rs +++ b/src/export.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -//pub use crate::tq::{NotReady, TimerQueue}; +// pub use crate::tq::{NotReady, TimerQueue}; pub use bare_metal::CriticalSection; #[cfg(armv7m)] pub use cortex_m::register::basepri; -- cgit v1.2.3 From 97a48983d2859740983cbf342e1287182426ed44 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 10 Dec 2020 20:33:13 +0100 Subject: More work --- src/export.rs | 8 ++++++++ src/lib.rs | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/export.rs b/src/export.rs index dedff2f..080b1f6 100644 --- a/src/export.rs +++ b/src/export.rs @@ -16,6 +16,7 @@ pub use cortex_m::{ use heapless::spsc::SingleCore; pub use heapless::{consts, i::Queue as iQueue, spsc::Queue}; pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap}; +pub use rtic_core::monotonic::Monotonic; pub type SCFQ = Queue; pub type SCRQ = Queue<(T, u8), N, u8, SingleCore>; @@ -112,6 +113,13 @@ where { } +#[inline(always)] +pub fn assert_monotonic() +where + T: Monotonic, +{ +} + /// Lock the resource proxy by setting the BASEPRI /// and running the closure with interrupt::free /// diff --git a/src/lib.rs b/src/lib.rs index c1930b0..ade1267 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,10 @@ use core::ops::Sub; use cortex_m::{interrupt::Nr, peripheral::NVIC}; pub use cortex_m_rtic_macros::app; -pub use rtic_core::{prelude as mutex_prelude, Exclusive, monotonic::Monotonic, Mutex}; +pub use rtic_core::{ + monotonic::{Clock, Instant, Monotonic}, + prelude as mutex_prelude, Exclusive, Mutex, +}; #[doc(hidden)] pub mod export; -- cgit v1.2.3 From 8e8ec9b7b879adae8d4de6cb2320b9b19290a7e0 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sat, 12 Dec 2020 23:24:54 +0100 Subject: Monotonic codegen now passing compile stage --- src/export.rs | 2 +- src/lib.rs | 4 +- src/tq.rs | 307 +++++++++++++++++++++++++++++----------------------------- 3 files changed, 153 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/src/export.rs b/src/export.rs index 080b1f6..ab5984e 100644 --- a/src/export.rs +++ b/src/export.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -// pub use crate::tq::{NotReady, TimerQueue}; +pub use crate::tq::{NotReady, TimerQueue}; pub use bare_metal::CriticalSection; #[cfg(armv7m)] pub use cortex_m::register::basepri; diff --git a/src/lib.rs b/src/lib.rs index ade1267..c85090f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,12 +35,10 @@ // #![deny(warnings)] #![no_std] -use core::ops::Sub; - use cortex_m::{interrupt::Nr, peripheral::NVIC}; pub use cortex_m_rtic_macros::app; pub use rtic_core::{ - monotonic::{Clock, Instant, Monotonic}, + monotonic::{self, Clock, Duration, Instant, Monotonic}, prelude as mutex_prelude, Exclusive, Mutex, }; diff --git a/src/tq.rs b/src/tq.rs index f2539a9..2bfb651 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -1,156 +1,151 @@ -// use core::{ -// cmp::{self, Ordering}, -// convert::TryInto, -// mem, -// ops::Sub, -// }; -// -// use cortex_m::peripheral::{SCB, SYST}; -// use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; -// -// use crate::Monotonic; -// -// pub struct TimerQueue(pub BinaryHeap, N, Min>) -// where -// M: Monotonic, -// ::Output: TryInto, -// N: ArrayLength>, -// T: Copy; -// -// impl TimerQueue -// where -// M: Monotonic, -// ::Output: TryInto, -// N: ArrayLength>, -// T: Copy, -// { -// /// # Safety -// /// -// /// Writing to memory with a transmute in order to enable -// /// interrupts of the SysTick timer -// /// -// /// Enqueue a task without checking if it is full -// #[inline] -// pub unsafe fn enqueue_unchecked(&mut self, nr: NotReady) { -// let mut is_empty = true; -// // Check if the top contains a non-empty element and if that element is -// // greater than nr -// let if_heap_max_greater_than_nr = self -// .0 -// .peek() -// .map(|head| { -// is_empty = false; -// nr.instant < head.instant -// }) -// .unwrap_or(true); -// if if_heap_max_greater_than_nr { -// if is_empty { -// mem::transmute::<_, SYST>(()).enable_interrupt(); -// } -// -// // Set SysTick pending -// SCB::set_pendst(); -// } -// -// self.0.push_unchecked(nr); -// } -// -// /// Dequeue a task from the TimerQueue -// #[inline] -// pub fn dequeue(&mut self) -> Option<(T, u8)> { -// unsafe { -// if let Some(instant) = self.0.peek().map(|p| p.instant) { -// let now = M::now(); -// -// if instant < now { -// // task became ready -// let nr = self.0.pop_unchecked(); -// -// Some((nr.task, nr.index)) -// } else { -// // set a new timeout -// const MAX: u32 = 0x00ffffff; -// -// let ratio = M::ratio(); -// let dur = match (instant - now).try_into().ok().and_then(|x| { -// x.checked_mul(ratio.numerator) -// .map(|x| x / ratio.denominator) -// }) { -// None => MAX, -// -// // ARM Architecture Reference Manual says: -// // "Setting SYST_RVR to zero has the effect of -// // disabling the SysTick counter independently -// // of the counter enable bit." -// Some(0) => 1, -// -// Some(x) => cmp::min(MAX, x), -// }; -// mem::transmute::<_, SYST>(()).set_reload(dur); -// -// // Start counting down from the new reload -// mem::transmute::<_, SYST>(()).clear_current(); -// -// None -// } -// } else { -// // The queue is empty -// mem::transmute::<_, SYST>(()).disable_interrupt(); -// -// None -// } -// } -// } -// } -// -// pub struct NotReady -// where -// T: Copy, -// M: Monotonic, -// ::Output: TryInto, -// { -// pub index: u8, -// pub instant: M::Instant, -// pub task: T, -// } -// -// impl Eq for NotReady -// where -// T: Copy, -// M: Monotonic, -// ::Output: TryInto, -// { -// } -// -// impl Ord for NotReady -// where -// T: Copy, -// M: Monotonic, -// ::Output: TryInto, -// { -// fn cmp(&self, other: &Self) -> Ordering { -// self.instant.cmp(&other.instant) -// } -// } -// -// impl PartialEq for NotReady -// where -// T: Copy, -// M: Monotonic, -// ::Output: TryInto, -// { -// fn eq(&self, other: &Self) -> bool { -// self.instant == other.instant -// } -// } -// -// impl PartialOrd for NotReady -// where -// T: Copy, -// M: Monotonic, -// ::Output: TryInto, -// { -// fn partial_cmp(&self, other: &Self) -> Option { -// Some(self.cmp(&other)) -// } -// } +use crate::{Instant, Monotonic}; +use core::cmp::Ordering; +use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; + +pub struct TimerQueue(pub BinaryHeap, N, Min>) +where + M: Monotonic, + N: ArrayLength>, + T: Copy; + +impl TimerQueue +where + M: Monotonic, + N: ArrayLength>, + T: Copy, +{ + /// # Safety + /// + /// Writing to memory with a transmute in order to enable + /// interrupts of the SysTick timer + /// + /// Enqueue a task without checking if it is full + #[inline] + pub unsafe fn enqueue_unchecked( + &mut self, + nr: NotReady, + enable_interrupt: F1, + pend_handler: F2, + ) where + F1: FnOnce(), + F2: FnOnce(), + { + let mut is_empty = true; + // Check if the top contains a non-empty element and if that element is + // greater than nr + let if_heap_max_greater_than_nr = self + .0 + .peek() + .map(|head| { + is_empty = false; + nr.instant < head.instant + }) + .unwrap_or(true); + if if_heap_max_greater_than_nr { + if is_empty { + // mem::transmute::<_, SYST>(()).enable_interrupt(); + enable_interrupt(); + } + + // Set SysTick pending + // SCB::set_pendst(); + pend_handler(); + } + + self.0.push_unchecked(nr); + } + + /// Check if the timer queue is empty. + #[inline] + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Dequeue a task from the TimerQueue + #[inline] + pub fn dequeue(&mut self, disable_interrupt: F) -> Option<(T, u8)> + where + F: FnOnce(), + { + unsafe { + M::clear_compare(); + + if let Some(instant) = self.0.peek().map(|p| p.instant) { + let now = M::now(); + + match instant.checked_duration_since(&now) { + None => { + // instant < now + // task became ready + let nr = self.0.pop_unchecked(); + + Some((nr.task, nr.index)) + } + Some(dur) => { + // TODO: Fix this hack... + let new_instant = *now.duration_since_epoch().integer() + *dur.integer(); + M::set_compare(new_instant); + + // Start counting down from the new reload + // mem::transmute::<_, SYST>(()).clear_current(); + + None + } + } + } else { + // The queue is empty + // mem::transmute::<_, SYST>(()).disable_interrupt(); + disable_interrupt(); + + None + } + } + } +} + +pub struct NotReady +where + T: Copy, + M: Monotonic, +{ + pub index: u8, + pub instant: Instant, + pub task: T, +} + +impl Eq for NotReady +where + T: Copy, + M: Monotonic, +{ +} + +impl Ord for NotReady +where + T: Copy, + M: Monotonic, +{ + fn cmp(&self, other: &Self) -> Ordering { + self.instant.cmp(&other.instant) + } +} + +impl PartialEq for NotReady +where + T: Copy, + M: Monotonic, +{ + fn eq(&self, other: &Self) -> bool { + self.instant == other.instant + } +} + +impl PartialOrd for NotReady +where + T: Copy, + M: Monotonic, +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} -- cgit v1.2.3 From 35b4ec0d0435879cca97536b5c866fc2ac2e9210 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 13 Dec 2020 00:06:50 +0100 Subject: Reexport embedded-time as rtic::time --- src/lib.rs | 2 +- src/tq.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index c85090f..0840589 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ use cortex_m::{interrupt::Nr, peripheral::NVIC}; pub use cortex_m_rtic_macros::app; pub use rtic_core::{ - monotonic::{self, Clock, Duration, Instant, Monotonic}, + monotonic::{self, embedded_time as time, Monotonic}, prelude as mutex_prelude, Exclusive, Mutex, }; diff --git a/src/tq.rs b/src/tq.rs index 2bfb651..a98eed6 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -1,4 +1,4 @@ -use crate::{Instant, Monotonic}; +use crate::{time::Instant, Monotonic}; use core::cmp::Ordering; use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; -- cgit v1.2.3 From dd52539e32690c5cff73efe40c5d443b770d82a0 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 13 Dec 2020 00:09:44 +0100 Subject: Less ... hacky? --- src/tq.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index a98eed6..8859392 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -81,9 +81,10 @@ where Some((nr.task, nr.index)) } - Some(dur) => { + Some(_) => { // TODO: Fix this hack... - let new_instant = *now.duration_since_epoch().integer() + *dur.integer(); + // Extract the compare time + let new_instant = *instant.duration_since_epoch().integer(); M::set_compare(new_instant); // Start counting down from the new reload -- cgit v1.2.3 From 0e134a41b5f53843b5e1c90cd0633ae56b7a3113 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 13 Dec 2020 14:20:28 +0100 Subject: Double check the compare instant --- src/tq.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index 8859392..5903b3f 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -84,13 +84,22 @@ where Some(_) => { // TODO: Fix this hack... // Extract the compare time - let new_instant = *instant.duration_since_epoch().integer(); - M::set_compare(new_instant); + M::set_compare(*instant.duration_since_epoch().integer()); + + // 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. + if instant.checked_duration_since(&M::now()).is_none() { + let nr = self.0.pop_unchecked(); + + Some((nr.task, nr.index)) + } else { + None + } // Start counting down from the new reload // mem::transmute::<_, SYST>(()).clear_current(); - - None } } } else { -- cgit v1.2.3 From aaa92ea2fac23d2679b5efc1178a45d994762bca Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 13 Dec 2020 17:48:11 +0100 Subject: Cleanup --- src/tq.rs | 103 ++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index 5903b3f..be854a5 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -2,17 +2,17 @@ use crate::{time::Instant, Monotonic}; use core::cmp::Ordering; use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; -pub struct TimerQueue(pub BinaryHeap, N, Min>) +pub struct TimerQueue(pub BinaryHeap, N, Min>) where - M: Monotonic, - N: ArrayLength>, - T: Copy; + Mono: Monotonic, + N: ArrayLength>, + Task: Copy; -impl TimerQueue +impl TimerQueue where - M: Monotonic, - N: ArrayLength>, - T: Copy, + Mono: Monotonic, + N: ArrayLength>, + Task: Copy, { /// # Safety /// @@ -23,7 +23,7 @@ where #[inline] pub unsafe fn enqueue_unchecked( &mut self, - nr: NotReady, + nr: NotReady, enable_interrupt: F1, pend_handler: F2, ) where @@ -63,44 +63,39 @@ where /// Dequeue a task from the TimerQueue #[inline] - pub fn dequeue(&mut self, disable_interrupt: F) -> Option<(T, u8)> + pub fn dequeue(&mut self, disable_interrupt: F) -> Option<(Task, u8)> where F: FnOnce(), { unsafe { - M::clear_compare(); + Mono::clear_compare(); if let Some(instant) = self.0.peek().map(|p| p.instant) { - let now = M::now(); - - match instant.checked_duration_since(&now) { - None => { - // instant < now - // task became ready + if instant < Mono::now() { + // instant < now + // task became ready + let nr = self.0.pop_unchecked(); + + Some((nr.task, nr.index)) + } else { + // TODO: Fix this hack... + // Extract the compare time + Mono::set_compare(*instant.duration_since_epoch().integer()); + + // 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. + if instant < Mono::now() { let nr = self.0.pop_unchecked(); Some((nr.task, nr.index)) + } else { + None } - Some(_) => { - // TODO: Fix this hack... - // Extract the compare time - M::set_compare(*instant.duration_since_epoch().integer()); - - // 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. - if instant.checked_duration_since(&M::now()).is_none() { - let nr = self.0.pop_unchecked(); - - Some((nr.task, nr.index)) - } else { - None - } - - // Start counting down from the new reload - // mem::transmute::<_, SYST>(()).clear_current(); - } + + // Start counting down from the new reload + // mem::transmute::<_, SYST>(()).clear_current(); } } else { // The queue is empty @@ -113,47 +108,47 @@ where } } -pub struct NotReady +pub struct NotReady where - T: Copy, - M: Monotonic, + Task: Copy, + Mono: Monotonic, { pub index: u8, - pub instant: Instant, - pub task: T, + pub instant: Instant, + pub task: Task, } -impl Eq for NotReady +impl Eq for NotReady where - T: Copy, - M: Monotonic, + Task: Copy, + Mono: Monotonic, { } -impl Ord for NotReady +impl Ord for NotReady where - T: Copy, - M: Monotonic, + Task: Copy, + Mono: Monotonic, { fn cmp(&self, other: &Self) -> Ordering { self.instant.cmp(&other.instant) } } -impl PartialEq for NotReady +impl PartialEq for NotReady where - T: Copy, - M: Monotonic, + Task: Copy, + Mono: Monotonic, { fn eq(&self, other: &Self) -> bool { self.instant == other.instant } } -impl PartialOrd for NotReady +impl PartialOrd for NotReady where - T: Copy, - M: Monotonic, + Task: Copy, + Mono: Monotonic, { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(&other)) -- cgit v1.2.3 From 0658d53843d5452085e7458269e0abebbf431971 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 10 Jan 2021 15:47:25 +0100 Subject: cleanup --- src/tq.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index be854a5..4c89a66 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -72,14 +72,13 @@ where if let Some(instant) = self.0.peek().map(|p| p.instant) { if instant < Mono::now() { - // instant < now // task became ready let nr = self.0.pop_unchecked(); Some((nr.task, nr.index)) } else { // TODO: Fix this hack... - // Extract the compare time + // Extract the compare time. Mono::set_compare(*instant.duration_since_epoch().integer()); // Double check that the instant we set is really in the future, else @@ -93,13 +92,9 @@ where } else { None } - - // Start counting down from the new reload - // mem::transmute::<_, SYST>(()).clear_current(); } } else { - // The queue is empty - // mem::transmute::<_, SYST>(()).disable_interrupt(); + // The queue is empty, disable the interrupt. disable_interrupt(); None -- cgit v1.2.3 From ebf2f058a4d2a1fcf118144b9893dc3038939bad Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 18 Feb 2021 19:30:59 +0100 Subject: Now with new monotonic trait and crate --- src/export.rs | 4 ++-- src/lib.rs | 6 ++---- src/tq.rs | 68 +++++++++++++++++++++++++++++++++++------------------------ 3 files changed, 44 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/export.rs b/src/export.rs index ab5984e..91a4a5e 100644 --- a/src/export.rs +++ b/src/export.rs @@ -16,7 +16,7 @@ pub use cortex_m::{ use heapless::spsc::SingleCore; pub use heapless::{consts, i::Queue as iQueue, spsc::Queue}; pub use heapless::{i::BinaryHeap as iBinaryHeap, BinaryHeap}; -pub use rtic_core::monotonic::Monotonic; +pub use rtic_monotonic as monotonic; pub type SCFQ = Queue; pub type SCRQ = Queue<(T, u8), N, u8, SingleCore>; @@ -116,7 +116,7 @@ where #[inline(always)] pub fn assert_monotonic() where - T: Monotonic, + T: monotonic::Monotonic, { } diff --git a/src/lib.rs b/src/lib.rs index 1d4df65..16f2e9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,10 +37,8 @@ use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; pub use cortex_m_rtic_macros::app; -pub use rtic_core::{ - monotonic::{self, embedded_time as time, Monotonic}, - 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}; #[doc(hidden)] pub mod export; diff --git a/src/tq.rs b/src/tq.rs index 4c89a66..6697f10 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -1,4 +1,7 @@ -use crate::{time::Instant, Monotonic}; +use crate::{ + time::{Clock, Instant}, + Monotonic, +}; use core::cmp::Ordering; use heapless::{binary_heap::Min, ArrayLength, BinaryHeap}; @@ -42,7 +45,7 @@ where }) .unwrap_or(true); if if_heap_max_greater_than_nr { - if is_empty { + if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && is_empty { // mem::transmute::<_, SYST>(()).enable_interrupt(); enable_interrupt(); } @@ -61,44 +64,53 @@ where self.0.is_empty() } + #[inline] + fn unwrapper(val: Result) -> T { + if let Ok(v) = val { + v + } else { + unreachable!("Your monotonic is not infallible") + } + } + /// Dequeue a task from the TimerQueue #[inline] - pub fn dequeue(&mut self, disable_interrupt: F) -> Option<(Task, u8)> + pub fn dequeue(&mut self, disable_interrupt: F, mono: &mut Mono) -> Option<(Task, u8)> where F: FnOnce(), { - unsafe { - Mono::clear_compare(); + mono.clear_compare_flag(); + + if let Some(instant) = self.0.peek().map(|p| p.instant) { + if instant < Self::unwrapper(Clock::try_now(mono)) { + // task became ready + let nr = unsafe { self.0.pop_unchecked() }; - if let Some(instant) = self.0.peek().map(|p| p.instant) { - if instant < Mono::now() { - // task became ready - let nr = self.0.pop_unchecked(); + Some((nr.task, nr.index)) + } else { + // TODO: Fix this hack... + // Extract the compare time. + mono.set_compare(*instant.duration_since_epoch().integer()); + + // 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. + if instant < Self::unwrapper(Clock::try_now(mono)) { + let nr = unsafe { self.0.pop_unchecked() }; Some((nr.task, nr.index)) } else { - // TODO: Fix this hack... - // Extract the compare time. - Mono::set_compare(*instant.duration_since_epoch().integer()); - - // 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. - if instant < Mono::now() { - let nr = self.0.pop_unchecked(); - - Some((nr.task, nr.index)) - } else { - None - } + None } - } else { - // The queue is empty, disable the interrupt. + } + } else { + // The queue is empty, disable the interrupt. + if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE { disable_interrupt(); - - None } + + None } } } -- cgit v1.2.3 From e52088bbd8f4f15b0d49ced8a24c5a2fc8c8c11f Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Mon, 22 Feb 2021 20:15:13 +0100 Subject: Of by 1 --- src/tq.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index 6697f10..541ffcd 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -82,7 +82,7 @@ where mono.clear_compare_flag(); if let Some(instant) = self.0.peek().map(|p| p.instant) { - if instant < Self::unwrapper(Clock::try_now(mono)) { + if instant <= Self::unwrapper(Clock::try_now(mono)) { // task became ready let nr = unsafe { self.0.pop_unchecked() }; @@ -96,7 +96,7 @@ where // 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. - if instant < Self::unwrapper(Clock::try_now(mono)) { + if instant <= Self::unwrapper(Clock::try_now(mono)) { let nr = unsafe { self.0.pop_unchecked() }; Some((nr.task, nr.index)) -- cgit v1.2.3 From 82d051e8e967522af735fff47a1738ce4952f950 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Mon, 22 Feb 2021 20:59:03 +0100 Subject: Added enable/disable timer calls --- src/tq.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index 541ffcd..a637007 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -29,6 +29,7 @@ where nr: NotReady, enable_interrupt: F1, pend_handler: F2, + mono: &mut Mono, ) where F1: FnOnce(), F2: FnOnce(), @@ -46,7 +47,8 @@ where .unwrap_or(true); if if_heap_max_greater_than_nr { if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && is_empty { - // mem::transmute::<_, SYST>(()).enable_interrupt(); + // mem::transmute::<_, SYST>(()).enable_interrupt();A + mono.enable_timer(); enable_interrupt(); } @@ -108,6 +110,7 @@ where // The queue is empty, disable the interrupt. if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE { disable_interrupt(); + mono.disable_timer(); } None -- cgit v1.2.3 From 56d99c02bd809dfa96d6c1f102e046533c5c631f Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Mon, 22 Feb 2021 20:59:23 +0100 Subject: Updated to new interface --- src/tq.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tq.rs b/src/tq.rs index a637007..063bbd8 100644 --- a/src/tq.rs +++ b/src/tq.rs @@ -90,9 +90,8 @@ where Some((nr.task, nr.index)) } else { - // TODO: Fix this hack... - // Extract the compare time. - mono.set_compare(*instant.duration_since_epoch().integer()); + // Set compare + 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 -- cgit v1.2.3 From 767d46e05bbc88eb3c236cf468f9432c7fe0ce05 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Thu, 25 Feb 2021 17:32:12 +0100 Subject: Review fixes --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 16f2e9f..8220739 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ #![deny(missing_docs)] #![deny(rust_2018_compatibility)] #![deny(rust_2018_idioms)] -// #![deny(warnings)] +#![deny(warnings)] #![no_std] use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC}; -- cgit v1.2.3