Embassy 执行器(executor)
Embassy executor是一个为嵌入式使用而设计的异步/等待(async/await)执行器,它支持中断和定时器功能。
特点
-
不需要
堆内存分配(alloc)
, 不需要堆,任务静态分配。 -
没有“固定容量”的数据结构,执行器可以处理1个或1000个任务,无需设置/调整。
-
集成的定时器队列:睡眠(sleep)很简单,只需执行
Timer::after_secs(1).await;
。 -
没有忙等(busy-loop)轮询: 当没有工作要做时,CPU会使用中断或
WFE/SEV
休眠。 -
高效的轮询:唤醒操作只会轮询被唤醒的任务,而不是所有任务。
-
平均:即使一个任务不断被唤醒,它也不能垄断CPU时间。在任务第二次被轮询之前,所有其他任务都有机会运行。
-
Embassy支持创建多个Executor实例,以在不同优先级上运行任务,可以让高优先级任务抢占低优先级任务。
执行器
执行器(Executor)的功能如下所述:它维护一个应该轮询的任务队列。当一个任务被创建时,会被轮询(1)。任务将尝试取得进展,直到它到达一个可能被阻塞的点。这可能发生在任务正在等待一个异步函数时。当这种情况发生,任务通过返回 Poll::Pending
(2)来让出执行权。一旦任务让出,执行器就会将任务排到运行队列的末尾,并继续轮询队列中的下一个任务(3)。当一个任务完成或取消后,它不会再次进入队列。
Executor需要不会无限期阻塞的任务,因为这会阻止执行器重新获得控制权并调度另一个任务。 |

如果您在应用程序中使用 #[embassy_executor::main]
宏,它会为您创建 Executor
并将入口点作为第一个任务。您也可以手动创建Executor,实际上,您可以创建多个Executor。
中断
中断是外设用来标志某些操作完成的常见方式,这与异步执行模型非常契合。下面的图表描述了一个典型的应用流程,其中(1)一个任务被轮询并尝试取得进展。然后任务(2)指示外设执行某项操作,并等待(await)。一段时间过后,(3)中断触发,标志着操作的完成。
然后外设HAL(4)确保中断信号被传输(route)到外设,并根据操作结果来更新外设状态。然后Executor(5)被通知应该轮询该任务,然后它就会这么做。

有一个名为 InterruptExecutor 的特殊执行器,它可以由中断驱动。可以通过创建多个 InterruptExecutor 实例,用来在不同优先级上驱动任务。
|
Time
Embassy提供了一个内部定时器队列,可以通过 time
feature 来启用。 Embassy假定平台上存在一个时钟 驱动
实现。 Embassy为nRF、STM32、RPi Pico、WASM和Std平台提供了时钟驱动(time driver)。
嵌入式平台的定时器驱动(timer driver)实现可能只支持设置固定数量的闹钟(alarm)。确保您希望同时使用定时器的任务数量不超过此限制。
定时器的速度可以在编译时使用 time-tick-<frequency>
来配置。目前,定时器可以配置为1000 Hz、32768 Hz或1 MHz。在更改默认设置之前,请确保目标芯片的HAL支持此频率设置。
如果您的应用程序不需要定时器,不启用 time feature 可以节省一些CPU周期并减少功耗。
|