本帖最后由 wangqy_ic 于 2024-11-18 00:15 编辑
#申请原创#
使用 Rust 进行嵌入式开发之借尸还魂编写 APM32 应用
开发环境搭建
本文描述的是在 Windows 系统进行开发,其他系统可参照进行。主要是两个主要步骤:
- 安装 Microsoft C++ 生成工具
- 安装 rustup
安装基础环境
安装好基础环境后,就可以进行 PC 的开发,过程是:
- 安装 Microsoft C++ 生成工具
- 安装 rustup
安装 Microsoft C++ 生成工具
从微软的网站下载Microsoft C++ 生成工具,网址:
https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/
点击紫色按钮就可以下载。
或者使用这个地址直接下载:
https://aka.ms/vs/17/release/vs_BuildTools.exe
下载完成后双击打开,在选择工作负荷请选择“使用C++的桌面开发”,点击“安装”并等待安装完成。
安装 rustup
从 Rust 官方网站下载 rust-init:https://www.rust-lang.org/tools/install
如果是32位系统,请选择绿色圈的按钮,64位系统请选择红色圈的按钮。或者用下面的链接直接下载:
- 32-bit: https://static.rust-lang.org/rustup/dist/i686-pc-windows-msvc/rustup-init.exe
- 64-bit: https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe
下载完成后双击打开,会打开一个命令行窗口:
有3个安装选项,直接输入1并回车,选择默认配置进行安装。安装过程会从自动下载所需内容:
出现绿色的文字提示表示安装完成:
按回车键完成安装,命令行窗口会关闭。重新打开命令行窗口(或者 Powershell 窗口,或者 Windows Terminal 窗口都可以),分别输入下面两个命令进行检查已安装工具的版本:
Hello world!
基础环境安装成功,我们可以跑个 Hello world!
在命令行窗口运行命令:
cargo new hello_world
cd hello_world
cargo run
可以看看实际运行情况:
倒数第二行的 Hello, world! 就是运行的结果。上述命令具体是这样的:
- cargo new 创建了一个名为 hello_world 的工程:创建了名为 hello_world 的文件夹,给了一个默认的代码和配置。
- cd hello_world 切换到刚才创建的工程目录。
- cargo run 构建和运行程序。
开发嵌入式程序的总体流程,也和这个差不多~
基础环境就这样了,下面介绍嵌入式开发需要的工具:
安装嵌入式开发所需工具
工具链
目前支持的工具链,可以通过 rustup target list 命令查看,这里不再赘述。目前 ARM 相关的有:
Cortex-M0, M0+, and M1 (ARMv6-M architecture): thumbv6m-none-eabi
Cortex-M3 (ARMv7-M architecture): thumbv7m-none-eabi
...
|
我们使用 rustup target add 命令安装所需的,例如想要支持 Cortex-M4 的 MCU,输入这个命令:
rustup target add thumbv7m-none-eabi
命令执行后会从网络拉取资源,且只有两句提示,请耐心等待:
其他工具
这些工具有:
- arm-none-eabi-gdb
- probe-rs
- cargo-binutils
- llvm-tools
arm-none-eabi-gdb
arm-none-eabi-gdb 是 ARM GNU 工具链的一部分,请自行安装并把对应的 bin 文件夹加入环境变量 PATH 中,这里就不再详细描述安装过程。
probe-rs
这个有点特殊,需要在 Powershell 里执行:
irm https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.ps1 | iex
如命令所示,这个是直接从 github 上拉取资源的。
如果你执行的命令有困难,可以搜索“Github 文件加速:网站,然后把下面的地址填进去,一般都可以下载的:
https://github.com/probe-rs/probe-rs/releases/download/v0.24.0/probe-rs-tools-x86_64-pc-windows-msvc.zip
|
把下载到的文件直接解压缩到 cargo 的对应目录,一般是:
C:\Users\<你的用户名>\.cargo\bin
| 确保这个文件的正确路径:C:\Users\<你的用户名>\.cargo\bin\cargo-embed.exe 。
cargo-binutils
使用命令安装:
cargo install cargo-binutils
这个命令会下载需要的代码,并编译生成全部的可执行程序。下载和编译都需要花一些时间,最后的提示类似下图:
llvm-tools
使用这个命令:
rustup component add llvm-tools llvm-tools-preview
类似上面的 rustup target add ,这个命令也是两句提示,中间过程没有其他信息,需要耐心等待~
其他 Debug 相关工具
如果需要调试,还需要相关的工具,如:
这些就不一一介绍了~
IDE 相关内容
IDE 的话,VSCode就非常不错,请配合以下插件使用:
- rust-analyzer
- Debugger for probe-rs
后一个也就是配合 probe-rs 使用的,具体安装方法也不再详述。
Rust 嵌入式开发初探
创建 Rust 嵌入式项目,其实蛮简单的,在某个合适的目录下执行以下命令创建工程并用 vs code 打开文件夹:
cargo new blink
cd blink
code .
前面讲过,cargo new 创建的项目就是打印 Hello, world!。我们现在基于这个模板,通过五个步骤修改为合适单片机的项目。
Step.1 创建 Embed.toml 文件:
[default.general]
chip = "STM32F411RE"
看内容大概猜测到了,这个项目使用的单片机是 STM32F411RE。
Step.2 创建 memory.x 文件:
/* Linker script for the STM32F411RE */
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
}
这个文件的内容看起来也很熟悉,对了,就是 LD 文件指明 Flash/ RAM 地址和长度。这个内容是足够我们将要完成的项目。
Step.3 创建 .cargo 目录,并创建 .cargo\config.toml 文件:
[build]
target = "thumbv7m-none-eabi"
[target.thumbv7m-none-eabi]
rustflags = ["-C", "link-arg=-Tlink.x"]
嗯,从内容也大致猜到作用了,我们项目的目标平台是 thumbv7em-none-eabi,也定义了链接参数。我们暂时也不用具体的参数写法。
Step.4 修改 Cargo.toml:
<div data-page-id="YJxjdWt94owtVqxa0srcKEBWned" data-lark-html-role="root" data-docx-has-block-data="false"><pre class="ace-line ace-line old-record-id-WDiSdPTacoRRZVxEzC9cmCaKn8e"><code class="language-TOML" data-lark-language="TOML" data-wrap="false">[package]
name = "blink"
version = "0.1.0"
edition = "2021"
[dependencies]
embedded-hal = "1.0.0"
nb = "1"
cortex-m = "0.7"
cortex-m-rt = "0.7"
panic-halt = "1.0.0"
stm32f4xx-hal = {version = "0.22.1",features = ["stm32f407"]}</code></pre></div><span data-lark-record-data="{"rootId":"YJxjdWt94owtVqxa0srcKEBWned","text":{"initialAttributedTexts":{"text":{"0":"[package]\nname = \"blink\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nembedded-hal = \"1.0.0\"\nnb = \"1\"\ncortex-m = \"0.7\"\ncortex-m-rt = \"0.7\"\npanic-halt = \"1.0.0\"\nstm32f4xx-hal = {version = \"0.22.1\",features = [\"stm32f407\"]}"},"attribs":{"0":"*0|b+4m*0+1p"}},"apool":{"numToAttrib":{"0":["author","7434168515399139331"]},"nextNum":1}},"type":"text","referenceRecordMap":{},"extra":{"channel":"saas","pasteRandomId":"4cba5a68-0cb5-44f4-aee9-147b74174055","mention_page_title":{},"external_mention_url":{}},"isKeepQuoteContainer":false,"isFromCode":true,"selection":[{"id":223,"type":"text","selection":{"start":0,"end":227},"recordId":"WDiSdPTacoRRZVxEzC9cmCaKn8e"}],"payloadMap":{},"isCut":false}" data-lark-record-format="docx/text" class="lark-record-clipboard"></span>
相对于工程创建时的内容,是增加了 7 ~ 12 行。也就是定义了项目的依赖~
Step.5 最后一步,修改代码 src\main.rs:
//! Blinks an LED
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f4xx_hal as hal;
use crate::hal::{pac, prelude::*};
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();
let gpioa = p.GPIOA.split();
let mut led = gpioa.pa5.into_push_pull_output();
至此,工程已经能编译出 STM32F411RE MCU 下的固件,功能是让 PA5 这个 IO 口定时翻转~可以用 qemu 进行测试:
qemu-system-gnuarmeclipse.exe --board NUCLEO-F411RE --image D:\rust\blink\target\thumbv7m-none-eabi\debug\blink
哦吼~ LED 灯闪起来了~
我不会在文章中贴视频,请移步bilibili:
【Rust Embedded 运行在 qemu】 https://www.bilibili.com/video/BV1ZMU7Y3E19/
借尸还魂编写 APM32 应用
惊悚的环节来了~~~
这个坛子里的大家都应该知道 APM32 系列 MCU 对 STM32 MCU 的兼容性,所以~我们也用 APM32F411VC TinyBoard 进行了测试,只需3步:
Step.1 当然是需要修改 APP 代码:
修改 main.rs 中关于 LED 的管脚,我们使用 APM32F411VC TinyBoard 上的 LED2,也就是 PE6:
//! Blinks an LED
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use panic_halt as _;
use stm32f4xx_hal as hal;
use crate::hal::{pac, prelude::*};
use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();
// let gpioa = p.GPIOA.split();
// let mut led = gpioa.pa5.into_push_pull_output();
// APM32F411VC TinyBoard: PE6 --> LED2
let gpioe = p.GPIOE.split();
let mut led = gpioe.pe6.into_push_pull_output();
loop {
for _ in 0..1_000_000 {
Step.2 生成烧录固件并烧录
编译无误后,通过下面的命令生成 Hex 文件:
cargo-objcopy --bin blink --release -- -O ihex target\thumbv7m-none-eabi\release\blink.hex
Step.3 烧录
最后就可以把开发板连接到 PC 上,用你熟悉的工具烧录,我这里用了 PyOCD:
pyocd load -t apm32f411ve target\thumbv7m-none-eabi\release\blink.hex
激动人心的结果:
所以,请移步 bilibili 观看视频:【Rust 运行在 APM32F411 Tiny Board】 https://www.bilibili.com/video/BV1cwU7YjEe4/
不是结论的结论
Rust 从最开始的个人项目,逐渐变成已经被工业界接纳的一个编程语言,并以极快的速度扩展着。从 Linux 内核到驱动开发都得到展现。嵌入式领域,特别的 MCU,也得到 Rust 官方的直接支持,相信各种生态工具会慢慢得到支持从而发展。目前国产 MCU 中,GD 的 MCU 是得到了社区的支持,多个型号的 MCU 都匹配了驱动,希望极海和更对的国产半导体厂商也积极争取上游和社区的支持,完善 Rust 的开发工具及生态~~~
------
【相关连接】
Rust 官方:https://www.rust-lang.org/
Rust 官方 Embedded:https://www.rust-lang.org/what/embedded
B站 软件工艺师 的《Rust 编程语言教程》:https://www.bilibili.com/video/BV1m1sreSEoh/
B站 爆米花胡了 的 《Rust嵌入式开发入门》:https://www.bilibili.com/video/BV16u411d7Fv/
|