rust嵌入式开发零基础入门教程(一)
1. 为什么选择 Rust 进行嵌入式开发?
传统上,嵌入式开发主要使用 C 或 C++。虽然它们很强大,但也伴随着一些固有的挑战,比如内存安全问题(野指针、内存泄漏)和复杂的并发编程。Rust 正是为了解决这些痛点而生的。
以下是 Rust 在嵌入式领域的一些核心优势:
-
内存安全,无 GC (Garbage Collection): Rust 通过所有权系统 (Ownership System)、借用 (Borrowing) 和生命周期 (Lifetimes),在编译时强制执行内存安全。这意味着你不用担心运行时出现空指针引用、数据竞争等问题,同时也避免了垃圾回收器带来的性能开销和不确定性,这对于资源受限的嵌入式系统至关重要。
-
零成本抽象: Rust 提供了强大的抽象能力(如泛型、Trait),但这些抽象在编译时会被优化掉,几乎不会产生额外的运行时开销,使得你可以编写高层次、易读的代码,同时获得接近汇编语言的性能。
-
强大的类型系统: 严格的类型检查帮助你在编译阶段捕获大量错误,减少调试时间。
-
并发安全: Rust 的所有权系统也扩展到了并发编程,有效防止了数据竞争,让你能更安全地编写多线程代码。
-
优秀的工具链: Rust 拥有
cargo
(包管理器和构建系统)、rustfmt
(代码格式化工具)、clippy
(Linter) 等一系列强大且易用的工具,极大地提高了开发效率。 -
活跃的社区和生态: 围绕嵌入式 Rust 的社区正在迅速发展,提供了大量库(crates)和支持资源。
2. 设置你的开发环境
在开始编写代码之前,需要配置好开发环境。
2.1 安装 Rust 工具链
首先,安装 Rust。我们使用 rustup
,它是 Rust 的官方安装程序和工具链管理器。
-
打开终端 (Terminal) 或命令提示符 (Command Prompt)。
-
运行以下命令:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Windows 用户: 推荐下载并运行
rustup-init.exe
安装程序,你可以从 Rust 官网 获取。或者在 WSL (Windows Subsystem for Linux) 中运行上述curl
命令。 -
按照提示进行安装,通常选择默认安装即可(
Proceed with installation (default)
)。
-
-
验证安装: 安装完成后,关闭并重新打开你的终端或命令提示符,然后运行:
rustc --version cargo --version
如果显示版本号,说明 Rust 编译器 (
rustc
) 和包管理器 (cargo
) 已经成功安装。
2.2 安装嵌入式开发所需组件
为了进行嵌入式开发,我们需要添加特定的 Rust 目标 (target) 和一些工具。
-
添加
thumbv7em-none-eabihf
目标: 这是 ARM Cortex-M 微控制器(例如 STM32 系列)常用的目标。thumbv7em
指的是 Cortex-M4/M7 处理器架构,none
表示不依赖操作系统(裸机),eabihf
表示支持硬件浮点运算。rustup target add thumbv7em-none-eabihf
如果你使用其他 ARM Cortex-M 系列,可能需要添加其他目标,例如
thumbv6m-none-eabi
(Cortex-M0/M0+) 或thumbv7em-none-eabi
(Cortex-M3)。 -
安装
cargo-generate
: 这是一个代码生成工具,可以帮助我们快速从模板创建新的 Rust 项目。cargo install cargo-generate
-
安装
cortex-m-cli
: 这是 Cortex-M 开发的命令行工具集,包含了一些实用工具,如调试器等。cargo install cortex-m-cli
-
安装
probe-run
(可选但推荐): 这是一个用于直接在微控制器上运行和调试程序的工具,非常方便。它需要你连接一个调试探针(如 ST-Link, J-Link)。cargo install probe-run
2.3 安装代码编辑器 (推荐 VS Code)
一个好的代码编辑器能大大提升开发体验。Visual Studio Code (VS Code) 是一个非常受欢迎的选择,它拥有强大的 Rust 扩展支持。
-
下载并安装 VS Code: Visual Studio Code - Code Editing. Redefined
-
安装 Rust 插件:
-
打开 VS Code。
-
点击左侧的“扩展”图标(或按
Ctrl+Shift+X
)。 -
搜索并安装 "rust-analyzer" 插件。这是 Rust 的语言服务器,提供了代码补全、错误检查、跳转定义等功能。
-
你可能还会想安装 "crates" 插件,它能帮你管理
Cargo.toml
中的依赖。
-
3. 编写你的第一个 "Hello, World!" 嵌入式程序 (非硬件)
在真正烧录到硬件之前,我们先创建一个基于模拟环境的“嵌入式”项目,让你感受一下 Rust 嵌入式项目的结构。
3.1 创建新项目
我们将使用一个社区维护的模板来快速生成一个 Cortex-M 的 Rust 项目。
-
选择一个工作目录,然后在终端中进入该目录。
-
运行
cargo generate
命令创建项目:cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
-
当提示
Project Name:
时,输入你的项目名称,例如:hello-cortex-m
-
cargo generate
会根据模板为你生成一个完整的项目结构。
-
3.2 了解项目结构
进入你刚刚创建的项目目录 (cd hello-cortex-m
),你会看到类似这样的文件结构:
hello-cortex-m/
├── .cargo/
│ └── config.toml # Cargo 配置,用于指定目标、运行器等
├── .vscode/ # VS Code 配置 (可选)
│ └── launch.json # 调试配置
├── src/
│ ├── main.rs # 你的主程序代码
│ └── lib.rs # 库文件 (如果有的话)
├── Cargo.toml # Cargo 项目配置文件
├── memory.x # 内存布局脚本 (重要!)
└── build.rs # 构建脚本 (可选)
-
Cargo.toml
: Rust 项目的核心配置文件,定义了项目的元数据、依赖项等。 -
src/main.rs
: 你的 Rust 源代码文件。 -
.cargo/config.toml
: 这个文件很重要,它配置了cargo
命令在构建和运行嵌入式项目时的行为,例如指定了交叉编译目标和运行调试器。 -
memory.x
: 这是一个链接器脚本,它告诉链接器如何将你的程序代码和数据放置在微控制器的内存(RAM 和 Flash)中。在裸机嵌入式开发中,你需要手动管理内存布局。
3.3 编写 "Hello, World!"
打开 src/main.rs
文件,你会看到一个基本的裸机程序框架。我们将修改它来打印一条消息。
Rust
#![no_std] // 不使用 Rust 标准库,因为嵌入式环境通常没有操作系统
#![no_main] // 不使用 Rust 的默认 main 函数(入口点),我们需要自己定义// 导入必要的宏和模块
use panic_halt as _; // 发生 panic 时停止程序
use cortex_m_rt::entry; // Cortex-M 运行时入口点宏// 引入 `cortex-m-debug` crate,用于打印消息(通过调试器)
use cortex_m_semihosting::{hprintln}; // `hprintln!` 宏用于通过半主机模式打印#[entry]
fn main() -> ! {// 打印 "Hello, World!" 到调试控制台hprintln!("Hello, Embedded Rust World!").unwrap();// 这是一个裸机程序,通常会进入一个无限循环,等待中断或执行任务loop {// 你可以在这里添加其他代码,例如点亮LED}
}
代码解释:
-
#![no_std]
和#![no_main]
:这两个属性告诉 Rust 编译器,这是一个裸机程序,不依赖标准的std
库,并且我们需要自己定义程序入口点。 -
use panic_halt as _;
:当程序发生不可恢复的错误(panic)时,这个 crate 会让 CPU 停止执行,防止程序崩溃。 -
use cortex_m_rt::entry;
:这是一个宏,标记了main
函数为 Cortex-M 微控制器的程序入口点。 -
use cortex_m_semihosting::{hprintln};
:cortex-m-semihosting
是一个库,它提供了一种通过调试器与开发主机进行通信的方式,称为半主机模式 (Semihosting)。hprintln!
就是通过这种模式将文本打印到你的调试器控制台。 -
#[entry]
:宏,将main
函数标记为程序的实际入口点。 -
fn main() -> !
:main
函数的签名。-> !
表示这个函数永不返回(因为它会进入一个无限循环)。 -
loop { ... }
:一个无限循环,在嵌入式系统中,主程序通常会进入一个循环来持续运行。
3.4 构建项目
在项目根目录(hello-cortex-m
)下,运行构建命令:
cargo build --release
-
cargo build
:用于编译你的项目。 -
--release
:以发布模式编译,这会进行更多的优化,生成更小、更快的二进制文件(调试模式通常更大,包含调试信息)。
如果一切顺利,你会看到编译成功的提示。生成的二进制文件(.elf
格式)会位于 target/thumbv7em-none-eabihf/release/
目录下,名为 hello-cortex-m
。
3.5 运行 "Hello, World!" (模拟/仿真)
要在没有实际硬件的情况下看到 "Hello, World!" 的输出,你需要一个能够模拟 Cortex-M 的工具。
-
QEMU (快速入门模拟) QEMU 是一个通用的开源机器模拟器和虚拟器。我们可以用它来模拟 Cortex-M CPU,而无需真正的开发板。
-
安装 QEMU:
-
Linux (Debian/Ubuntu):
sudo apt install qemu-system-arm
-
macOS (Homebrew):
brew install qemu
-
Windows: 从 QEMU 官网 下载安装包并安装。确保将 QEMU 的可执行文件路径添加到系统环境变量
PATH
中。
-
-
运行你的程序: 在
hello-cortex-m
项目的根目录下,运行:qemu-system-arm -cpu cortex-m3 -nographic -semihosting -kernel target/thumbv7em-none-eabihf/release/hello-cortex-m
-
-cpu cortex-m3
: 指定模拟的 CPU 类型。即使你使用的是thumbv7em
目标,cortex-m3
在 QEMU 中通常是一个稳定的选择来运行简单的 Cortex-M 程序。 -
-nographic
: 不显示图形界面。 -
-semihosting
: 启用半主机模式,这样hprintln!
的输出才能显示在终端。 -
-kernel
: 指定要加载并运行的固件文件。
-
如果一切正常,应该会在终端看到
Hello, Embedded Rust World!
的输出。 -
下一步
已经成功设置了 Rust 嵌入式开发环境,并运行了第一个模拟程序。在下一部分教程中,将深入探讨:
-
所有权、借用和生命周期在嵌入式 Rust 中的实际意义。
-
如何真正地烧录和运行程序到实际的开发板上(例如 STM32 系列)。
-
通过操作 GPIO(通用输入输出)点亮一个 LED。