从零开始制作 Rust MCU SDK - PAC 制作篇
从零开始制作 Rust MCU SDK - PAC 制作篇
怎么制作
制作一个 SDK 的顺序为:
SVD -> PAC -> HAL
第一步制作 PAC(Peripheral Access Crate)
使用工具:svd2rust。这个工具可以根据 svd 文件生成 PAC。
接下来以 CW32L010 为例制作一个 PAC。
1. 安装工具
cargo install svd2rustcargo install formrustup component add rustfmt2. 创建一个 PAC 库工程
需要用 Cargo 创建一个 lib 工程,命令如下:
cargo new cw32l010_pac --libcd cw32l010_pac将 svd 文件放入工程根目录,例如:
cw32l010_pac/├── Cargo.toml└── STM32F103.svd3. 根据芯片内核选择 target
svd2rust 支持 Cortex-M、MSP430、RISC-V 和 Xtensa LX6 微控制器。生成的 crate 可通过 --target 标志针对特定架构进行定制。
该标志接受 "cortex-m"、"msp430"、"riscv"、"xtensa-lx" 和 "none" 作为值。使用 "none" 可生成与架构无关的 crate,适用于 svd2rust 当前未知的架构,例如 Cortex-A 架构。
如果省略 --target 标志,svd2rust 将默认目标架构为 Cortex-M。
常用选择:
STM32F103 / STM32F407 / STM32G4 -> --target cortex-mCH32V203 / CH32V307 / CH32V003 -> --target riscv架构不确定,只想生成寄存器访问层 -> --target none比如 STM32:
svd2rust -i .\STM32F103.svd --target cortex-m比如 WCH 的 CH32V307:
svd2rust -i .\CH32V307.svd --target riscv执行后,Cortex-M 目标通常会生成:
build.rsdevice.xlib.rs4. 拆解 lib.rs 为正常 Rust 工程目录
官方文档也说明了 Cortex-M 会生成这三个文件:build.rs、device.x、lib.rs。
所有这些文件都必须包含在同一个设备 crate 中。lib.rs 文件包含多个内联模块且未格式化。建议使用 form 工具将其拆分,然后使用 rustfmt / cargo fmt 格式化输出:
svd2rust -i CW32L010.svdrm -rf srcform -i lib.rs -o src/ && rm lib.rscargo fmt5. 不同内核的 Cargo.toml 配置
生成的 crate 必须提供一个可选的 rt 功能,并依赖于以下这些 crate:
critical-sectionv1.xcortex-m>= v0.7.6cortex-m-rt>= v0.6.13vcell>= v0.1.2
此外,当启用 rt 特性时,必须同时启用 cortex-m-rt 的 device 特性。设备 crate 的 Cargo.toml 将如下所示:
[dependencies]critical-section = { version = "1.0", optional = true }cortex-m = "0.7.6"cortex-m-rt = { version = "0.6.13", optional = true }vcell = "0.1.2"
[features]rt = ["cortex-m-rt/device"]Cortex-M PAC 可以按照下面的方式配置
[package]name = "cw32l010_pac"version = "0.1.0"edition = "2021"
[dependencies]critical-section = { version = "1.0", optional = true }cortex-m = "0.7.6"cortex-m-rt = { version = "0.6.13", optional = true }vcell = "0.1.2"
[features]default = ["critical-section"]rt = ["cortex-m-rt/device"]这些依赖和 rt feature 的写法来自 svd2rust 官方文档。Cortex-M 生成的 PAC 通常需要 critical-section、cortex-m、cortex-m-rt、vcell;其中 rt feature 要启用 cortex-m-rt/device。
这里的:
default = ["critical-section"]是为了本地练习时能直接用:
Peripherals::take()官方文档里提到,Peripherals::take 通过生成 crate 的 critical-section feature 启用,并且这个方法只能成功调用一次。
RISC-V PAC 可以按照下面的方式配置
[package]name = "ch32v307-pac"version = "0.1.0"edition = "2021"
[dependencies]critical-section = { version = "1.0", optional = true }riscv = "0.12.1"riscv-rt = { version = "0.13.0", optional = true }vcell = "0.1.0"
[features]default = ["critical-section"]rt = ["riscv-rt"]svd2rust 文档里给 RISC-V 的依赖示例包含 critical-section、riscv、riscv-peripheral、riscv-rt、vcell,其中 rt 相关依赖应做成可选 feature。
WCH 这里要稍微注意:生成 PAC 只是寄存器访问层,启动代码、中断入口、链接脚本、运行时 crate 还要看后面具体用不用 qingke-rt、riscv-rt、ch32-hal 之类的生态。单纯做寄存器访问,PAC 本身可以先独立生成出来。
生成的代码默认使用 2021 版 Rust。若想启用 2024 版相关功能,请传入 --edition=2024。
6. 检查 PAC 能否编译
添加对应的 target 工具
命令如下:
rustup target add xxxxxxxxxx- Cortex-M0+ 使用
thumbv6m-none-eabi - Cortex-M3 使用
thumbv7m-none-eabi - Cortex-M4 使用
thumbv7em-none-eabihf - RISC-V 青稞 V4F 使用
riscv32imac-unknown-none-elf
检查命令:
cargo check --target thumbv7em-none-eabihf
# 开启 rt 可以使用下面的命令cargo check --target thumbv7m-none-eabi --features rt7. 在工程中使用 PAC
后续可以在 HAL 或应用工程中引入生成好的 PAC crate,并基于寄存器访问层继续封装外设抽象。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!