开发者生态
morning
异步 Rust 与 RTOS 的对决 (2022)
2026-09-03
1 阅读
约6分钟阅读
kooi
字号:
现在是时候写另一篇关于嵌入式异步 Rust 的技术博客文章了。这一次,我们将在 STM32F446 微控制器上将 Embassy/Rust 与 FreeRTOS/C 进行对比。现在是时候写另一篇关于嵌入式异步 Rust 的技术博客文章了。这一次,我们将在 STM32F446 微控制器上将 Embassy/Rust 与 FreeRTOS/C 进行对比。它们都将运行执行相同操作的应用程序。然后,我们将根据中断延迟、程序大小、RAM 使用情况和编程难易程度来判断它们。已经有很多文章比较 C 和 Rust,所以我们今天不重点讨论这个。我将尝试展示两个“正常”应用程序。这两个项目都可以通过大量工作进行调整以提供更好的性能。这样做可能是一项几乎永无休止的任务。因此,作为指导原则,应用程序将是: 可移植(-ish)到其他芯片和架构(除了对 HAL 的依赖之外) 简单 通过编译器优化、RTOS 设置和线程优先级等常规选项和设置进行调整 最后,我们应该对 RTOS 和异步执行器如何工作有一个基本的了解。我有偏见,但我希望这篇博文能够提供公平的比较。如果您有建议,请告诉我们!我们将使用 STM32F446ZET6 微控制器在 180Mhz 下进行测试,部分测量将使用 Rigol DS1054Z 示波器完成。异步 Rust Rust 中的异步函数是返回 future 的函数的语法糖。 pub 特征 Future { 类型输出 ; fn poll ( self : Pin<& mut Self >, cx: & mut Context< '_ >) -> Poll< Self ::Output>;该函数被转换为可以轮询的状态机对象。状态机允许代码跳转到函数中,从之前停止的地方恢复。它还跟踪跨等待点保留的所有变量。 Rust 期货是惰性的,它们只在轮询时运行。要运行 future 直至其完成,您所要做的就是连续调用 poll 函数,直到它停止返回 Pending 状态并返回 Ready(Output) 状态。这很简单,但效率不高。为了解决这个问题,还有 Wakers 。唤醒者可以向执行者发出信号,表明未来应该再次轮询。该唤醒程序可以由 future 本身调用,也可以提供给 future 所依赖的另一个进程/线程。一般来说,执行器会调用 poll 函数一次,然后只有在唤醒器被触发时才会再次调用它。一个 future 可以调用其他 future 并将它们合并到自己中。对于执行器来说,它轮询的任何顶级 future 通常称为任务。还可以说的还有很多。幸运的是,我不必这样做,因为那里有一些非常好的资源:在大使馆中,大使馆也使用这种机制,但增加了一些限制。任务必须静态分配 Embassy 不想依赖分配器 所有任务必须在编译时已知 需要夜间编译器 需要 type_alias_impl_trait 预览功能 这是因为我们无法使用装箱特征对象,因为没有分配器 对于许多外设,Embassy 制作了一个异步接口。这允许使用以下代码: #[embassy::task] async fn my_task(mut button: ExtiInput<'static, PC13>) {loop {button.wait_for_rising_edge().await;信息!(“按下!”); Button.wait_for_falling_edge().await; info!("发布了!");这里发生了一些事情。 wait_for_rising_edge 创建一个新的 future 并返回它。 future的构造函数配置pin的中断。在第一次民意调查中,未来将其唤醒器放入 EXTI 唤醒器的全局数组中。当 EXTI 中断发生时,该数组中适当的唤醒器用于唤醒正确的任务。因此,当中断退出时,执行器再次轮询任务,wait_for_rising_edge future 注意到它的中断已触发并返回它已准备好。就这样,计划继续进行。 Embassy 不做的一件事是抢占,这意味着活动任务只有在等待某些事情时才会切换到更重要的任务。这称为协作多任务处理。但是,Embassy 还有其他一些功能可以让这个缺失的功能不再是问题,本文稍后将对此进行介绍。 RTOS 实时操作系统将所有内容划分为独立的线程。与任务不同的是,线程不运行状态机,而是运行普通代码。这意味着您不必以特殊方式编写代码。任何旧功能都可以在 RTOS 中运行。当必须暂停一个线程的执行以切换到另一个线程时,必须捕获并保存整个处理器上下文,因为该线程正在运行正常代码。当该代码恢复时,它将要求处理器上下文再次相同。这种多线程设计适合抢占式线程。这意味着内核可以为所有线程提供公平的执行时间,用户可以指定优先级,并且内核可以在一个线程中响应事件和中断。
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