Rust + 嵌入式:强力开发组合

news2024/10/7 14:28:27

Rust 的由来 

Rust 编程语言的灵感诞生于一次意外。2006年,当 Graydon Hoare 回到位于温哥华的公寓时,发现电梯又因为软件崩溃出了故障。住在 21 楼的他无奈爬楼时,不禁心想,“我们搞计算机的,怎么连个能正常运行的电梯都做不出来!” 这次经历后,Hoare 开始着手设计一门新的编程语言,他希望这门语言可以在不引入内存错误的同时,产出更短、更快的代码 [1] 。 

您可以前往 [2] 和 [3],进一步了解 Rust 的发展。 

时光流转,已经过去了 18 年,Rust 现已成为全球炙手可热的新兴编程语言,每年都吸引着越来越多的关注。2020 年第一季度时,约有 60 万开发者使用 Rust 进行开发,到了 2022 年第一季度,使用人数已增长至 220 万 [4]。著名的科技巨头,如 Mozilla、Dropbox、Cloudflare、Discord、Facebook(Meta)、Microsoft 等,都在代码库中广泛运用 Rust 语言。 

  

根据 2021 年开发者调查统计,Rust 语言已连续六年位列“开发者最爱的编程语言”榜首。  

应用于嵌入式开发的编程语言 

比起 Web 开发和桌面开发,嵌入式开发受到的关注较为有限,背后的原因或许涉及以下几个方面: 

  • 硬件限制:嵌入式系统有限的硬件资源(如性能和内存)增大了软件开发的难度。 
  • 市场限制:相对于 Web 和桌面应用,嵌入式市场较小,嵌入式编程开发者所获得的经济回报相对较低。 
  • 底层专业知识要求:嵌入式开发要求开发者具备对具体硬件和底层编程语言的专业知识。 
  • 开发周期较长:相对于为 Web 和桌面应用开发软件,为嵌入式系统开发软件需要对代码进行测试和优化,以满足特定硬件要求,耗费时间更长。 
  • 底层编程语言限制:汇编语言和 C 语言等底层编程语言为开发者提供的抽象较少,而直接访问硬件资源和内存可能会引入内存错误。 

上述的几个方面足以让我们感受到嵌入式开发的独特之处,也解释了为什么对于年轻程序员来说,嵌入式开发并不像 Web 开发那么受欢迎。使用 Python、JavaScript 或 C# 等常见的现代编程语言进行开发时,开发者并不需要计算每个处理器周期或内存中使用的每个千字节,这样虽然便利但极大的变化,会导致开发者在初次接触嵌入式开发时很难适应,不论是初学者还是经验丰富的 Web/桌面/移动开发者,都极具挑战性。因此,有必要设计一门专用于嵌入式开发的现代编程语言。 


为什么选择 Rust? 

Rust 是一门发展时间较短的现代编程语言,它专注于内存和线程安全,旨在开发可靠且安全的软件。此外,Rust 对并发和并行的支持可以实现对资源的高效利用,这一点在嵌入式开发中尤为重要。Rust 的应用逐渐广泛,其生态系统也逐渐成型,越来越多追求高效与安全性的开发者都开始将其作为理想的开发语言。这些都是在嵌入式开发或是注重安全性和可靠性的项目中选择 Rust 的主要原因。 

Rust 的优势(与 C 和 C++ 相比) 

  • 内存安全: Rust 通过使用所有权和借用的概念,有效地消除了空指针解引用和缓冲区溢出等内存相关的错误。也就是说,通过所有权和借用系统,Rust 可以保证编译时的内存安全。因为在嵌入式开发中,由于内存和资源的限制,检测和解决内存相关错误存在困难,所以Rust 提供的内存安全保证尤为重要。 
  • 并发安全:Rust 完美支持零成本抽象、并发编程和多线程,通过内置 async/await 语法和强大的类型系统,有效地消除数据竞争等常见的并发错误。该特性不仅适用于嵌入式系统,各个领域的开发者都可以借此轻松写出安全高效的并发代码。 
  • 高性能:Rust 的性能与 C 和 C++ 旗鼓相当,Rust 还能提供更可靠的内存安全和并发安全。 
  • 代码可读性:相较于 C 和 C++, Rust 的语法设计更注重代码可读性和降低错误率,它引入了模式匹配、类型推导和函数式编程结构等特性,使代码的编写与维护更为便捷,尤其适用于较为复杂的大型项目。 
  • 日益壮大的生态系统:Rust 的生态系统包括各种库(crates)、工具和资源,可供包括嵌入式开发在内的各开发领域使用。随着生态系统的不断发展壮大,开发者可以轻松使用 Rust 搭建工程,并找到所需的特定支持和资源。 
  • 包管理器和构建系统:Rust 内置 Cargo 包管理器,用于自动化构建、测试和发布流程,同时也能创建新项目并管理依赖项。 

