这篇文章旨在尝试将 Embassy 的 blinky 案例在 Blue Pill (STM32F103C8T6)开发板上运行,它将记录所需要的依赖和常见问题的解决方法
本文参考了 Jonathan Klimt 的环境配置
系统环境: Ubuntu 22.04.4 (6.5.0-26-generic)
1. 前提
假设已经安装 rust-up
和 build-essential
,有正常的 Rust 编译环境。当前使用的 Rust Toolchian 版本为 1.77.1(2024-03-27),如果出现问题可以尝试使用这个 Toolchain 版本看看问题是否消失。
1.1 依赖库安装
sudo apt install -y pkg-config libudev-dev libusb-1.0 libftdil-debv
1.2 probe-rs
Toolkit
我们安装 probe-rs
,其中包含了 probe-rs
,cargo-flash
,cargo-embed
等常用工具
cargo install probe-rs --features cli
1.3 ARM Cortex-m toolchain
这是进行交叉编译需要的库
sudo apt install binutils-arm-none-eabi
1.4 连接设备
我们需要安装 OpenOCD 来对设备进行快速烧录和调试
sudo apt-get install openocd
安装完成后,我们尝试使用 OpenOCD 对我们的 ST-Link 设备进行探测。我们先查看 ST-Link 连接器是否被时被识别,我们使用 lsusb | grep ST
命令对它进行查找
说明我们已经成功连接了,这时我们通过 OpenOCD 来探测设备是否工作正常
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg
我们注意到有错误信息,这是因为这个型号(STM32F103C8T6)的芯片是仿制版,其 CPU tap id 被修改,请见 这个 讨论。我们将 OpenOCD 安装目录(通常为 /usr/share/openocd
)下 scripts/target
的 stm32f1x.cfg
中的 0x1ba01477
改为 0x2ba01477
。请注意将原始文件保存,以免需要恢复。
我们现在能够成功连接并且识别开发板了
1.5 ST-Link Tools
我们安装 st-link tools 便于我们对开发板进行快速的格式化和烧录,这样能够使得我们绕开 cargo-embed 工具,能够更清楚地看到错误信息,并且更灵活。
我们下载 stlink-1.8.0_amd64.deb 或任何版本的 Debian 包。接下来在下载位置使用 sudo apt install ./{file-name.deb}
进行安装。这样不需要我们编译。
安装完成后使用 st-info --descr
进行检查是否正常
我们可以尝试使用 st-erase
对设备进行格式化(慎重),但是可能会出现 "Flash Memory is Write Protected" 提示,这是因为 STM32 芯片的写保护措施。如果我们使用 "ST-Link Tools" 直接使用 cargo embed
命令,只会在写入 Page 0 时报错,但是不会写出错误原因。
现在我们可以使用 Windows 下的 ST-Link Utility 软件对其进行解锁。
首先连接设备,在 ST-Link Utility 中找到 Target -> Connect
连接完成后选择 Target -> Option Bytes
在这里我们关闭 Read Out Protection (如果没有关闭)
我们反选所有的 Flash 扇区保护
最后点击右下角 Apply 应用设置,现在开发板的读写保护已经被关闭了
2. Embassy 案例
我们 clone Embassy 项目并进入 STM32F1x 的示例下
2.1 代码理解
使用 Embassy 框架使得写一个任务变得十分简单。我们使用异步关键词 async
修饰这个函数,并且使用 embassy_executor::main
来告诉编译器这个是主任务。
我们通过 调用 embassy_stm32::init
函数初始化芯片和外围设备,该函数返回可用的外围设备对象(记为 p
)
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
}
接下来我们可以通过创建Output
对象获得 PC13
这个引脚的控制,最后在一个循环中将这个引脚置高,等待一段时间再置低。
这里简单说明:Timer::after_millis
函数返回一个 Future
对象,我们在这里使用 .await
会放弃CPU使用权并交还给执行器。在时钟过期后,程序将从这里被恢复执行。
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
info!("Hello World!");
let mut led = Output::new(p.PC13, Level::High, Speed::Low);
loop {
info!("high");
led.set_high();
Timer::after_millis(300).await;
info!("low");
led.set_low();
Timer::after_millis(300).await;
}
}
2.2 烧录运行
git clone https://github.com/embassy-rs/embassy.git
cd embassy/examples/stm32f1
现在使用 cargo run 进行编译和写入
cargo run --bin blinky --release
在写入完成后 Blue Pill 就能够闪灯了!
Top comments (0)