Embassy源码分析-time

  • 2023年 11月18日
  • 读完约需 5 分钟
  • • 
  • 标签: 
  • embassy
  • rust
  • async
  • 最后更新于 2023年 11月25日

embassy-time crate提供了时间相关的模块,具体有

  • [Instant] 表示从系统启动到现在的刻度值。
  • [Duration]表示从某时刻开始到现在经过的时间段。
  • [Timer]实现了异步延迟操作。
  • [Ticker]实现了固定期限的延迟。
  • [Delay]提供了基于embedded-hal的延迟特性
  • [time] 仅处理单调递增的刻度计数,它仅仅是一个抽象,需要一个全局的[time driver]具体实现。

个人理解time只是一个抽象,需要相应的运行环境的time driver支持。源码树中自带了driver.rs和std、wasm环境的driver、用于测试的mock driver,分别位于drvier_std.rs、driver_wasm.rs和drvier_mock.rs,后续只分析std环境的源码。

crate开放的接口(lib.rs)

  1. 公开上述除time外的接口
  2. 定义时钟频率常量TICK_HZ。它是整个crate的基准,依据运行环境不同而不同。源码中使用get_tick.py,自动生成Cargo.toml中tick的内容和src/tick.rs的内容。
  3. 定义gcd函数,用于定义常量GCD_1K和GCD_1M,目的应该是为了提升精度。
  4. 根据Cargo.toml的描述,定义了“defmt-timestamp-uptime“ feature时,在日志消息中添加系统启动到当前的秒数。

公开接口介绍

接下来按lib.rs中public的顺序和相互逻辑来介绍

duration.rs

定义了Duration结构

pub struct Duration {
    pub(crate) ticks: u64,
}

它仅包含一个u64类型的ticks字段。后续定义了如下系列函数:

  1. MIN、MAX常量,其值分别是ticks为u64::MIN和u64::MAX的Duration类型。
  2. 静态函数,以ticks(u64)、秒、毫秒、微秒的方式获取Duration的值。
  3. 静态函数,以ticks(u64)、秒、毫秒、微秒的方式将传入的值转换为Duration实例。并且提供对应的取整变形(from_xxx_floor)。
  4. 提供从频率(hz)到Duration的转换函数from_hz(hz: u64) -> Duration。
  5. 提供上述转换用到的加减乘除函数
  6. 提供加减乘除的trait实现,和对应的xxxAssign trait实现,其中乘除的四种trait还实现了u32类型参数的实现。
  7. 实现了fmt::Display trait。
  8. 实现了core::time::Duration到Duration的TryFrom和From trait。

driver.rs

时间驱动的定义集中在这里。末尾定义了time_driver_impl宏提供了便捷的方式来实现time driver。

通过Driver trait,定义了以下必须实现的接口函数:

  • now(&self) -> u64: 函数必须是单调增的
  • allocate_alarm(&self) -> Option<AlarmHandle>: 定义报警,注意需要先设置回调,否则会导致未定义行为(UB)
  • set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()): 设置当报警触发时执行的回调函数,在中断或线程模式下均可执行。
  • set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool: 在给定的时间戳处设置警报。

其中用到的AlarmHandle定义如下:

pub struct AlarmHandle {
    id: u8,
}

它实现了两个成员函数:

  • new(id: u8) -> Self: 用给定的id创建AlarmHandle实例
  • id(&self):返回当前实例的id。

instant.rs

  • 跟duration.rs类似,也提供了以ticks(u64)、秒、毫秒、微秒的方式将传入的值转换为Instant实例的方法。
  • 跟duration.rs类似,也提供了从Instant实例以ticks(u64)、秒、毫秒、微秒的方式返回ticks的方法
  • 提供上述转换用到的加减乘除函数
  • 提供加减乘除的trait实现,和对应的xxxAssign trait实现
  • 实现了fmt::Display trait

delay.rs

queue.rs