embedded-hal icon indicating copy to clipboard operation
embedded-hal copied to clipboard

Need for a Generic Instant/Time/Duration

Open tib888 opened this issue 6 years ago • 3 comments
trafficstars

Hi All,

I'v run into the need for a generic "Instant" implementation several times.

  • Its implementation could be "tick based", for example running from 72Mhz clock with an u32 counter - this overflows about every 1 minute.
  • Or can be "time based" for example every 1ms an u32 counter is incremented, so we do not have to worry about overflows for about 50 days.

Depending on your application you can decide what resolution ticks you need (and how often you can tolerate an overflow) and what kind of HW resources you have to increase a counter.

Then this implementation of "Instant" trait(s) could be passed to various stuff, like:

  • measure impulse width of an infrared remote control
  • decide between clicks / double clicks
  • switch debounce filters
  • measure the length of light part of the days
  • etc.

Each of these implementations would be generic about the "Instant" trait(s), but all of them likely

  • want to store one or more past instant so it most be Copy
  • calculate the duration between these instants ops::Sub<Output=DURATION>
  • make some calculation with these durations, so DURATION: Default, Copy, ops::Add<Output=DURATION>, ops::Sub<Output=DURATION>
  • calculate a future instant by adding a duration to a past instant
  • compare/order instants, durations
  • convert this duration into a known time unit for example Into < Microseconds >

The std time, duration is too big overhead for an embedded system, with this abstraction each application could be provided with a well optimized time measurement utility.

Please comment!

tib888 avatar Jan 28 '19 12:01 tib888

The std time, duration is too big overhead for an embedded system

I'm curious what you mean by core::time::Duration having too much of an overhead?

Its definition is struct Duration { secs: u64, nanos: u32 }, so memory-wise there isn't a problem. Likewise, operations like addition are pretty trivial and would optimise down to nothing.

In my application, I'm using the time since a stable reference point (e.g. power on or the unix epoch) for time-keeping purposes.

/// Something which records the elapsed real time.
///
/// This uses shared references because it may be shared between multiple
/// components at any one time.
pub trait SystemClock {
    /// The amount of time that has passed since a clock-specific reference
    /// point (e.g. device startup or the unix epoch).
    fn elapsed(&self) -> Duration;
}

Michael-F-Bryan avatar Jul 12 '19 12:07 Michael-F-Bryan

In my application, I'm using the time since a stable reference point (e.g. power on or the unix epoch) for time-keeping purposes.

First of all, thanks for sharing your application repo! In clock.rs of your application, it seems that measuring the actual elapsed time is possible only when std is enabled for std::time::Instant support.

May I ask how I could implement such 'time-measuring' functionality without std support?? Thank you 😄

JOE1994 avatar Jan 04 '20 17:01 JOE1994

On an embedded device (most #[no_std] applicationd) you often bring your own clock.

This is typically implemented by registering a SysTick interrupt handler and incrementing a counter every time it's triggered. From there you can do some math with the clock frequency to turn ticks into seconds. I don't want to make assumptions about your application or force people to use whatever I implement, so we use a trait.

If you're compiling with the full standard library we know we'll always have access to the "current time" via the OS, so I've provided an implementation instead of forcing every user to write it themselves.

Michael-F-Bryan avatar Jan 05 '20 14:01 Michael-F-Bryan