Rust 的劣势(与 C 和 C++ 相比) 

虽然优势明显,但 Rust 并非一门完美的语言,与其他编程语言(包括但不限于 C 和 C++)相比,它也存在一些不足之处。 

  • 学习曲线陡峭:Rust 的学习曲线比起 C 等多数编程语言更为陡峭。开发者们需要花费更多的时间和精力来理解它的独特特性,如上文所提到的所有权、借用系统等。这对初次接触 Rust 的开发者来说,可能会是一种挑战。 
  • 编译时间长:和其他语言比起来,Rust 拥有高级类型系统和借用检查器,需要花费更长的编译时间,这一点在大型工程中尤为明显。 
  • 工具支持不足:尽管 Rust 的生态系统正在迅速扩展,但 C 和 C++ 等更加成熟的编程语言已经存在了几十年,积累了大量的代码库。相较之下,Rust 的工具支持还是略显不足,在特定项目中找到并使用合适工具的难度相较略高。 
  • 底层控制不足:相较于 C 和 C++,Rust 的安全特性可能会限制其底层控制能力。尽管 Rust 仍支持特定底层优化或是直接与硬件交互,但难度略高。 
  • 社区支持不足:与 C 和 C++ 等更为成熟的编程语言相比,Rust 仍然是一门相对较新的编程语言。它的社区规模较小,贡献代码的开发者和可供使用的资源、库和工具也相对较少。 

综上所述,与 C  和 C++ 等传统的嵌入式开发语言相比,Rust 在内存安全、并发支持、性能、代码可读性以及生态系统等方面都具有诸多优势。因此,在嵌入式开发中,尤其是在注重安全、可靠性和稳定性的项目中,使用 Rust 的开发者数量稳步上升。但相较于 C 和 C++,Rust 的不足之处往往与其作为一门相对较新的语言以及独特的特性有关。不过,Rust 的优势已足以使其成为某些项目的不二之选。 


如何运行 Rust 代码? 

根据不同的环境和应用需求,可以通过多种方式运行基于 Rust 的固件,此类固件通常支持在宿主环境或裸机环境下运行。接下来将详细介绍这两种环境。 

什么是宿主环境? 

与普通的 PC 环境类似,Rust 的宿主环境提供了一个可供构建 Rust 标准库 (std) 的操作系统。标准库(std)是包含在各个 Rust 安装程序中的模块和类型的集合,支持多种用于构建 Rust 程序的功能,包括数据结构、配网、互斥锁和其他同步原语、输入/输出等。 

在宿主环境 (简称为 std) 下,开发者可以使用基于 C 的 ESP-IDF 开发框架中的功能。ESP-IDF 提供的 newlib 环境支持开发者在该框架之上构建 Rust 标准库。还可以将 ESP-IDF 作为操作系统来构建 Rust 应用程序。因此除上述列出的所有标准库功能外,还可以使用 ESP-IDF API 中实现基于 C 的功能。 

以下为在 ESP-IDF (FreeRTOS) 上运行的 blinky 示例(更多示例存放在 esp-idf-hal 仓库中): 

// 导入示例所需外设 
use esp_idf_hal::delay::FreeRtos; 
use esp_idf_hal::gpio::*; 
use esp_idf_hal::peripherals::Peripherals; 
 
// Start of our main function i.e entry point of our example 
fn main() -> anyhow::Result<()> { 
    // 应用所需 ESP-IDF 补丁 
    esp_idf_sys::link_patches(); 
 
    // 初始化所有所需外设 
    let peripherals = Peripherals::take().unwrap(); 
 
    // 创建一个 led 对象,将其设置为 GPIO4 引脚的输出模式 
    let mut led = PinDriver::output(peripherals.pins.gpio4)?; 
 
    // 设置一个每 500 毫秒即切换 LED 开/关状态的无限循环 
    loop { 
        led.set_high()?; 
        // 进入睡眠模式,以防触发看门狗 
        FreeRtos::delay_ms(1000); 
 
        led.set_low()?; 
        FreeRtos::delay_ms(1000); 
    } 
} 

