执行器 Executor#
原文: https://embassy.dev/book/dev/runtime.html
Embassy 执行器(executor)是一个为嵌入式设计的异步/等待(async/await)执行器,支持中断和定时器。
功能特性#
无需手动分配,不需要堆;任务都是静态分配的。
动态大小;无需配置或调整,执行器就可以1到1000个任务;
集成的定时队列:很简单就可以实现休眠,只需要
Timer::after_secs(1).await;
无需一直轮询:没有任务时,配合中断或
WFE/SEV
(Wait For Event/Wait For Interrupt),CPU可以进入休眠状态;高效轮询:执行器只会轮询已经被唤醒的任务,而不是所有任务;
公平:即使给定任务不断被唤醒,给定任务也不会独占CPU时间。在给定任务第二次轮询之前,其他任务都有机会运行。
支持创建多个执行器实例,并以不同优先级运行任务。遇到优先级低的任务,较高优先级的任务可以抢占运行。
执行器#
执行器功能的描述如下:
执行器保存一个它需要轮询的任务队列.
当一个任务被创建时,执行器执行器
Poll
(1).该任务将尝试运行,取得进展,直到被阻. 当任务正在等待异步函数时,就可能会发生这种情况。但这种情况发生时,任务通过(2)返回
Poll::Pending
.一旦任务让出,执行器就会将改任务加入运行队列的末尾,并继续执行(3)来拉取队列中的下一个任务。当任务完成或取消时,它无需再次入队;
执行器依赖于不会一直阻塞的任务,因为这会阻止执行器重新获得控制权来调度另一个任务。
如果在你的应用程序中使用了#[embassy_executor::main]
宏,那它就会为你创建执行器,并创建主入口点来作为第一个任务。你也可以手动创建执行器,而且可以创建多个执行器。
中断#
中断是外设发出操作完成信号的通用机制,这种机制很适合异步执行模型。下图描述一个典型的应用执行流程:
(1)任务被轮询,并尝试取得进展。
(2)任务知识外设执行某些操作,并等待。
经过一段时间后,(3)发出中断,标志这操作完成。
然后(4)HAL 确保中断信号被路由到外设,使用操作的结果来更新外设的状态。
然后(5)执行器收到通知,任务可以继续被轮询。
这里有一个叫
InterruptExecutor
的特殊执行器,他由中断驱动。通过创建多个InterruptExecutor
实例,可以驱动不同优先级的任务。
定时#
Embassy 有一个内部的定时器队列,可以通过设置time
特性标记来启用。启用后,Embassy 假定平台已经存在一个计时器的驱动的实现。Embassy 为 nRF、STM32、RPi Pico、WASM 和 Std 平台提供了时间驱动程序。
嵌入式平台的定时器驱动程序的实现,可能仅支持设置固定数量的警报。请确保你同时使用的计时器任务数量不超过此限制。
定时器速度可在编译时使用time-tick-<frequency>
配置。目前,定时器可以配置为以 1000 Hz、32768 Hz 或 1 MHz 来运行。在更改默认值之前,请确保目标 HAL 支持特定频率的设置。
如果您的应用程序不需要计时器,则不要启用
time
功能,这样可以节省一些 CPU 周期并降低功耗。