rust嵌入式开发之RTICvsEmbassy
RTIC和Embassy是目前rust嵌入式开发中比较热门的两个框架。本来呢,针对RTIC的移植已经完成了一小半,但在移植过程中感受到了RTIC的不足,正好跳出来全面考察下embassy,本文就是根据目前的尝试结果做个对比总结。
RTIC和Embassy是两种完全不同的思路:
1、RTIC是基于MCU强大的中断体系以中断来驱动,所以RTIC的重心是放到了数据的隔离上,可参考rust嵌入式开发补充,整个框架,不管是处理还是规模都比较简单
2、Embassy则是基于rust语言的异步特性【async和await】、Send等来实现线程化并确保安全
也就是说,一个依托底层MCU,一个依托rust语言,所以分别形成了自己的特色。
RTIC的优缺点
RTIC的优点就是简便,一旦理解了RTIC的工作机制,开发起来只要牢记三个方面就好了:
- 中断驱动:所有的任务调用源头都是某个硬件中断,是天然的事件-响应模型,以此模型来编写各个处理任务,然后将这些任务分配到相应的硬件中断中spawn就好了,逻辑非常清晰、简洁
- 数据隔离:RTIC将数据分为了本地和共享两类,本地数据为某个任务独享,其它任务全都无法访问;共享数据为指定的某几个任务共享,使用时需加锁来互斥使用。确保了数据安全,而且数据的访问逻辑也非常清晰,不容易混乱,使用上也非常简单,不会出现复杂的Option<Arc<Mutex<…>>>的形式【RTIC自己做了,提供给用户任务时就是复制过来的数据指针了】
- 优先级:RTIC依靠MCU进行任务的调度,而MCU不管其它,只依靠中断许可和优先级进行调度。所以,优先级就是RTIC工作的基石,如果用户任务较多,就需要仔细考虑这些任务的调配和优先级的匹配问题
RTIC的缺点就是过于简单,对rust的特性支持不够,面对稍微复杂点的任务,就有些力不从心了。
首先,上面讲了RTIC良好的数据隔离机制,但反过来,由于用户任务中的数据,都来自RTIC从自己所管理的全局数据中的复制,所以RTIC的用户任务中,很难使用闭包,因为其所有的数据都是从栈上分配的,一旦离开所在用户任务就会被销毁,而RTIC中所有任务都是中断驱动。这两点决定了RTIC中的闭包无法异步使用,但不能脱离本地来异步使用的闭包,一点价值都没有的。
而如果自己用box来保存与复制,那何不干脆另起一个用户任务呢?!
但每个RTIC的用户任务的参数都是通过宏扩写出来的,所以用户任务很难通过指针的方式按需调度,这对状态机、控制台命令、远程控制等功能很不友好。
也就是说,RTIC最大的问题就是不灵活,一旦需要灵活的根据实际情况来动态调用用户任务,RTIC就会很笨拙。需要通过静态函数和统一的参数表,来为用户任务的调用提供参数转换和过渡。这对于状态机还好,但对于控制台命令和远程控制就很不友好了。
其次,RTIC是用过程宏来完成规模庞大的任务和数据的扩写工作的【对rust的过程宏还不太理解的可参考:rust嵌入式之用类函数宏简写状态机定义】,但由于其对过程宏的重度使用,使得我们编写自己的过程宏然后和RTIC进行衔接时,就不能触碰所有的数据和用户任务,只能通过上面提到的静态函数来进行过渡。
而这,自然就会大幅度的削弱过程宏的强大与便利了。
Embassy的优缺点
Embassy我才刚开始尝试,所以就只能对比上面RTIC的优缺点来说了。
1、Embassy既然是依托rust的async和await来调度任务,所以其必须实现自己的一个运行时来完成中断接管、poll登记与分发、基于优先级的任务调度等等
运行时的存在,自然会提供更好的灵活性和弹性,更有利于充分发挥rust作为现代语言的优势与强大。
2、Embassy提供了强大的线程间通信手段,如Channel和mbox,这就非常便于复杂业务场景下各功能部件之间的密切协作了
3、任务的创建手段更灵活、更便利,如:
方式一:独立任务模式:
#[embassy_executor::task]
async fn writer(mut tx: UartTx<'static, USART1, DMA1_CH4>) {#串口1通过一个Channel接收要发送的字符串,然后以DMA方式发送loop {let buf = CHANNEL.receive().await;unwrap!(tx.write(buf.as_bytes()).await);}
}
在主程序中启动该任务:
unwrap!(spawner.spawn(writer(tx)));
如此,不管在哪,只要通过Channel发送字符串就可以执行:
CHANNEL.send(s).await;
方式二:闭包模式:
//主程序中定义一个闭包
let blinky = async {loop {//注意,这里直接使用了主程序创建的led和delay两个局部变量【rust会自动将其分配到堆上去】//其它闭包也可以使用这两个变量【对于没有实现Copy的,需要考虑借用问题】//当然,如果多个闭包同时使用到某个复杂的数据结构,需要实现Send或用Mutex等实现线程间数据保护led.toggle();Timer::after_millis(delay).await;}
};
//将这个闭包启动
futures::join!(blinky, ...其它闭包...);
RTIC可以同样很简单的实现方式一,但根本无法实现方式二。而对于大量简单的小任务来说,显然方式二更简便,同时还省去了RTIC中复杂的数据隔离措施,更轻更快。
此外,Embassy对过程宏的使用不是太过严重,甚至还可以在Embassy项目中支持RTIC框架,结合其对闭包的友好支持,我们完全可以在用过程宏来定义状态机、控制台命令时直接用闭包来实现动作或命令的实现函数,既省去了过渡函数的繁琐,还更容易阅读与理解,降低了bug的几率。
当然,Embassy不提供如RTIC般的数据隔离与保护,所以线程间的数据保护就需要程序员自己来承担了。
总结
如开头所述,RTIC其实是一种中断驱动的嵌入式任务调度思想的rust实现【增强了数据隔离与保护】,而Embassy则是rust语言用于嵌入式环境的一种实现【所有其有两个发力点:运行时和基于自己HAL的各种芯片的适配】。
显然,RTIC更容易上手,更针对固定功能的嵌入式开发;而Embassy更有rust味道,更灵活、更强大,给予了程序员更丰富的支持,同时也对程序员提出了rust特有的高要求、高门槛。
当然,rust嵌入式开发还有tock,在Embassy之前,笔者也是更看好tock,但仔细研究了几天,笔者认为就嵌入式来说,tock属于过度设计了:
- 资源占用过于庞大,flash需256K起,ram需64K起,对于大多数的嵌入式应用来说,实无必要
- tock的一个诉求是彼此隔离所以安全的app,但对于嵌入式来说,实在有些过分了
所以,tock是针对一个复杂产品的中控来设计的。由于我们目前尚无此需求,所以我们显然不是tock预期中的目标群体。因此很快就转向Embassy了。
相关文章:
rust嵌入式开发之RTICvsEmbassy
RTIC和Embassy是目前rust嵌入式开发中比较热门的两个框架。本来呢,针对RTIC的移植已经完成了一小半,但在移植过程中感受到了RTIC的不足,正好跳出来全面考察下embassy,本文就是根据目前的尝试结果做个对比总结。 RTIC和Embassy是两…...
Bug地狱 #1 突然宕机,企业级应用到底怎么了
Bug地狱 #1 突然宕机,企业级应用到底怎么了 背景 目前就职的企业经营是一家服务小微门店Saas企业,以进销存管理和客户营销为主体提供订阅服务。项目正式上线可以说是从13年,基础架构是Web和后端使用C# .net,数据库使用SQL Serve…...
使用 Python、Elasticsearch 和 Kibana 分析波士顿凯尔特人队
作者:来自 Jessica Garson 大约一年前,我经历了一段压力很大的时期,最后参加了一场篮球比赛。 在整个过程中,我可以以一种我以前无法做到的方式断开连接并找到焦点。 我加入的第一支球队是波士顿凯尔特人队。 波士顿凯尔特人队是…...
探索C语言结构体:编程中的利器与艺术
✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C语言学习 贝蒂的主页:Betty‘s blog 1. 常量与变量 1. 什么是结构体 在C语言中本身就自带了一些数据类型&#x…...
Git介绍与常用命令总结
Git介绍与其常用命令总结 1、Git介绍2、Git的使用3、Git常用命令3.1 初始化仓库3.2 克隆仓库3.3 配置用户信息3.4 提交代码(Commit)3.5 推送代码(Push)3.6 拉取代码(Pull)3.7 分支(Branch)3.8 远程仓库(Remote)3.9 撤销回退本地改动3.10 更新本地仓库与远程仓库 1、Git介绍 Gi…...
机器学习 | 探索朴素贝叶斯算法的应用
朴素贝叶斯算法是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域,并且在实际应用中表现出色。 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法: 1)对于给定的待分类项r…...
【无刷电机学习】电流采样电路硬件方案
【仅作自学记录,不出于任何商业目的】 目录 AD8210 INA282 INA240 INA199 AD8210 【AD8210数据手册】 在典型应用中,AD8210放大由负载电流通过分流电阻产生的小差分输入电压。AD8210抑制高共模电压(高达65V),并提供接地参考缓冲输出&…...
对于协同过滤算法我自己的一些总结和看法
文章目录 协同过滤算法的基本原理协同过滤算法的分类用户相似度计算UserCF && ItemCF应用场景 协同过滤算法的优缺点优点缺点 协同过滤算法的总结与展望Q&A 协同过滤算法的基本原理 关于协同过滤算法,我看过很多老师写的博客以及一些简单的教程&#x…...
数据库管理phpmyadmin
子任务1-PHPmyadmin软件的使用 本子任务讲解phpmyadmin的介绍和使用操作。 训练目标 1、掌握PHPmyadmin软件的使用方法。 步骤1 phpMyAdmin 介绍 phpmyadmin是一个用PHP编写的软件工具,可以通过web方式控制和操作MySQL数据库。通过phpMyAdmin可以完全对数据库进行…...
Oracle数据表ID自增操作
一、Oracle ID自增长功能介绍 Oracle数据库默认不支持像 SQLServer、MySQL中的自增长(auto increment)功能,即自动为每一行记录的自增长字段生成下一个值。 二、Oracle ID自增长方法 第一种,通过序列(sequence&#…...
npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher
当使用npm下载vue3-lazy时出现一下错误时的解决方案 报错:npm WARN deprecated uuid3.4.0: Please upgrade to version 7 or higher 尝试使用过一下命令更新 npm install uuidlatest -g 是安装了最新版本的uuid, 再次下载已解决问题 ***但看某些播客依…...
第2节、让电机转起来【51单片机+L298N步进电机系列教程】
↑↑↑点击上方【目录】,查看本系列全部文章 摘要:本节介绍用简单的方式,让步进电机转起来。其目的之一是对电机转动有直观的感受,二是熟悉整个开发流程。本系列教程必要的51单片机基础包括IO口操作、中断、定时器三个部分&#…...
1154: 第多少天
题目描述 定义一个包括年、月、日的结构体变量,读入年、月、日,计算该日在当年中是第几天。注意闰年问题。 输入描述 三个整数,分别表示年、月、日。保证输入是实际存在的日期,且年份在1000至3000之间(包含1000和30…...
【C语言初阶-const作用详解】const修饰变量、const修饰指针(图文详解版)
少年,做你认为对的事 目录 少年,做你认为对的事 1.const修饰变量 2.const修饰指针(重要) 代码1: 代码2: 代码3: 编辑 3.结论 1.const修饰变量 const修饰变量将变量赋予了常量属性…...
线程协作工具类【CountDownLatch倒数门闩、Semaphore信号量、CyclicBarrier循环栏栅、Condition接口】
线程协作工具类 CountDownLatch倒数门闩Semaphore信号量CyclicBarrier循环栅栏CyclicBarrier和CountDownLatch区别: Condition接口(条件对象) 转自 极客时间 线程协作工具类就是帮助程序员更容易的让线程之间进行协作,来完成某个业务功能。 CountDownLatch倒数门闩…...
Python 函数式编程进阶:map、filter、reduce
Python 函数式编程进阶:map、filter、reduce 介绍map 函数作用和语法使用 map 函数Lambda 函数的配合应用 filter 函数作用和语法使用 filter 函数Lambda 函数的结合运用 reduce 函数作用和语法使用 reduce 函数典型应用场景 介绍 在函数式编程中,map、…...
大模型|基础_word2vec
文章目录 Word2Vec词袋模型CBOW Continuous Bag-of-WordsContinuous Skip-Gram存在的问题解决方案 其他技巧 Word2Vec 将词转化为向量后,会发现king和queen的差别与man和woman的差别是类似的,而在几何空间上,这样的差别将会以平行的关系进行表…...
14.2 url后端过滤器(❤❤)
14.2 过滤器 1. 过滤器Filter1.1 配置形式实现过滤器1.2 过滤器生命周期1.3 过滤器特性(面试点)1.4 注解形式实现过滤器1.5 两种实现的选择2. 应用2.1 字符集过滤:统一设置请求与响应字节编码1. 配置方式实现过滤器参数化:init-param标签关键代码完整代码2. 注解方式实现2.2 多…...
Leetcode 377 组合总和 Ⅳ
题意理解: 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 这道题目和凑零钱是一样的,需要求使用指定元素(纸币…...
CleanMyMacX4.14.6如何清理mac垃圾内存
一直以来,苹果电脑的运行流畅度都很好,但是垃圾内存多了磁盘空间慢慢变少,还是会造成卡顿的。这篇文章就告诉大家电脑如何清理垃圾内存,电脑如何清理磁盘空间。 一、电脑如何清理垃圾内存 垃圾内存指的是各种缓存文件和系统垃圾…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
