Rust嵌入式时间队列驱动库embassy-time-queue-driver的使用,高效管理异步任务与定时事件
Rust嵌入式时间队列驱动库embassy-time-queue-driver的使用,高效管理异步任务与定时事件
embassy-time-queue-driver crate 包含了 embassy-time 定时器队列使用的驱动 trait。
通常情况下不需要直接使用这个 crate,只有在实现自定义定时器队列时才需要用到它。
目前有两个定时器队列实现:
- 在 embassy-time 中,通过 generic-queue 特性启用
- 在 embassy-executor 中,通过 integrated-timers 特性启用
示例代码
use embassy_time_queue_driver::{TimerQueueDriver, TimerQueueInstant};
// 自定义定时器队列驱动实现示例
struct MyTimerDriver;
impl TimerQueueDriver for MyTimerDriver {
type Instant = MyInstant;
type Ticks = u64;
fn now(&self) -> Self::Instant {
// 实现获取当前时间
MyInstant(0)
}
fn ticks_from_nanos(&self, nanos: u64) -> Self::Ticks {
// 实现纳秒转ticks
nanos / 1000
}
fn set_alarm(&self, _timestamp: Self::Instant, _ticks: Self::Ticks) {
// 实现设置闹钟
}
fn disable_alarm(&self) {
// 实现禁用闹钟
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct MyInstant(u64);
impl TimerQueueInstant for MyInstant {
fn checked_add(self, duration: embassy_time::Duration) -> Option<Self> {
self.0.checked_add(duration.as_nanos() as u64).map(MyInstant)
}
fn checked_sub(self, duration: embassy_time::Duration) -> Option<Self> {
self.0.checked_sub(duration.as_nanos() as u64).map(MyInstant)
}
}
// 使用示例
#[embassy_executor::main]
async fn main(_spawner: embassy_executor::Spawner) {
let driver = MyTimerDriver;
// 创建定时器队列
let queue = embassy_time::TimerQueue::new(driver);
// 设置定时任务
queue.set_timeout(embassy_time::Duration::from_secs(1), || {
println!("1秒后执行");
});
}
完整示例demo
以下是一个更完整的示例,展示了如何使用embassy-time-queue-driver创建一个简单的定时任务系统:
use embassy_time::{Duration, TimerQueue};
use embassy_time_queue_driver::{TimerQueueDriver, TimerQueueInstant};
use embassy_executor::Spawner;
// 自定义时间点类型
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct MyInstant(u64);
impl TimerQueueInstant for MyInstant {
fn checked_add(self, duration: Duration) -> Option<Self> {
self.0.checked_add(duration.as_nanos() as u64).map(MyInstant)
}
fn checked_sub(self, duration: Duration) -> Option<Self> {
self.0.checked_sub(duration.as_nanos() as u64).map(MyInstant)
}
}
// 自定义定时器驱动实现
struct MyTimerDriver {
current_time: core::sync::atomic::AtomicU64,
}
impl TimerQueueDriver for MyTimerDriver {
type Instant = MyInstant;
type Ticks = u64;
fn now(&self) -> Self::Instant {
MyInstant(self.current_time.load(core::sync::atomic::Ordering::Relaxed))
}
fn ticks_from_nanos(&self, nanos: u64) -> Self::Ticks {
nanos / 1000 // 将纳秒转换为微秒
}
fn set_alarm(&self, timestamp: Self::Instant, ticks: Self::Ticks) {
println!("设置闹钟在 {} ticks 后触发 ({} 绝对时间)", ticks, timestamp.0);
}
fn disable_alarm(&self) {
println!("禁用闹钟");
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// 创建定时器驱动实例
let driver = MyTimerDriver {
current_time: core::sync::atomic::AtomicU64::new(0),
};
// 创建定时器队列
let queue = TimerQueue::new(driver);
// 设置多个定时任务
queue.set_timeout(Duration::from_secs(1), || {
println!("任务1: 1秒后执行");
});
queue.set_timeout(Duration::from_secs(3), || {
println!("任务2: 3秒后执行");
});
queue.set_timeout(Duration::from_millis(500), || {
println!("任务3: 500毫秒后执行");
});
// 模拟时间流逝
for i in 1..=5 {
println!("当前时间: {}秒", i);
// 更新时间
driver.current_time.store(i * 1_000_000_000, core::sync::atomic::Ordering::Relaxed);
// 检查定时任务
queue.check_alarms();
embassy_time::Timer::after(Duration::from_secs(1)).await;
}
}
安装
在项目目录中运行以下Cargo命令:
cargo add embassy-time-queue-driver
或者在Cargo.toml中添加:
embassy-time-queue-driver = "0.1.0"
许可证
MIT OR Apache-2.0
1 回复
embassy-time-queue-driver: Rust嵌入式时间队列驱动库
介绍
embassy-time-queue-driver
是 Embassy 嵌入式框架中的一个时间队列驱动库,专门为嵌入式系统设计,用于高效管理异步任务和定时事件。它提供了轻量级的时间管理功能,特别适合在资源受限的嵌入式环境中使用。
主要特性
- 轻量级实现,适合资源受限的嵌入式环境
- 精确的时间管理功能
- 支持异步任务调度
- 与 Embassy 异步运行时无缝集成
- 低功耗设计,适用于电池供电设备
使用方法
添加依赖
首先,在 Cargo.toml
中添加依赖:
[dependencies]
embassy-time-queue-driver = "0.1"
embassy-executor = "0.1"
embassy-time = { version = "0.1", features = ["time-driver"] }
基本示例
use embassy_time::{Duration, Timer};
use embassy_executor::Spawner;
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
// 简单的延时示例
Timer::after(Duration::from_millis(500)).await;
println!("500ms elapsed");
// 周期性任务
loop {
Timer::after(Duration::from_secs(1)).await;
println!("1 second elapsed");
}
}
定时任务管理
use embassy_time::{Duration, Timer};
use embassy_executor::Spawner;
#[embassy_executor::task]
async fn periodic_task(interval: Duration) {
loop {
// 执行周期性工作
println!("Periodic task executed");
Timer::after(interval).await;
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// 启动周期性任务,每2秒执行一次
spawner.spawn(periodic_task(Duration::from_secs(2))).unwrap();
// 主任务可以做其他工作
loop {
Timer::after(Duration::from_secs(5)).await;
println!("Main task check-in");
}
}
超时处理
use embassy_time::{Duration, Timer, TimeoutError};
async fn do_something_with_timeout() -> Result<(), TimeoutError> {
// 模拟一个可能超时的操作
Timer::after(Duration::from_millis(100)).await;
Ok(())
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
// 设置500ms超时
match embassy_time::with_timeout(Duration::from_millis(500), do_something_with_timeout()).await {
Ok(_) => println!("Operation completed successfully"),
Err(TimeoutError) => println!("Operation timed out"),
}
}
硬件定时器集成
use embassy_time::driver::{Driver, AlarmHandle};
use embassy_time::{Duration, Instant};
struct MyDriver;
impl Driver for MyDriver {
fn now(&self) -> u64 {
// 实现获取当前时间的逻辑
// 通常从硬件定时器读取
0
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
// 分配警报句柄
Some(AlarmHandle::new(0))
}
fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) {
// 设置硬件定时器在指定时间触发
}
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let driver = MyDriver;
embassy_time_driver::impl_driver_global!(driver);
// 现在可以使用embassy_time的各种功能
Timer::after(Duration::from_millis(100)).await;
}
完整示例:嵌入式系统多任务定时器
下面是一个完整的嵌入式应用示例,展示如何使用embassy-time-queue-driver
管理多个定时任务:
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use core::fmt::Write;
use heapless::String;
// 定义两个异步任务
#[embassy_executor::task]
async fn task_led_controller(interval: Duration) {
loop {
// 模拟LED切换
println!("LED state toggled");
Timer::after(interval).await;
}
}
#[embassy_executor::task]
async fn task_sensor_reader(interval: Duration) {
let mut count = 0;
loop {
// 模拟传感器读数
let mut buf: String<32> = String::new();
write!(&mut buf, "Sensor reading #{}: {}", count, 42).unwrap();
println!("{}", buf);
count += 1;
Timer::after(interval).await;
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
println!("Starting embedded application with embassy-time-queue-driver");
// 启动LED控制任务,每秒执行一次
spawner.spawn(task_led_controller(Duration::from_secs(1))).unwrap();
// 启动传感器读取任务,每2秒执行一次
spawner.spawn(task_sensor_reader(Duration::from_secs(2))).unwrap();
// 主任务打印系统状态
let mut system_uptime = 0;
loop {
println!("System uptime: {} seconds", system_uptime);
system_uptime += 5;
Timer::after(Duration::from_secs(5)).await;
}
}
最佳实践
-
合理设置时间精度:根据应用需求选择合适的时间精度,过高的精度会增加功耗。
-
避免长时间阻塞:在异步任务中避免长时间阻塞操作,以免影响其他定时任务的执行。
-
错误处理:总是处理可能的超时错误,特别是在网络或外设操作中。
-
低功耗设计:在电池供电设备中,合理使用
Timer
可以让处理器在等待期间进入低功耗模式。
embassy-time-queue-driver
为嵌入式Rust开发提供了强大而高效的时间管理功能,特别适合需要精确时间控制和低功耗设计的应用场景。