Embassy源码分析-time
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)
- 公开上述除time外的接口
- 定义时钟频率常量TICK_HZ。它是整个crate的基准,依据运行环境不同而不同。源码中使用
get_tick.py
,自动生成Cargo.toml中tick的内容和src/tick.rs的内容。 - 定义gcd函数,用于定义常量GCD_1K和GCD_1M,目的应该是为了提升精度。
- 根据Cargo.toml的描述,定义了“defmt-timestamp-uptime“ feature时,在日志消息中添加系统启动到当前的秒数。
公开接口介绍
接下来按lib.rs中public的顺序和相互逻辑来介绍
duration.rs
定义了Duration结构
它仅包含一个u64类型的ticks字段。后续定义了如下系列函数:
- MIN、MAX常量,其值分别是ticks为u64::MIN和u64::MAX的Duration类型。
- 静态函数,以ticks(u64)、秒、毫秒、微秒的方式获取Duration的值。
- 静态函数,以ticks(u64)、秒、毫秒、微秒的方式将传入的值转换为Duration实例。并且提供对应的取整变形(from_xxx_floor)。
- 提供从频率(hz)到Duration的转换函数from_hz(hz: u64) -> Duration。
- 提供上述转换用到的加减乘除函数
- 提供加减乘除的trait实现,和对应的xxxAssign trait实现,其中乘除的四种trait还实现了u32类型参数的实现。
- 实现了fmt::Display trait。
- 实现了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定义如下:
它实现了两个成员函数:
- 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