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了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 651 (Div. 2)C. Number Game 博弈 奇偶数 偶数的表示

Submission #244500083 - Codeforces 题目&#xff1a; 思路&#xff1a; 此题要从奇偶性上入手。&#xff08;注意除的是奇因数&#xff0c;即一个奇数。我想成质数了&#xff09; 1.当A选手开局是1时&#xff0c;A败。 2.当A选手开局是2和奇数时&#xff0c;A必胜。&…

Golang context 万字解析实现原理

Golang&#xff1a;context基于go1.21版本 Context 是什么Context 的功能应用场景源码分析1.10 Context核心结构1.1Err错误2 .1 emptyCtx 3.1 Background() 和 TODO()4.1.1 cancelCtx4.1.2 Deadline 方法4.1.2 Done 方法4.1.2 Err 方法4.1.2 Value 方法 4.2 WithCancel() 和 Wi…

vue2 el-table新增行内删除行内(两种写法)里面第一个是树组件,第二个是数字组件,第一个数组件只能勾选最后一个节点

第一种 <template><div class"time_table"><div style"margin-bottom: 10px"><el-button click"addRowFn">新增</el-button></div><el-form ref"costForm" :model"formData">&l…

备战蓝桥杯---搜索(剪枝)

何为剪枝&#xff0c;就是减少搜索树的大小。 它有什么作用呢&#xff1f; 1.改变搜索顺序。 2.最优化剪枝。 3.可行性剪枝。 首先&#xff0c;单纯的广搜是无法实现的&#xff0c;因为它存在来回跳的情况来拖时间。 于是我们可以用DFS&#xff0c;那我们如何剪枝呢&#…

Http请求Cookie失效问题

Http请求Cookie失效问题记录 一、问题现象 在开发功能的过程中&#xff0c;业务依赖cookie进行取之&#xff0c;项目进行交互时会对前端http请求携带的cookies进行解析操作&#xff0c;但在自测调试对过程中出现账户的授权失效的报错问题。 二、问题排查 用arthas进行代码方…

React16源码: React中event事件监听绑定的源码实现

event事件监听 1 &#xff09;概述 在 react-dom 代码初始化的时候&#xff0c;去注入了平台相关的事件插件接下去在react的更新过程绑定了事件的操作&#xff0c;在执行到 completeWork 的时候对于 HostComponent 会一开始就先去执行了 finalizeInitialChildren 这个方法位置…

鸿蒙应用/元服务开发-窗口(Stage模型)设置悬浮窗

一、设置悬浮窗说明 悬浮窗可以在已有的任务基础上&#xff0c;创建一个始终在前台显示的窗口。即使创建悬浮窗的任务退至后台&#xff0c;悬浮窗仍然可以在前台显示。通常悬浮窗位于所有应用窗口之上&#xff1b;开发者可以创建悬浮窗&#xff0c;并对悬浮窗进行属性设置等操…

使用网关过滤器,根据业务规则实现微服务动态路由

文章目录 业务场景拦截器实现Spring Cloud Gateway介绍 业务场景 我们服务使用Spring Cloud微服务架构&#xff0c;使用Spring Cloud Gateway 作为网关&#xff0c;使用 Spring Cloud OpenFeign 作为服务间通信方式作为网关&#xff0c;主要作用是鉴权与路由转发。大多数应用场…

3d网上虚拟现实展厅让汽车零部件厂商脱颖而出

在这个信息爆炸的时代&#xff0c;如何让自己的产品在众多竞争者中脱颖而出?让我们为您揭示一个秘密武器——汽车线上3D云展示软件。 想象一下&#xff0c;一辆外观炫酷、性能卓越的红色汽车&#xff0c;通过这款3D云展示软件&#xff0c;呈现在潜在客户的眼前。那流线型的车身…

Failed at the chromedriver@2.27.2 install script.

目录 【错误描述】Failed at the chromedriver2.27.2 install script. npm install报的错误 【解决方法】 删除node_modules文件夹npm install chromedriver --chromedriver_cdnurlhttp://cdn.npm.taobao.org/dist/chromedrivernpm install 【未解决】 下载该zip包运行这个&…