适用宿主环境的情况 

  • 实现多项功能:如需在嵌入式系统实现大量功能,比如支持网络协议、文件输入/输出或者引入复杂的数据结构,可以考虑使用宿主环境,该环境下的标准库提供丰富的功能,帮助您快速高效地构建复杂的应用程序。 
  • 要求可移植性:标准库提供了一套支持在不同平台和架构上使用的标准化 API,方便编写具有可移植性和重用性的代码。 
  • 进行快速开发:标准库提供了丰富的功能集,可以快速高效地构建应用程序,无需担心底层细节。 

什么是裸机环境?  

裸机环境是指没有可供使用的操作系统环境。当编译的 Rust 程序拥有 no_std 属性时,该程序无权访问上述 std 章节中提到的某些特定功能。尽管仍支持使用配网或引入复杂数据结构等功能,但实现方式将会更加复杂。 no_std 程序依赖于 Rust 所有环境中可用的核心语言特性,包括数据类型、控制结构和底层内存管理。此环境在嵌入式编程中非常实用,特别适用于内存资源有限、需要对硬件进行低级别控制的场景。 

以下为在裸机环境上(不借助操作系统)运行的 blinky 示例(更多示例存放在 esp-hal 仓库中): 

#![no_std] 
#![no_main] 
 
// 导入示例所需外设  
use esp32c3_hal::{ 
    clock::ClockControl, 
    gpio::IO, 
    peripherals::Peripherals, 
    prelude::*, 
    timer::TimerGroup, 
    Delay, 
    Rtc, 
}; 
use esp_backtrace as _; 
 
// 设置程序执行的起始点 
// 因为这是一个 `no_std` 程序,不存在主函数 
#[entry] 
fn main() -> ! { 
    // 初始化所有所需外设 
    let peripherals = Peripherals::take(); 
    let mut system = peripherals.SYSTEM.split(); 
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 
 
    // 禁用看门狗定时器。对于 ESP32-C3 来说,包括 Super WDT、 
    // RTC WDT 和 TIMG WDT 
    let mut rtc = Rtc::new(peripherals.RTC_CNTL); 
    let timer_group0 = TimerGroup::new( 
        peripherals.TIMG0, 
        &clocks, 
        &mut system.peripheral_clock_control, 
    ); 
    let mut wdt0 = timer_group0.wdt; 
    let timer_group1 = TimerGroup::new( 
        peripherals.TIMG1, 
        &clocks, 
        &mut system.peripheral_clock_control, 
    ); 
    let mut wdt1 = timer_group1.wdt; 
 
    rtc.swd.disable(); 
    rtc.rwdt.disable(); 
    wdt0.disable(); 
    wdt1.disable(); 
 
    // 将 GPIO4 设置为输出,并将其初始状态设置为高电平 

    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); 
    // 创建一个 led 对象,将其设置为 GPIO4 引脚的输出模式 
    let mut led = io.pins.gpio5.into_push_pull_output(); 
 
    // 启动 LED 
    led.set_high().unwrap(); 
 
    // 初始化延迟外设,并在循环中 
    // 使用它来切换 LED 的状态 

    let mut delay = Delay::new(&clocks); 
 
    // 设置一个每 500 毫秒即切换 LED 开/关状态的无限循环 
    loop { 
        led.toggle().unwrap(); 
        delay.delay_ms(500u32); 
    } 
} 

适用裸机环境的情况 

  • 减少内存占用:如果嵌入式系统资源有限,需要占用较小的内存,可以考虑使用裸机环境,因为 std 会显著增加最终二进制文件的大小和编译时间。 
  • 实现直接硬件控制:如果需要在嵌入式系统中实现直接硬件控制,例如实现底层设备驱动程序或访问特定硬件功能,可以考虑使用裸机环境,因为 std 的抽象层会提高直接与硬件进行交互的难度。 
  • 涉及实时约束或对时间敏感的应用程序:如果嵌入式系统要求实时性能或低延迟响应时间,可以考虑使用裸机环境,因为 std 可能导致意外延迟和开销。 
  • 自定义需求:裸机环境支持更多自定义配置,同时也能实现对应用程序行为的精细控制,非常适用于特定或非标准环境。 

