为什么 Rust 正在征服嵌入式开发

在嵌入式系统开发的历史中,C 语言几乎是唯一的选择。但 C 的手动内存管理和缺乏类型安全保证,导致嵌入式软件中内存泄漏、缓冲区溢出、空指针等 Bug 频发。Rust 凭借零成本抽象、所有权系统和编译期内存安全检查,正在颠覆嵌入式开发的格局。2024 年,Linux 内核正式接纳 Rust 作为第二语言,标志着 Rust 在系统级编程中的正式崛起。

一、Rust 嵌入式开发生态

1.1 核心层 Embedded HAL

Embedded HAL(Hardware Abstraction Layer)是 Rust 嵌入式生态的基石,定义了硬件接口的统一抽象:

// Embedded HAL 核心 trait
pub trait OutputPin {
    fn set_high(&mut self) -> Result<(), Self::Error>;
    fn set_low(&mut self) -> Result<(), Self::Error>;
}

pub trait InputPin {
    fn is_high(&self) -> Result;
    fn is_low(&self) ->(R) -> Result;
}

pub trait Spi {
    fn transfer(&mut self, words: &mut [u8]) -> Result<(), Self::Error>;
}

pub trait I2c {
    fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error>;
    fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error>;
}

1.2 PAC 层(Peripheral Access Crate)

PAC 提供了对 MCU 寄存器的类型安全访问,通常由 svd2rust 工具从 SVD 文件自动生成:

// STM32F4xx PAC 示例 - 控制 GPIO
let dp = stm32f4xx::Peripherals::take().unwrap();
dp.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
dp.GPIOA.moder.modify(|_, w| w.moder5().output());
dp.GPIOA.odr.modify(|_, w| w.odr5().set_bit());  // LED ON

1.3 HAL Crate

HAL 层在 PAC 之上构建,提供高层且符合人体工程学的 API,屏蔽寄存器操作细节:

use stm32f4xx_hal::{pac, prelude::*, timer::Timer};

let dp = pac::Peripherals::take().unwrap();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(168.MHz()).freeze();
let gpioa = dp.GPIOA.split();
let mut led = gpioa.pa5.into_push_pull_output();

// 优雅的 blink 实现
loop {
    led.set_high();
    Timer::syst(cortex_m::Peripheral::take().unwrap().SYST, &clocks)
        .start(1.Hz()).wait();
    led.set_low();
    Timer::syst(...).start(1.Hz()).wait();
}

二、RTIC 框架:Rust 实时中断驱动并发

RTIC(Real-Time Interrupt-driven Concurrency)是 Rust 嵌入式生态中最强大的实时框架,提供:零开销任务调度、优先级继承、无锁消息传递和编译期资源共享。

#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true)]
mod app {
    use rtic::Monotonic;
    
    // 共享资源自动加锁
    #[shared]
    struct Shared {
        counter: u32,
        buffer: [u8; 64],
    }
    
    // 本地资源拥有互斥访问权
    #[local]
    struct Local {
        led: PA5,
    }
    
    // 初始化函数 - 返回资源所有权
    #[init]
    fn init(cx: init::Context) -> (Shared, Local) {
        let dp = cx.device;
        // ... 硬件初始化 ...
        // 启动周期性任务
        tick::spawn().ok();
        (Shared { counter: 0, buffer: [0; 64] }, Local { led })
    }
    
    // 定时器中断 - 周期性任务,每10ms触发
    #[task(priority = 1)]
    fn tick(cx: tick::Context) {
        tick::spawn_after(10.millis()).ok();  // 重新调度
    }
    
    // UART 中断 - 异步串口处理
    #[task(binds = USART1, priority = 2, shared = [buffer])]
    fn uart_rx(cx: uart_rx::Context) {
        let byte = read_uart_byte();
        cx.shared.buffer.lock(|buf| {
            buf.push(byte);
        });
        process_msg::spawn().ok();
    }
    
    // 异步任务 - 非中断上下文执行
    #[task(priority = 3, shared = [counter, buffer])]
    async fn process_msg(cx: process_msg::Context) {
        cx.shared.counter.lock(|c| *c += 1);
        cx.shared.buffer.lock(|buf| {
            // 处理缓冲区数据
        });
    }
}

三、嵌入式 Rust 的 async/await

Rust 的 async/await 在嵌入式领域同样强大,配合 embassy 框架可以创建高效的异步嵌入式应用:

// Embassy 异步嵌入式框架
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_time::{Duration, Timer};

#[embassy_executor::main]
async fn main(spawner: Spawner) {
    let p = embassy_stm32::init(Default::default());
    let mut led = Output::new(p.PB14, Level::High, Speed::Low);
    
    // 异步任务,非阻塞执行
    spawner.spawn(blink_task(led)).ok();
    spawner.spawn(uart_task(p.USART1)).ok();
}

#[embassy_executor::task]
async fn blink_task(mut led: Output<'static, PB14>) {
    loop {
        led.set_high();
        Timer::after(Duration::from_millis(500)).await;
        led.set_low();
        Timer::after(Duration::from_millis(500)).await;
    }
}

四、对比:C vs Rust 嵌入式开发

维度C 语言Rust
内存安全手动管理,易出错所有权系统编译期保证
并发安全数据竞争难以避免Send/Sync trait 编译期防止竞态
抽象能力宏,不类型安全traits + generics,零成本抽象
并发编程FreeRTOS任务,手动同步RTIC/embassy,编译期资源管理
调试体验printf + JTAGprobe-rs + defmt,结构化日志
包管理手动维护MakefileCargo生态系统,只需 Cargo.toml
学习曲线相对平缓陡峭(所有权、生命周期)

五、总结

Rust 在嵌入式领域的崛起并非偶然。它解决了 C/C++ 几十年来一直存在的内存安全问题,同时提供现代编程语言的全部能力。RTIC 和 embassy 等框架展示了 Rust 如何在资源受限的 MCU 上实现高级 RTOS 语义。尽管学习曲线陡峭,但对于追求高性能、高可靠性的嵌入式系统,Rust 是未来十年的最佳选择。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部