【npm】安装全局包,使用时提示:不是内部或外部命令,也不是可运行的程序或批处理文件

问题 如图&#xff0c;明明安装Vue是全局包&#xff0c;但是使用时却提示&#xff1a; 解决办法 使用以下命令任意一种命令查看全局包的配置路径 npm root -g 然后将此路径&#xff08;不包括node_modules&#xff09;添加到环境变量中去&#xff0c;这里注意&#xff0c;原…

JAVA SpringBoot中使用redis的事务

1、自定义redisConfig , 如果项目中要使用redis事务&#xff0c;最好将用事务和不用事务的redis分开。 Configuration public class RedisConfig {Resourceprivate RedisProperties redisProperties;Bean("redisTemplate")public RedisTemplate<String, Object>…

前端框架学习 Vue(3)vue生命周期,钩子函数,工程化开发脚手架CLI,组件化开发,组件分类

Vue 生命周期 和生命周期的四个阶段 Vue生命周期:一个Vue实例从创建 到 销毁 的整个过程 生命周期四个阶段 :(1)创建 (2)挂载 (3)更新 (4)销毁 Vue生命周期函数(钩子函数) Vue生命周期过程中,会自动运行一些函数,被称为[生命周期钩子] ->让开发者可以在[特定阶段] 运行自…

【云原生kubernetes系列】---亲和与反亲和

1、亲和和反亲和 node的亲和性和反亲和性pod的亲和性和反亲和性 1.1node的亲和和反亲和 1.1.1ndoeSelector&#xff08;node标签亲和&#xff09; #查看node的标签 rootk8s-master1:~# kubectl get nodes --show-labels #给node节点添加标签 rootk8s-master1:~# kubectl la…

用GOGS搭建GIT服务器

GOGS官网 Gogs: A painless self-hosted Git service 进入文件所在目录 cd /usr/local/develop 解压文件 tar -xvf gogs_0.13.0_linux_amd64.tar.gz 解压之后 进入gogs 目录 cd gogs 创建几个目录 userdata 存放用户数据 log文件存放进程日志 repositories 仓库根目…

19113133262(微信同号)【主题广范|见刊快】2024年新材料与应用化学国际学术会议(ICNMAC 2024)

【主题广范|见刊快】2024年新材料与应用化学国际学术会议(ICNMAC 2024) 2024 International Conference New Materials and Applied Chemistry(ICNMAC 2024) 一、【会议简介】 会议背景&#xff1a;随着科技的飞速发展&#xff0c;新材料与应用化学领域的研究成果日益丰富。为…

MySQL进阶45讲【12】为什么你的MySQL偶尔会卡一下

1 前言 平时的工作中&#xff0c;不知道大家有没有遇到过这样的场景&#xff0c;一条SQL语句&#xff0c;正常执行的时候特别快&#xff0c;但是有时也不知道怎么回事&#xff0c;它就会变得特别慢&#xff0c;并且这样的场景很难复现&#xff0c;它不只随机&#xff0c;而且持…

事件驱动架构:使用Flask实现MinIO事件通知Webhooks

MinIO的事件通知可能一开始看起来并不激动人心&#xff0c;但一旦掌握了它们的力量&#xff0c;它们就能照亮您存储桶内的动态。事件通知是一个全面、高效的对象存储系统中的关键组件。Webhooks是我个人最喜欢的工具&#xff0c;用于与MinIO集成。它们在事件的世界中就像一把瑞…

基于NSGA-II的深度迁移学习

深度迁移学习 迁移学习是一种机器学习技术&#xff0c;它允许一个预训练的模型被用作起点&#xff0c;在此基础上进行微调以适应新的任务或数据。其核心思想是利用从一个任务中学到的知识来帮助解决另一个相关的任务&#xff0c;即使这两个任务的数据分布不完全相同。这种方法…

靶机实战bwapp亲测xxe漏洞攻击及自动化XXE注射工具分析利用

靶机实战bwapp亲测xxe漏洞攻击及自动化XXE注射工具分析利用。 1|0介绍 xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目录遍历等.首先存在漏洞的web服务一定是存在xml传输数据的,可以在http头的content-type中查…