小结:要不要从 C 转到 Rust 呢? 

如果您打算新开发一个对内存安全或是并发性有要求的工程或任务,可以考虑从 C 转到 Rust。但对于已经用 C 开发完毕且正常运行的工程,就没有为 Rust 而重新编写并测试整个代码库的必要了。使用 Rust 代码调用 C 函数的难度并不大,因此对于这种工程,可以考虑保留已有的 C 代码,并使用 Rust 编写新添加的功能以及模块。此外,也可以尝试使用 Rust 编写 ESP-IDF 组件。总而言之,是否要从 C 转向 Rust 需根据具体的需求进行权衡。 


参考链接 

  1. How Rust went from a side project to the world’s most-loved programming language | MIT Technology Review
  2. Announcing Rust 1.0 | Rust Blog (rust-lang.org)
  3. 4 years of Rust | Rust Blog (rust-lang.org)
  4. The state of the Rust market in 2023 (yalantis.com)
  5. Stack Overflow Developer Survey 2021
  6. https://docs.rust-embedded.org/book/intro/no-std.html#hosted-environments

 

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

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

相关文章

接口测试要会什么技能?测试老鸟总结,从接口到接口自动化全面盲扫...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

YOLOv5改进:引入DenseNet思想打造密集连接模块,彻底提升目标检测性能

目录 一、密集连接模块的介绍1、密集连接的概念2、密集连接与残差连接的对比3、DenseNet的结构 二、 YOLOv5中引入密集连接模块的原因1、密集连接模块对于目标检测的优势2、密集连接模块对目标检测性能的影响 三、 YOLOv5中密集连接模块的具体实现1、使用DenseNet的基本单元Den…

怎样才能尽快从开发岗转到产品经理岗位?

越来越多的开发同学随着工作年限的增长都会产生类似的想法。 当然&#xff0c;背后的原因也是多种多样&#xff0c;像薪资上的限制、行业前景的担忧等等&#xff0c;很多同学则踌躇在原地不敢转产品岗位&#xff0c;而有的同学则是通过各种不同方式顺利转岗到产品经理岗位&…

树莓派从源码构建安装Git最新版

1、查看Git版本 首先我们通过SSH客户端连接树莓派,在树莓派中通过查看 Git 版本信息&#xff0c;我们只能看到最高版本显示为 2.30.2&#xff0c;并且通过apt安装也无法将Git更新到最新版。 git --version sudo apt upgrade git那么我们只能通过从源代码来构建安装Git了&…

单片机复习题第二章

1.在AT89S52单片机中&#xff0c;如果采用6MHz晶振&#xff0c;一个机器周期为2us。 时钟周期的振荡频率为fosc&#xff0c;则时钟周期T1/fosc。 一个机器周期包括12个时钟周期。 2.内部RAM中&#xff0c;位地址为40H&#xff0c;88H的位&#xff0c;该位所在字节的字节地址分别…

scrollIntoView 的使用

描述 将调用此方法的元素滚动到浏览器窗口的可见区域。 scrollIntoView 官方文档 用法 element.scrollIntoView() 用法同 element.scrollIntoView(true) element.scrollIntoView(alignToTop) true 表示 element 元素顶部与可见区域的顶部对齐&#xff0c;默认值false 表示 el…

基于html+css的图展示56

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Packet Tracer - 第 2 层 VLAN 安全

Packet Tracer - 第 2 层 VLAN 安全 目标 在 SW-1 和 SW-2 之间连接新的冗余链路。 启用中继&#xff0c;并在 SW-1 和 SW-2 之间的新中继链路上 配置安全。 创建新的管理 VLAN (VLAN 20) 并将管理 PC 连接到 该 VLAN。 实施 ACL 以阻…

Java学习-GUI编程-JFrame窗口

