#duration #time #rate #clock #instant #hardware-abstraction

无 std embedded-time

完全定义、可互操作、易于使用且快速的人性化时间单位(包括持续时间和比率类型),具有硬件定时器抽象和软件定时器

21 个版本 (11 个重大变更)

0.12.1 2021年10月2日
0.12.0 2021年5月31日
0.11.0 2021年5月6日
0.10.1 2020年11月15日
0.8.1 2020年7月26日

#537 in 嵌入式开发

Download history 4327/week @ 2024-03-15 3366/week @ 2024-03-22 3205/week @ 2024-03-29 2982/week @ 2024-04-05 3673/week @ 2024-04-12 4520/week @ 2024-04-19 3599/week @ 2024-04-26 3403/week @ 2024-05-03 3431/week @ 2024-05-10 3070/week @ 2024-05-17 3485/week @ 2024-05-24 3460/week @ 2024-05-31 3595/week @ 2024-06-07 4382/week @ 2024-06-14 5288/week @ 2024-06-21 3826/week @ 2024-06-28

17,713 每月下载量
少于 42 crates 中使用

MIT/Apache

130KB
2K SLoC

# embedded-time

embedded-time 提供了全面的 DurationRate 类型库,以及硬件定时器/时钟的 Clock 抽象和用于嵌入式系统的相关 Instant 类型。

此外,还提供了一个与该包中所有类型无缝工作的软件定时器实现。

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()));

动机

嵌入式系统中的时间处理通常与操作系统大不相同。例如,在操作系统上,时间是以任意纪元为基准测量的。嵌入式系统通常不知道(也不关心)实际时间是什么,而是关心自系统启动以来经过了多少时间。

标准库类型的缺点

持续时间

  • 存储为 u64 秒和 u32 纳秒。
  • 这过于夸张,增加了不必要的复杂性,超出了嵌入式系统所需(或期望)的复杂度。
  • 任何读取(除秒和纳秒外)都需要进行算术转换到所需单位
  • 这比本项目实现的时间单位类似标记联合体慢得多。

瞬间

  • Instant 类型需要 std

time crate 的缺点

《time》crate 是一个出色的库,但并不适合嵌入式系统(尽管它支持 no_std 上下文中的一些功能子集)。它存在一些与核心 Duration 类型相同的缺点(尤其是存储格式),并且依赖于 std 中的 Instant 结构。它还添加了很多在嵌入式环境中很少用到的功能。例如,它提供了全面的日期/时间格式化、时区和日历支持。

背景

什么是 Instant?

在 Rust 生态系统内,似乎有一种惯例是从 Instant 类型调用一个名为 now() 的关联函数。通常没有“时钟”的概念。我认为以这种方式使用 Instant 是违反了 关注点分离 原则的。什么是 Instant?它是一个读取当前时间的计时实体,还是它本身就是那个时间点。在这种情况下,两者都是。

作为替代,当前的时间点是从一个 时钟 读取的。从 Clock 读取的 InstantClock 具有相同的精度和宽度(内部类型)。请求两个 Instant 之间的差值会得到一个 Duration,它可以有不同的精度和/或宽度。

概述

采用的方法类似于 C++ 的 chrono 库。在 DurationRate 中,使用的是固定点值,即它们由 整数缩放因子 值组成。缩放因子是一个 constFraction。这种结构的一个好处是它避免了不必要的算术运算。例如,如果 Duration 类型是 Milliseconds,调用 Duration::integer() 方法直接返回整数部分,在这种情况下就是由 Duration 表示的毫秒数。转换算术运算仅在显式转换时间单位时(例如,Milliseconds --> Seconds)执行。

此外,还提供了广泛的速率类型,包括 HertzBitsPerSecondKibibytesPerSecondBaud 等。

Duration 类型可以转换为 Rate 类型,反之亦然。

定义

时钟:任何周期性计数的实体(即外部或外围硬件计时器/计数器)。通常,这需要单调。只要满足其他要求,环绕时钟也被视为单调。

环绕时钟:当达到最大值时,下一次计数为最小值的时钟。

计时器:向到期计数的一个实体。

瞬间:从时钟中读取的特定时间点。

持续时间:两个瞬间之间的差异。自某个瞬间以来经过的时间。一段时间。

速率:每单位时间事件的数量,例如频率、数据速率等。

导入

建议的使用语句如下,具体取决于需要什么

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;

持续时间类型

单位 扩展
小时 小时
分钟 分钟
毫秒 毫秒
微秒 微秒
纳秒 纳秒
  • Rate类型转换
use embedded_time::{duration::*, rate::*};

Microseconds(500_u32).to_rate() == Ok(Kilohertz(2_u32))
  • 转换为/从Generic Duration类型
use 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 兼容性

  • 转换为/从core::time::Duration

core持续时间类型的基准比较

构造和读取毫秒
use embedded_time::duration::*;

let duration = Milliseconds::<u64>(ms); // 8 bytes
let count = duration.integer();

(嵌入式时间持续时间类型的大小仅是内部类型的大小)

use std::time::Duration;

let core_duration = Duration::from_millis(ms); // 12 bytes
let count = core_duration.as_millis();

(核心持续时间类型的大小为12 B)

速率类型

频率

单位 扩展
梅比赫兹 MiHz
兆赫兹 MHz
基比赫兹 KiHz
千赫兹 kHz
赫兹 Hz

数据速率

单位 扩展
每秒梅比字节 MiBps
每秒兆字节 MBps
每秒基比字节 KiBps
每秒千字节 KBps
每秒字节 Bps
每秒梅比比特 Mibps
每秒兆比特 Mbps
每秒基比比特 Kibps
每秒千比特 kbps
每秒比特 bps

符号速率

单位 扩展
梅比波特 MiBd
每秒兆波特 MBd
每秒基比波特 KiBd
每秒千波特 kBd
波特 Bd
  • 在同一类别(频率、数据速率等)和基本(兆、梅比、千、基比)内从/到所有其他速率类型的转换。例如,MiBps(每秒梅比字节)--> Kibps(每秒基比比特)和MBps(每秒兆字节)--> kbps(每秒千比特)。

  • Duration类型转换

use embedded_time::{duration::*, rate::*};

Kilohertz(500_u32).to_duration() == Ok(Microseconds(2_u32))
  • 转换为/从Generic Rate类型
use 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特质,允许抽象硬件计时器/时钟以进行时间维护。

计时器

  • Clock实现对象产生的软件计时器。
  • 单次或周期性/连续的
  • 阻塞延迟
  • 轮询到期
  • 读取经过/剩余的持续时间

可靠性和可用性

  • 广泛的测试
  • 详细文档,附有示例
  • 适用于nRF52_DK板的示例

注释

此crate的一些部分是从各种来源派生的

许可证:MIT OR Apache-2.0

依赖关系

~405–640KB
~13K SLoC