Rust 闯入嵌入式世界:为什么 C 语言不再是王者

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:“硬件”时代正在改变语言

\n\n

如果你曾经用 C 语言为微控制器编写过固件,你会知道那种感觉。那种在调试三个小时后发现程序挂死的感觉——指针飞到了天上,而看门狗却无能为力。嵌入式开发多年来一直是 C 语言和汇编语言的领地。但在过去几年里,一位新玩家登上了舞台——Rust。它不仅仅是“另一种语言”,更是嵌入式系统的一次真正突破。

\n\n

在本文中,我们将探讨为什么 Rust 嵌入式开发 不是炒作,而是一种必需。我们将查看真实的代码示例,与 C 语言进行比较,并了解如何入门。如果你正在为 STM32、ESP32 或 ARM Cortex-M 编写代码,那么你来对地方了。

\n\n

为什么 Rust 对于嵌入式来说是理想的结合

\n\n

嵌入式系统是一个充满限制的世界。内存少,没有操作系统,没有堆,没有异常。编译时错误是好的,运行时错误是坏的。Rust 正是为这些条件而设计的。

\n\n

无垃圾回收的内存安全性

\n\n

C 语言嵌入式开发者的主要痛点包括 释放后使用、双重释放内存和缓冲区溢出。Rust 在类型层面解决了这些问题。所有权和借用模型即使在 no_std 环境中也能工作——无需分配器、无需操作系统、无需垃圾回收器。

\n\n

想象一下,你正在为 LED 编写一个驱动程序。在 C 语言中,你会这样写:

\n\n
// C 代码\nvoid led_on(GPIO_TypeDef *gpio, uint16_t pin) {\n    gpio->BSRR = pin;\n}
\n\n

一切正常,直到有人传入一个空指针。Rust 不会让你这样做:

\n\n
// Rust 代码\nfn led_on(gpio: &mut GpioRegisters, pin: u16) {\n    gpio.bsrr.write(|w| w.bits(pin.into()));\n}
\n\n

这里的 &mut GpioRegisters 保证了引用是有效的,并且对寄存器的访问是独占的。编译器根本不会让危险代码通过。

\n\n

零成本抽象

\n\n

嵌入式开发者最大的恐惧之一是高级语言会“吞噬”处理器时钟周期。Rust 遵循 零成本抽象 原则:你只为使用的东西付费。迭代器、闭包、trait——所有这些都能编译成与手动展开的 C 语言循环一样高效的机器码。

\n\n

此外,在 Rust 的嵌入式生态系统中,有些 crate 可以在单指令级别工作。例如,cortex-m-rt 生成中断向量和启动代码,没有一条多余的指令。

\n\n

实际项目:用 Rust 让 LED 闪烁 (STM32)

\n\n

让我们为 STM32F3Discovery 板编写一个简单的程序。我们将使用 cortex-m-quickstart 和来自 embedded rust 社区的 HAL。

\n\n

步骤 1:项目设置

\n\n

确保你已经安装了 Rust 和 ARM Cortex-M 工具链:

\n\n
rustup target add thumbv7em-none-eabihf\ncargo install cargo-generate
\n\n

根据模板创建项目:

\n\n
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
\n\n

步骤 2:编写代码

\n\n

打开 src/main.rs 并编写经典的 Blinky 程序:

\n\n
#![no_std]\n#![no_main]\n\nuse cortex_m_rt::entry;\nuse panic_halt as _;\nuse stm32f3xx_hal::{pac, prelude::*};\n\n#[entry]\nfn main() -> ! {\n    // 获取外设访问权限\n    let dp = pac::Peripherals::take().unwrap();\n    let mut rcc = dp.RCC.constrain();\n    let mut gpioe = dp.GPIOE.split(&mut rcc.ahb);\n\n    // 将 PE9 引脚配置为输出(LED LD1)\n    let mut led = gpioe\n        .pe9\n        .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);\n\n    loop {\n        led.set_high().unwrap();\n        cortex_m::asm::delay(8_000_000);\n        led.set_low().unwrap();\n        cortex_m::asm::delay(8_000_000);\n    }\n}
\n\n

这里发生了什么?

\n
    \n
  • #![no_std] — 我们没

博客

书籍推荐