Java学习-GUI编程-JFrame窗口 public class TestJFrame {public void init(){JFrame jf new JFrame("这是一个JFream窗口");jf.setVisible(true);jf.setBounds(100,100,400,400);JLabel label new JLabel("这是一个label");label.setHorizontalAlignmen…

Linux之shell函数和正则表达式(八)

1、函数 1、函数概述 shell 中允许将一组命令集合成语句形成一段可用代码&#xff0c;这些代码块称为 shell 函数&#xff0c;给这段代码起个名字称为函数名&#xff0c;后续可以直接调用该段代码的功能 2、定义函数 函数名() {函数体&#xff08;一堆命令的集合&#xff0…

程序员的下一个风口

面对近一年的裁员潮&#xff0c;以及 GPT 出现带来的 AI 颠覆潮流&#xff0c;各种话题出现&#xff1a;「前端已死」、「后端已死」、「Copy/Paste 程序员将被 AI 取代」。程序员行业是否还有发展空间&#xff1f; 这一两年的就业机会是因为经济衰落周期内造成的&#xff0c;不…

pmp备考有哪些适合新手的学习资料?

在备考中&#xff0c;无论你是胸有成竹的学霸还是忐忑不安的学渣&#xff0c;强烈建议你是时候展现真正的技术了——临阵磨枪不快也光&#xff01;你准备好了吗&#xff1f;前方为大家准备了高能备考技巧和干货资料包&#xff0c;拿起热水杯&#xff0c;准备走起。 1.PMBOK知识…

怎样使用Web自动化测试减少手动劳动?以百度网站为例

从入门到精通&#xff01;企业级接口自动化测试实战&#xff0c;详细教学&#xff01;&#xff08;自学必备视频&#xff09; 目录 摘要 步骤1&#xff1a;安装和配置Selenium 步骤2&#xff1a;启动浏览器并访问百度网站 步骤3&#xff1a;关闭浏览器 总结 摘要 本指南将…

数据风险评估

通过数据风险评估定位敏感数据并分析其漏洞。根据文件的敏感度对文件进行分类&#xff0c;并确保为它们提供必要的保护。 发现、分析和保护敏感数据 查找所有个人数据根据敏感度对文件进行分类遵守 IT 法规分析文件和权限 查找所有个人数据 监控企业存储环境并接收有关敏感…

(CVE-2022-22965)Spring Framework 远程命令执行漏洞(vulfocus复现)

漏洞原理 该漏洞是SpringFramework数据绑定的一个漏洞&#xff0c;如果后台方法中接受的参数为非基础类型&#xff0c;Spring会根据前端传入的请求正文中的参数的key值来查询与其名称所对应的getter和setter方法&#xff0c;攻击者利用这一特性修改了Tomcat的一个用于日志记录…

java开发记录v2(引入jar,问题及解决)

引入本地jar包 在src同级目录下新建libs目录将jar包放入进去 在pom.xml中下加入以下代码 <dependencies><dependency><groupId>com.hikvision.ga</groupId><artifactId>artemis-http-client</artifactId><version>1.1.8</ver…

Acer非凡X14笔记本电脑蓝屏了怎么U盘重装系统?

Acer非凡X14笔记本电脑蓝屏了怎么U盘重装系统&#xff1f;有用户在使用Acer非凡X14笔记本电脑的时候&#xff0c;系统开机后出现了蓝屏的情况&#xff0c;导致自己的电脑无法正常的去进行使用。那么这个情况怎么去通过U盘重装系统的方法来恢复系统的使用呢&#xff1f;一起来看…

软考A计划-重点考点-专题十二(JAVA程序设计)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

数据中心列头柜监控在常熟某微模块中的应用

安科瑞 耿敏花 摘要&#xff1a;安科瑞精密配电系统是安科瑞针对数据中心集中监控要求提供的多回路监控装置&#xff0c;监控多回路电参量并可对各种故障进行告警。主要适用于各类列头柜、精密配电柜、电源分配柜、UPS输出柜等末端配电设备的监控。在阐述数据中心机房机柜配电…

Keepalived结合Nginx实现WEB高可用服务

前言 随着Nginx在国内的发展潮流&#xff0c;越来越多的互联网公司都在使用Nginx&#xff0c;Nginx高性能、稳定性成为IT人士青睐的HTTP和反向代理服务器。 Nginx负载均衡一般位于整个网站架构的最前端或者中间层&#xff0c;如果为最前端时单台Nginx会存在单点故障&#xff0…