第一章:Rust与嵌入式开发概述

各位同学,欢迎来到《Rust实战:嵌入式与WebAssembly应用开发》的第一课。

我是这门课的主讲,一个在嵌入式圈子里摸爬滚打了十几年的老工程师。说实话,我接触Rust的时间不算最早,但一用上就感觉——嗯,这语言就是为嵌入式量身定做的。今天咱们先聊聊基础,把Rust和嵌入式开发这盘棋的全局看清楚。

1.1 Rust语言特性:为什么它值得你花时间?

Rust是一门系统级编程语言。说白了,它想干两件事:一是像C/C++那样直接操作硬件,二是保证内存安全,不让程序动不动就崩。

我个人最看重的特性有三个:

  • 零成本抽象:你写的高级抽象,编译后不会产生额外开销。这在嵌入式里太重要了,每一字节的RAM、每一个CPU周期都得精打细算。
  • 所有权与借用:这是Rust的独门绝技。编译器在编译时就帮你检查内存使用,没有垃圾回收,也没有野指针。我在项目中遇到过好几次C语言的内存泄漏,排查起来真是头大。Rust从根源上杜绝了这类问题。
  • 无畏并发:Rust的类型系统能保证数据竞争在编译期就被发现。你想想看,多任务系统里最怕什么?就是两个任务同时改一个变量。Rust直接说:不行,你得加锁或者用消息传递。

核心要点:Rust不是一门“容易”的语言,但它是一门“正确”的语言。你花在编译器报错上的时间,将来会在调试器里加倍省回来。

1.2 嵌入式系统简介:我们到底在做什么?

嵌入式系统,就是那些藏在设备里的计算机。小到智能手环,大到汽车ECU,甚至卫星上的控制器,都是嵌入式系统。

它们有几个共同特点:

  • 资源受限:可能只有几KB的RAM,几十KB的Flash。你没法跑Linux,更别说Python了。
  • 实时性要求:比如电机控制,必须在几微秒内响应,慢了机器就废了。
  • 可靠性第一:医疗设备、航空航天,代码出bug是要出人命的。

我记得刚入行时,用C写一个I2C驱动,因为一个中断优先级没设对,导致数据偶尔错乱。查了整整三天,最后发现是编译器优化把某个volatile变量给优化掉了。这种坑,Rust基本不会让你踩。

1.3 Rust在嵌入式领域的优势:为什么选它?

咱们直接对比一下:

对比项 C/C++ Rust
内存安全 全靠程序员自觉 编译器强制保证
并发安全 容易出数据竞争 类型系统保证
零成本抽象 可以做到 原生支持
生态工具 成熟但分散 统一且现代
学习曲线 相对平缓 较陡,但值得

你可能会问:既然C用了这么多年,为什么还要换?

我的回答是:因为现代嵌入式系统越来越复杂。一个简单的蓝牙传感器,可能就要处理协议栈、加密、低功耗管理。用C写,你得自己管理每一块内存,自己处理每一个边界情况。Rust把这些都自动化了,让你能专注于业务逻辑。

个人经验:我曾经把一个用C写了三年的项目,用Rust重写了一遍。代码量减少了约30%,而且之前那些间歇性崩溃的bug,在重写过程中一个都没出现。当然,重写本身花了不少时间,但后续维护成本大幅降低。

1.4 开发环境搭建:从零开始

好,理论说完了,咱们动手。搭建Rust嵌入式开发环境,其实就三步。

1.4.1 安装rustup

rustup是Rust的版本管理工具。打开终端,执行:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

安装完成后,重启终端,输入 rustc --version 确认安装成功。

注意:如果你在Windows上,建议用WSL2或者直接装Linux虚拟机。虽然Windows也能用,但很多嵌入式工具链对Linux支持更好。我个人习惯在Ubuntu 22.04上开发,省心。

1.4.2 配置cargo和工具链

cargo是Rust的包管理器和构建工具。安装rustup时它会自动装上。接下来,我们需要添加嵌入式目标架构:

rustup target add thumbv7em-none-eabihf
rustup target add thumbv6m-none-eabi
rustup target add riscv32imac-unknown-none-elf

这些目标架构对应不同的ARM Cortex-M内核和RISC-V芯片。你根据自己手头的开发板选择就行。我刚开始学的时候,用的是STM32F4系列,所以加了 thumbv7em-none-eabihf

1.4.3 安装必要的工具

嵌入式开发还需要一些辅助工具:

  • cargo-generate:快速生成项目模板
  • probe-rs:调试和烧录工具
  • flip-link:链接器配置工具

安装命令:

cargo install cargo-generate probe-rs-cli flip-link

嗯,这里要注意:probe-rs依赖libusb,Linux下需要安装 libusb-1.0-0-dev。我曾经在Arch Linux上折腾了半天,就是因为忘了装这个依赖。

1.5 知识体系总览

为了让你对本章内容有个整体印象,我画了一张图:

Rust嵌入式开发 Rust语言特性 嵌入式系统简介 Rust在嵌入式中的优势 开发环境搭建 零成本抽象 所有权与借用 无畏并发 资源受限 实时性要求 可靠性第一 内存安全 并发安全 rustup安装 cargo配置

这张图把本章的知识点串起来了。你看,Rust语言特性是基础,嵌入式系统是应用场景,Rust的优势是桥梁,环境搭建是动手的第一步。四者缺一不可。

1.6 避坑指南:我踩过的那些坑

最后,分享几个我刚开始用Rust做嵌入式时遇到的坑:

  • 目标架构选错:我第一次用STM32F103,选了thumbv7em-none-eabihf,结果编译出来的程序跑不起来。后来才发现F103是Cortex-M3,应该用thumbv7m-none-eabi。嗯,这个坑我记了很久。
  • 忘记安装链接脚本:Rust嵌入式项目需要自己提供链接脚本(memory.x)。我第一次编译时,cargo报了一堆链接错误,我还以为是代码写错了。后来才发现是忘了把链接脚本放到项目里。
  • 调试器驱动问题:在Windows上,ST-Link调试器需要安装驱动。我折腾了两个小时,最后发现是驱动版本太旧。换成最新版就好了。

重要提醒:如果你用的是J-Link调试器,记得先装SEGGER的驱动包。probe-rs虽然支持J-Link,但需要正确的驱动版本。我曾经因为驱动不匹配,导致调试器连不上目标板,白白浪费了一个下午。

好了,第一章的内容就到这里。环境搭好了,下一章咱们就开始写第一个Rust嵌入式程序——点亮LED。那才是真正有意思的部分。


专注资料整理