网站建设 前沿文章,外贸网站建设预算,招工信息发布平台,襄樊大型网站建设我们用rust开发的新版产品刚刚交付#xff0c;已经在海上安装测试完毕并顺利投产。终于松了口气#xff0c;同时也有时间和精力来做个全面的总结了。
这个产品#xff0c;目前差不多有三版#xff1a;
第一个版本是用crt-thread写的#xff0c;投产后出了一个内存泄露的…我们用rust开发的新版产品刚刚交付已经在海上安装测试完毕并顺利投产。终于松了口气同时也有时间和精力来做个全面的总结了。
这个产品目前差不多有三版
第一个版本是用crt-thread写的投产后出了一个内存泄露的bug由于我们的产品是安装到海上bug修复了也很难更新到产品上最后穷尽洪荒之力才找出对策进行了处置【不是排除】但现在依然象个定时炸弹一样悬在那。导致我对c失去信心最终下定决心换用rust第二个是用rust写的demo版本是基于RTIC框架写的。后因认为RTIC框架的限制比较大在写完主体功能后就废弃了第三个版本就是基于Embassy框架写的这一刚交付的版本
ps海上的情况太过复杂很多情况是我们现在的测试环境无法完全模拟的
本文即是基于笔者开发这三个版本的经验对rust嵌入式的开发所做的一个阶段性的总结。
开发门槛高 vs 现场智能化
就嵌入式来说rustEmbassy vs crt-thread的门槛是两个级别。
我是java和python的系统工程师开发第一个版本时就没用过c也没开发过嵌入式但花了一个月的时间第一个版本就写完了。
开发第三个版本时有了第一个版本的所有设备功能的开发经验有第二个版本的rust尝试但总的开发时间是从年后到5月下旬合到三个月了。
当然这里面主要的原因有两个
1、rust在嵌入式方面的生态没有c这么成熟有rt-thread这样的RTOS。虽然Embassy也比较成熟了但它不是一个完整的RTOS需要花大量的精力来开发一些较为底层的功能部件如之前介绍过的数据锁rust嵌入式开发之基于await构造应用级临界区。
当然如果只是如多数嵌入式的应用场景那样的话用RTIC框架完全可以rust嵌入式开发之RTICvsEmbassy那就简单很多了。但如我上面那篇文章所述RTIC框架能力有限起码对我司来说的是不够的
我们需要连接大量各厂家的设备串口之多以至于只能用10串口的STM32F403VG每种设备的协作机制完全不同所以就需要强大的异步协作能力RTIC就没有提供异步支持海上工程的特殊性决定了我们必须提供多种的错误恢复手段RTIC太弱
2、除了第一版中通常的现场操控能力之外在新版中我还开发了额外的应用能力如命令行这相当于在做RTOS中的shell了所以本质上还是rust嵌入式的生态还不够成熟的问题。
第一个版本是以在服务器上抄收到现场数据为完工标志但海上施工非常困难出海时一切正常突然瓢泼大雨的再正常不过了所以有必要提供现场的检查手段因此需要提供命令行功能。
其它还有debug、对象锁之类。
这也是我坚持认为随着MCU的资源越来越丰富嵌入式编程必然会走向复杂化、应用化的原因为了在竞争中获胜现场器件越来越智能化是必要的、必须的趋势
如我们现在就在考虑海上碰撞的预警、检测与证据固定已经在进行功能方面的论证。
也正是基于这个判断我才会坚定的抛弃c而拥抱rust。
概要之如果只是瞄准目前通常的嵌入式应用场景固定功能的现场操控。其实没必要用rust嵌入式编程【rustRTIC功能有限又自带rust的高门槛完全属于自找麻烦】门槛太高、成本也高出很多开发周期【尤其是产品成型的第一个版本的开发周期】太长可能会导致产品验证出现问题。
但是如果希望提高竞争水准、抬升行业准入门槛并将其中一个发力点落在现场感知、反应的智能化能力上我认为除非有极深的积累否则rust嵌入式自然拥有相当强的竞争力毕竟c太古老了不太适合快速低成本开发高可靠、高价值的应用。
对冲rust的高门槛
rust门槛高、心智负担重这是公认的rust的缺点。但就嵌入式而言这个缺点其实是不存在的。
原因非常简单嵌入式再如何复杂现在也远比后台应用简单的多所以完全可以采取措施来对冲rust的高门槛
1、用静态变量互斥访问来对冲rust的生命周期、借用难
对rust的生命周期、借用作为初学者的我也很头疼而我的解决办法非常粗暴
嵌入式的应用场景简单所以我直接把主要功能所需要的数据静态化、然后进行包裹、再用互斥锁进行保护这样一来所有的操作接口都是static self。
这就完全不再需要考虑生命周期和借用的问题了编程难度直线下降编译器一声都不敢吱:)
这个方法在上线后轻松抗住了一天40万条数据的采集压力而且经过计算还远没到设备极限大家可以放心大胆的用:)
2、用资源的高耗费来对冲编程的复杂度
既然现在MCU的资源极大的丰富了堆资源就好绕开死磕技术难度的坑就是了。
就如我们的串口读取底层申请了内存上层应用什么时候用完、需要进行释放是不清楚的而且串口读取到的数据还可能流经多种功能模块比如用蓝牙模块以modbus协议读取设备数据就需要流经串口模块、蓝牙模块、modbus模块、应用模块。这对内存管理就带了很大的压力。
所以我同样是用简单粗暴的方法来应对每层自己申请自己释放要提交给上层的就做一次内存copy。
这样过一层就做一次内存copy的资源耗费显然太过巨大但这样简单啊硬怼资源就很容易实现反正内存copy那点开销相比现在的MCU和嵌入式场景实在不值一提。
这个以资源开销来换简化编程、消弭bug的方法在我们多个串口、多种设备管控一天40多万条数据的采集、海上无线传输的压力下工作良好
一句话在目前的情况下rust嵌入式编程不需要考虑优化、不需要担心浪费堆资源是最应优先考虑的方案。
在我来看对一个产品来说有两个指标是决定性的
关键需求的满足度产品的稳定性
前者是客户花钱的理由rust的现代性和良好生态是支撑我们依托智能化产品来提升核心竞争力的利器自然就是选择rust的最大理由后者是客户付钱的理由rust写出的程序天然自带的健壮性和可靠性就是选择rust的第二大理由。
当然rust在嵌入式方面的生态还有所不足但这只是时间问题总要给新生儿成长的时间。
谁都有缺点弥补缺点就需要成本。借用工程技术手段和高资源开销来弥补rust的缺点就是我们目前必要的成本。
现在看下来这些成本完全可以接受。
rust嵌入式的不足
生态、生态、生态。这必须是rust嵌入式的最大不足。尤其是在芯片国产替代的当下国产芯片在rust嵌入式方面的投入基本可以忽略。
如我们第一版用的就是国产的GD32但在看好rust嵌入式的前景之后由于芯片厂商等在基础设施方面的投入不足最后只好又选了STM32。
当然我相信国内的芯片厂家既然提供了这么强大的MCU最终一定是需要软件来消耗掉这些资源的我们的新版本已经消耗掉了384K的Flash还有很大空间值得挖掘:)
而这要靠c肯定不现实最终还是要在rust上发力的。只是需要提提速啊:(
rust嵌入式在生态方面的最大不足对我们来说自然就是缺乏一个如国产的rt-thread这样的国产RTOS。由于缺了不少必要的基础部件就需要自己来开发这相当于提升了开发门槛和成本。
rust嵌入式的第二个不足就是no_std和std的隔离。这就导致rust的良好生态在嵌入式方面被大幅度的削弱了。
比如我在命令行中原本要实现参数的核验但rust工业标准的正则表达式crate在no_std下就用不了只好用了可以支持no_std的regex-automata但用下来总感觉有些问题由于时间太紧张了实在无法全面测试最后干脆就先取消了命令行的参数核验能力。
就目前来说no_std的问题还影响不大但随着现场智能化诉求的提升这个问题势必会带来越来越大的限制。
第三个不足应该是rust的不足就是IDE在编辑界面无法自动扩展宏。
我选择rust的一个重要理由就是相比c中的宏rust的过程宏异常的强大完全可以媲美java中的反射和python中的修饰符关键还是零开销rust嵌入式之用类函数宏简写状态机定义。
在java和python中我都自己实现了ORM、状态机等所以我深知反射技术是各种框架的基础对现代软件工程和编程技术具有无与伦比的巨大意义当然还有所要花费的巨大开销。
在rust中我同样用过程宏实现了状态机、命令行、debug、控制台、串口/pwm等接口操作的自动扩写、扩展对象锁、命令-期望等等。
对rust的过程宏我实在是太满意了。
但是宏用得太多某些利用宏扩写出来的技术细节我自己也就记不清楚了当需要探究某个技术细节的时候IDE竟然不给自动展开所扩写的代码还需要手动执行命令来展开宏然后去另外的文件中来查看非常低效。
这个不足在排错的时候尤其讨厌
结语
虽然rust嵌入式有着种种的不足但我依然相信rust在嵌入式领域前程远大。