Crates.io | embedded-time |
lib.rs | embedded-time |
version | 0.12.1 |
source | src |
created_at | 2020-05-21 22:28:38.396336 |
updated_at | 2021-10-02 18:34:30.088271 |
description | Fully defined, inter-operable, ergonomic, and fast human-time units (both duration and rate types) with hardware timer abstraction and software timers. |
homepage | |
repository | https://github.com/FluenTech/embedded-time/ |
max_upload_size | |
id | 244341 |
size | 246,448 |
embedded-time
provides a comprehensive library of Duration
and Rate
types as well as
a Clock
abstractions for hardware timers/clocks and the associated Instant
type for
in embedded systems.
Additionally, an implementation of software timers is provided that work seemlessly with all the types in this crate.
use embedded_time::{duration::*, rate::*};
let micros = 200_000_u32.microseconds(); // 200_000 ╬╝s
let millis: Milliseconds = micros.into(); // 200 ms
let frequency: Result<Hertz,_> = millis.to_rate(); // 5 Hz
assert_eq!(frequency, Ok(5_u32.Hz()));
The handling of time on embedded systems is generally much different than that of OSs. For instance, on an OS, the time is measured against an arbitrary epoch. Embedded systems generally don't know (nor do they care) what the real time is, but rather how much time has passed since the system has started.
u64
seconds and u32
nanoseconds.Instant
type requires std
.time
crateThe time
crate is a remarkable library but isn't geared for embedded systems (although it does
support a subset of features in no_std
contexts). It suffers from some of the same drawbacks
as the core::Duration type (namely the storage format) and the Instant
struct dependency on
std
. It also adds a lot of functionally that would seldom be useful in an embedded context.
For instance it has a comprehensive date/time formatting, timezone, and calendar support.
In the Rust ecosystem, it appears to be idiomatic to call a now()
associated function from an
Instant type. There is generally no concept of a "Clock". I believe that using the Instant
in
this way is a violation of the separation of concerns principle. What is an Instant
? Is it a
time-keeping entity from which you read the current instant in time, or is it that instant in
time itself. In this case, it's both.
As an alternative, the current instant in time is read from a Clock. The Instant
read from
the Clock
has the same precision and width (inner type) as the Clock
. Requesting the
difference between two Instant
s gives a Duration
which can have different precision and/or
width.
The approach taken is similar to the C++ chrono
library. Duration
s and Rate
s are
fixed-point values as in they are comprised of integer and scaling factor values.
The scaling factor is a const
Fraction
. One benefit of this
structure is that it avoids unnecessary arithmetic. For example, if the Duration
type is
Milliseconds
, a call to the Duration::integer()
method simply returns the integer
part directly which in the case is the number of milliseconds represented by the Duration
.
Conversion arithmetic is only performed when explicitly converting between time units (eg.
Milliseconds
--> Seconds
).
In addition, a wide range of rate-type types are available including Hertz
,
BitsPerSecond
, KibibytesPerSecond
, Baud
, etc.
A Duration
type can be converted to a Rate
type and vica-versa.
Clock: Any entity that periodically counts (ie an external or peripheral hardware timer/counter). Generally, this needs to be monotonic. A wrapping clock is considered monotonic in this context as long as it fulfills the other requirements.
Wrapping Clock: A clock that when at its maximum value, the next count is the minimum value.
Timer: An entity that counts toward an expiration.
Instant: A specific instant in time ("time-point") read from a clock.
Duration: The difference of two instants. The time that has elapsed since an instant. A span of time.
Rate: A measure of events per time such as frequency, data-rate, etc.
The suggested use statements are as follows depending on what is needed:
use embedded_time::duration::*; // imports all duration-related types and traits
use embedded_time::rate::*; // imports all rate-related types and traits
use embedded_time::clock;
use embedded_time::Instant;
use embedded_time::Timer;
Units | Extension |
---|---|
Hours | hours |
Minutes | minutes |
Seconds | seconds |
Milliseconds | milliseconds |
Microseconds | microseconds |
Nanoseconds | nanoseconds |
Rate
typesuse embedded_time::{duration::*, rate::*};
Microseconds(500_u32).to_rate() == Ok(Kilohertz(2_u32))
Generic
Duration
typeuse embedded_time::{duration::*};
Seconds(2_u64).to_generic(Fraction::new(1, 2_000)) == Ok(Generic::new(4_000_u32, Fraction::new(1, 2_000)))
Seconds::<u64>::try_from(Generic::new(2_000_u32, Fraction::new(1, 1_000))) == Ok(Seconds(2_u64))
core
Compatibilitycore::time::Duration
core
duration typeuse embedded_time::duration::*;
let duration = Milliseconds::<u64>(ms); // 8 bytes
let count = duration.integer();
(the size of embedded-time
duration types is only the size of the inner type)
use std::time::Duration;
let core_duration = Duration::from_millis(ms); // 12 bytes
let count = core_duration.as_millis();
(the size of core
duration type is 12 B)
Units | Extension |
---|---|
Mebihertz | MiHz |
Megahertz | MHz |
Kibihertz | KiHz |
Kilohertz | kHz |
Hertz | Hz |
Units | Extension |
---|---|
MebibytePerSecond | MiBps |
MegabytePerSecond | MBps |
KibibytePerSecond | KiBps |
KiloBytePerSecond | KBps |
BytePerSecond | Bps |
MebibitPerSecond | Mibps |
MegabitPerSecond | Mbps |
KibibitPerSecond | Kibps |
KilobitPerSecond | kbps |
BitPerSecond | bps |
Units | Extension |
---|---|
Mebibaud | MiBd |
Megabaud | MBd |
Kibibaud | KiBd |
Kilobaud | kBd |
Baud | Bd |
Conversion from/to all other rate types within the same class (frequency, data rate, etc.) and base (mega, mebi, kilo, kibi). For example, MiBps (mebibytes per second) --> Kibps (kibibits per second) and MBps (megabytes per second) --> kbps (kilobits per second).
Conversion from Duration
types
use embedded_time::{duration::*, rate::*};
Kilohertz(500_u32).to_duration() == Ok(Microseconds(2_u32))
Generic
Rate
typeuse embedded_time::rate::*;
Hertz(2_u64).to_generic(Fraction::new(1,2_000)) == Ok(Generic::new(4_000_u32, Fraction::new(1,2_000)))
Hertz::<u64>::try_from(Generic::new(2_000_u32, Fraction::new(1,1_000))) == Ok(Hertz(2_u64))
Clock
trait allowing abstraction of hardware timers/clocks for timekeeping.Clock
impl object.Some parts of this crate were derived from various sources:
RTIC
time
(Specifically the time::NumbericalDuration
implementations for primitive integers)License: MIT OR Apache-2.0