Rust 嵌入式开发:RISC-V、ARM、ESP32 的支持

核心要点

  • 为什么 Rust 适合嵌入式开发:安全性、性能、内存安全
  • 嵌入式开发的基本概念:交叉编译、链接脚本、内存布局
  • RISC-V 架构的支持:使用 Rust 开发 RISC-V 程序
  • ARM 架构的支持:使用 Rust 开发 ARM 程序
  • ESP32 的支持:使用 Rust 开发 ESP32 程序
  • 实际案例:实现一个简单的 LED 闪烁程序

上个月我尝试用 C 语言写一个 ESP32 的 LED 闪烁程序,结果花了半天时间调试内存泄漏问题。这让我开始思考,有没有更安全的语言可以用于嵌入式开发。

为什么 Rust 适合嵌入式开发

内存安全

Rust 的所有权、借用和生命周期机制可以在编译时检查内存安全问题,避免内存泄漏和段错误。这在资源受限的嵌入式系统中尤其重要。

性能

Rust 可以编译成高效的机器码,性能接近 C 语言。同时,Rust 的零成本抽象可以让你写出简洁的代码,而不会影响性能。

生态系统

Rust 有丰富的嵌入式开发生态系统,包括:

  • embedded-hal:硬件抽象层,提供统一的 API 访问外设
  • cortex-m:ARM Cortex-M 处理器的支持
  • riscv:RISC-V 架构的支持
  • esp32-hal:ESP32 芯片的硬件抽象层

嵌入式开发的基本概念

交叉编译

嵌入式系统通常使用不同架构的处理器,所以需要交叉编译。Rust 提供了简单的交叉编译方法。

1
2
3
4
5
6
7
8
9
# 安装交叉编译工具链
rustup target add riscv32imc-unknown-none-elf
rustup target add thumbv7m-none-eabi

# 编译到 RISC-V 架构
cargo build --target riscv32imc-unknown-none-elf --release

# 编译到 ARM Cortex-M 架构
cargo build --target thumbv7m-none-eabi --release

链接脚本

链接脚本用于指定程序的内存布局。在 Rust 中,你可以使用 link-arg 编译选项来指定链接脚本。

1
2
3
4
5
6
7
8
9
10
# Cargo.toml
[profile.release]
lto = true
codegen-units = 1
panic = "abort"

[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
rustflags = [
"-C", "link-arg=-Tlink.x",
]

内存布局

嵌入式系统的内存布局通常包括:

  • Flash 内存:用于存储程序代码和常量数据
  • RAM:用于存储变量和堆栈
  • 外设寄存器:用于访问硬件外设

RISC-V 架构的支持

RISC-V 是一种开源的指令集架构,具有模块化和可扩展性的特点。Rust 对 RISC-V 架构的支持非常好。

开发板推荐

  • Sipeed Longan Nano:基于 GD32VF103 芯片的 RISC-V 开发板
  • Espressif ESP32-C3:ESP32 系列的 RISC-V 芯片

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#![no_std]
#![no_main]

use panic_halt as _;
use riscv_rt::entry;
use gd32vf103_hal::prelude::*;
use gd32vf103_hal::pac;

#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut rcu = dp.RCU.configure().freeze();
let mut gpioa = dp.GPIOA.split(&mut rcu);

let mut led = gpioa.pa1.into_push_pull_output();

loop {
led.toggle();
for _ in 0..1_000_000 {
// 简单的延时
}
}
}

ARM 架构的支持

ARM 架构是嵌入式开发中最常用的架构之一。Rust 对 ARM Cortex-M 处理器的支持非常成熟。

开发板推荐

  • STM32F4 Discovery:基于 STM32F407 芯片的 ARM 开发板
  • Arduino Uno R4:基于 RA4M1 芯片的 ARM 开发板

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#![no_std]
#![no_main]

use panic_halt as _;
use cortex_m_rt::entry;
use stm32f4xx_hal::prelude::*;
use stm32f4xx_hal::pac;

#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let gpioa = dp.GPIOA.split();

let mut led = gpioa.pa5.into_push_pull_output();

loop {
led.toggle();
for _ in 0..1_000_000 {
// 简单的延时
}
}
}

ESP32 的支持

ESP32 是一款流行的 Wi-Fi + 蓝牙芯片,广泛应用于物联网设备。Rust 对 ESP32 的支持正在快速发展。

开发板推荐

  • Espressif ESP32-DevKitC:官方推荐的 ESP32 开发板
  • Wemos D1 Mini ESP32:小巧的 ESP32 开发板

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#![no_std]
#![no_main]

use panic_halt as _;
use esp32_hal::prelude::*;
use esp32_hal::pac;
use esp32_hal::delay::Delay;

#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut system = dp.SYSTEM.split();
let clocks = system.clock_control.freeze();
let mut delay = Delay::new(&clocks);

let gpio = dp.GPIO.split();
let mut led = gpio.gpio2.into_push_pull_output();

loop {
led.toggle();
delay.delay_ms(1000u32);
}
}

实际案例:LED 闪烁程序

让我们实现一个简单的 LED 闪烁程序,使用 Rust 开发。

步骤 1:创建项目

1
2
cargo new led-blink
cd led-blink

步骤 2:配置 Cargo.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[dependencies]
embedded-hal = "0.2"
esp32-hal = "0.13"
panic-halt = "0.2"
riscv-rt = "0.9"

[profile.release]
lto = true
codegen-units = 1
panic = "abort"

[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
rustflags = [
"-C", "link-arg=-Tlink.x",
]

步骤 3:编写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#![no_std]
#![no_main]

use panic_halt as _;
use riscv_rt::entry;
use esp32_hal::prelude::*;
use esp32_hal::pac;
use esp32_hal::delay::Delay;

#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let mut system = dp.SYSTEM.split();
let clocks = system.clock_control.freeze();
let mut delay = Delay::new(&clocks);

let gpio = dp.GPIO.split();
let mut led = gpio.gpio2.into_push_pull_output();

loop {
led.toggle();
delay.delay_ms(1000u32);
}
}

步骤 4:编译和烧录

1
2
3
4
5
# 编译
cargo build --target riscv32imc-unknown-none-elf --release

# 烧录
esptool.py --chip esp32c3 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x0 target/riscv32imc-unknown-none-elf/release/led-blink

总结

Rust 是一种非常适合嵌入式开发的语言,它兼具了 C 语言的性能和安全性。Rust 对 RISC-V、ARM 和 ESP32 架构的支持都非常好,有丰富的生态系统和社区支持。

如果你正在寻找一种更安全、更现代的嵌入式开发语言,那么 Rust 是一个很好的选择。