change Monotonic::ratio return type to Fraction

This commit is contained in:
Jorge Aparicio 2019-07-11 13:28:25 +02:00
parent 6a8404ac92
commit a87cb2486f
5 changed files with 41 additions and 17 deletions

View file

@ -8,7 +8,7 @@ use core::{
}; };
use bare_metal::Nr; use bare_metal::Nr;
use rtfm::{Monotonic, MultiCore}; use rtfm::{Fraction, Monotonic, MultiCore};
// both cores have the exact same interrupts // both cores have the exact same interrupts
pub use Interrupt_0 as Interrupt_1; pub use Interrupt_0 as Interrupt_1;
@ -24,8 +24,11 @@ pub struct MT;
impl Monotonic for MT { impl Monotonic for MT {
type Instant = Instant; type Instant = Instant;
fn ratio() -> u32 { fn ratio() -> Fraction {
1 Fraction {
numerator: 1,
denominator: 1,
}
} }
unsafe fn reset() { unsafe fn reset() {

View file

@ -8,7 +8,7 @@ use core::{
}; };
use bare_metal::Nr; use bare_metal::Nr;
use rtfm::{Monotonic, MultiCore}; use rtfm::{Fraction, Monotonic, MultiCore};
// both cores have the exact same interrupts // both cores have the exact same interrupts
pub use Interrupt_0 as Interrupt_1; pub use Interrupt_0 as Interrupt_1;
@ -24,8 +24,11 @@ pub struct MT;
impl Monotonic for MT { impl Monotonic for MT {
type Instant = Instant; type Instant = Instant;
fn ratio() -> u32 { fn ratio() -> Fraction {
1 Fraction {
numerator: 1,
denominator: 1,
}
} }
unsafe fn reset() { unsafe fn reset() {

View file

@ -10,9 +10,15 @@ use core::{
use cortex_m::peripheral::DWT; use cortex_m::peripheral::DWT;
use crate::Fraction;
/// A measurement of the CYCCNT. Opaque and useful only with `Duration` /// A measurement of the CYCCNT. Opaque and useful only with `Duration`
/// ///
/// This data type is only available on ARMv7-M /// This data type is only available on ARMv7-M
///
/// Note that this value is tied to the CYCCNT of one core and that sending it a different core
/// makes it lose its meaning -- each Cortex-M core has its own CYCCNT counter and these are usually
/// unsynchronized and they may even be running at different frequencies.
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub struct Instant { pub struct Instant {
inner: i32, inner: i32,
@ -21,7 +27,6 @@ pub struct Instant {
unsafe impl Sync for Instant {} unsafe impl Sync for Instant {}
#[cfg(not(feature = "heterogeneous"))]
unsafe impl Send for Instant {} unsafe impl Send for Instant {}
impl Instant { impl Instant {
@ -182,15 +187,16 @@ impl U32Ext for u32 {
} }
/// Implementation of the `Monotonic` trait based on CYCle CouNTer /// Implementation of the `Monotonic` trait based on CYCle CouNTer
#[cfg(not(feature = "heterogeneous"))]
pub struct CYCCNT; pub struct CYCCNT;
#[cfg(not(feature = "heterogeneous"))]
impl crate::Monotonic for CYCCNT { impl crate::Monotonic for CYCCNT {
type Instant = Instant; type Instant = Instant;
fn ratio() -> u32 { fn ratio() -> Fraction {
1 Fraction {
numerator: 1,
denominator: 1,
}
} }
unsafe fn reset() { unsafe fn reset() {

View file

@ -116,13 +116,25 @@ impl From<cortex_m::Peripherals> for Peripherals {
} }
} }
/// A fraction
pub struct Fraction {
/// The numerator
pub numerator: u32,
/// The denominator
pub denominator: u32,
}
/// A monotonic clock / counter /// A monotonic clock / counter
pub trait Monotonic { pub trait Monotonic {
/// A measurement of this clock /// A measurement of this clock
type Instant: Copy + Ord + Sub; type Instant: Copy + Ord + Sub;
/// The ratio between the SysTick (system timer) frequency and this clock frequency /// The ratio between the SysTick (system timer) frequency and this clock frequency
fn ratio() -> u32; ///
/// 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 /// Returns the current time
fn now() -> Self::Instant; fn now() -> Self::Instant;

View file

@ -62,11 +62,11 @@ where
// set a new timeout // set a new timeout
const MAX: u32 = 0x00ffffff; const MAX: u32 = 0x00ffffff;
let dur = match (instant - now) let ratio = M::ratio();
.try_into() let dur = match (instant - now).try_into().ok().and_then(|x| {
.ok() x.checked_mul(ratio.numerator)
.and_then(|x| x.checked_mul(M::ratio())) .map(|x| x / ratio.denominator)
{ }) {
None => MAX, None => MAX,
Some(x) => cmp::min(MAX, x), Some(x) => cmp::min(MAX, x),
}; };