将 Rust crates 用于 STM32 微控制器板
Using Rust crates for an STM32 microcontroller board
我目前正在尝试学习 Rust(专门针对嵌入式),来自嵌入式系统的 C 背景和 Python。
到目前为止,我一直在阅读 Rust Programming Language and Rust for Embedded,并阅读了网络上的一些博客文章。
我希望我的第一个项目是一个简单的“Blinky”,其中 LED 无限闪烁。我有一个 STM32L152CDISCOVERY 开发板,里面有一个 STM32L152 芯片(与 STM32L151 基本相同),它是一个 Cortex M3。
我不想从头开始实施所有内容,而是想利用现有的 crate 和 HAL。我发现了两个看起来很有希望的:stm32l1 and stm32l1xx-hal。我已经尝试阅读它们每个的文档以及部分源代码,但我仍然无法弄清楚如何正确使用它们。
有几个关于 Rust 和板条箱的问题:
我看到 stm32l1xx-hal
依赖于 stm32l1
。我是否需要在我的 Cargo.toml
文件中添加两者作为依赖项?还是会产生与所有权相关的问题?
这是添加它们的正确方法吗?为什么第二个加成那样[dependencies.stm32l1]
?
[dependencies]
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
panic-halt = "0.2.0"
stm32l1xx-hal = "0.1.0"
[dependencies.stm32l1]
version = "0.13.0"
features = ["stm32l151", "rt"]
要闪烁 LD4(连接到 PB4PB6),我必须在 RCC 寄存器中启用 GPIOB,然后配置引脚推拉输出。通过检查 stm32l1xx-hal
的文档,我发现有一个 RCC struct and a PB4 struct 方法 into_push_pull_output
。但是,我仍然不明白如何使用这些结构:如何导入它们或如何获取它们的实例。
我看过 stm32l1
的代码示例,但没有看过 stm32l1xx-hal
的代码示例。我知道我可以做到:
use stm32l1::{stm32l151};
...
let p = stm32l151::Peripherals::take().unwrap();
p.RCC.ahbenr.modify(|_,w| w.gpiopben().set_bit());
但在 stm32l1xx-hal
的源代码中,我看到 RCC 部分已经在 impl GpioExt for $GPIOX
中完成,但我不知道如何获得此“部分”功能。
感谢任何为我指明正确方向的帮助。
我从 Discord 社区得到了一些帮助。答案是(我稍微修改了一下):
stm32l1xx-hal
已经依赖于 stm32l1
作为 seen here。无需导入两次。添加到 Cargo.toml:
就足够了
[dependencies.stm32l1xx-hal]
version = "0.1.0"
default-features = false
features = ["stm32l151", "rt"]
- 请注意
default-features = false
是可选的,但没有它编译器会给我一个错误。
语法是等价的,但是正如我上面所说,我只需要添加一个HAL。可以在第一个样式中加花括号{}
来添加选项,如:
stm32l1xx-hal = { version = "0.1.0", features = ["stm32l151", "rt"]}
执行眨眼的正确代码(在 PB6 上,而不是 PB4,唉)是:
#![no_main]
#![no_std]
use panic_halt as _;
use cortex_m_rt::entry;
use stm32l1xx_hal::delay::Delay;
use stm32l1xx_hal::gpio::GpioExt;
use stm32l1xx_hal::hal::digital::v2::OutputPin;
use stm32l1xx_hal::rcc::{Config, RccExt};
use stm32l1xx_hal::stm32::Peripherals;
use stm32l1xx_hal::stm32::CorePeripherals;
use stm32l1xx_hal::time::MicroSeconds;
#[entry]
fn main() -> ! {
let p = Peripherals::take().unwrap();
let cp = CorePeripherals::take().unwrap();
// Get LED pin PB6
let gpiob = p.GPIOB.split();
let mut led = gpiob.pb6.into_push_pull_output();
// Set up a delay
let rcc = p.RCC.freeze(Config::default());
let mut delay = Delay::new(cp.SYST, rcc.clocks);
loop {
// Turn LED On
led.set_high().unwrap();
delay.delay(MicroSeconds(1_000_000_u32));
// Turn LED Off
led.set_low().unwrap();
delay.delay(MicroSeconds(1_000_000_u32));
}
}
- 对我来说,关键是要了解可以从
Peripherals
调用 split
方法,因为 stm32l1xx-hal
为 split
中定义的结构实现了 split
14=]。换句话说,HAL crate 不仅定义了新的结构,而且还扩展了现有结构的功能。我需要全神贯注于特征设计模式。
我目前正在尝试学习 Rust(专门针对嵌入式),来自嵌入式系统的 C 背景和 Python。 到目前为止,我一直在阅读 Rust Programming Language and Rust for Embedded,并阅读了网络上的一些博客文章。
我希望我的第一个项目是一个简单的“Blinky”,其中 LED 无限闪烁。我有一个 STM32L152CDISCOVERY 开发板,里面有一个 STM32L152 芯片(与 STM32L151 基本相同),它是一个 Cortex M3。
我不想从头开始实施所有内容,而是想利用现有的 crate 和 HAL。我发现了两个看起来很有希望的:stm32l1 and stm32l1xx-hal。我已经尝试阅读它们每个的文档以及部分源代码,但我仍然无法弄清楚如何正确使用它们。
有几个关于 Rust 和板条箱的问题:
我看到
stm32l1xx-hal
依赖于stm32l1
。我是否需要在我的Cargo.toml
文件中添加两者作为依赖项?还是会产生与所有权相关的问题?这是添加它们的正确方法吗?为什么第二个加成那样
[dependencies.stm32l1]
?[dependencies] cortex-m-rt = "0.6.10" cortex-m-semihosting = "0.3.3" panic-halt = "0.2.0" stm32l1xx-hal = "0.1.0" [dependencies.stm32l1] version = "0.13.0" features = ["stm32l151", "rt"]
要闪烁 LD4(连接到
PB4PB6),我必须在 RCC 寄存器中启用 GPIOB,然后配置引脚推拉输出。通过检查stm32l1xx-hal
的文档,我发现有一个 RCC struct and a PB4 struct 方法into_push_pull_output
。但是,我仍然不明白如何使用这些结构:如何导入它们或如何获取它们的实例。
我看过 stm32l1
的代码示例,但没有看过 stm32l1xx-hal
的代码示例。我知道我可以做到:
use stm32l1::{stm32l151};
...
let p = stm32l151::Peripherals::take().unwrap();
p.RCC.ahbenr.modify(|_,w| w.gpiopben().set_bit());
但在 stm32l1xx-hal
的源代码中,我看到 RCC 部分已经在 impl GpioExt for $GPIOX
中完成,但我不知道如何获得此“部分”功能。
感谢任何为我指明正确方向的帮助。
我从 Discord 社区得到了一些帮助。答案是(我稍微修改了一下):
就足够了stm32l1xx-hal
已经依赖于stm32l1
作为 seen here。无需导入两次。添加到 Cargo.toml:[dependencies.stm32l1xx-hal] version = "0.1.0" default-features = false features = ["stm32l151", "rt"]
- 请注意
default-features = false
是可选的,但没有它编译器会给我一个错误。
语法是等价的,但是正如我上面所说,我只需要添加一个HAL。可以在第一个样式中加花括号
{}
来添加选项,如:stm32l1xx-hal = { version = "0.1.0", features = ["stm32l151", "rt"]}
执行眨眼的正确代码(在 PB6 上,而不是 PB4,唉)是:
#![no_main] #![no_std] use panic_halt as _; use cortex_m_rt::entry; use stm32l1xx_hal::delay::Delay; use stm32l1xx_hal::gpio::GpioExt; use stm32l1xx_hal::hal::digital::v2::OutputPin; use stm32l1xx_hal::rcc::{Config, RccExt}; use stm32l1xx_hal::stm32::Peripherals; use stm32l1xx_hal::stm32::CorePeripherals; use stm32l1xx_hal::time::MicroSeconds; #[entry] fn main() -> ! { let p = Peripherals::take().unwrap(); let cp = CorePeripherals::take().unwrap(); // Get LED pin PB6 let gpiob = p.GPIOB.split(); let mut led = gpiob.pb6.into_push_pull_output(); // Set up a delay let rcc = p.RCC.freeze(Config::default()); let mut delay = Delay::new(cp.SYST, rcc.clocks); loop { // Turn LED On led.set_high().unwrap(); delay.delay(MicroSeconds(1_000_000_u32)); // Turn LED Off led.set_low().unwrap(); delay.delay(MicroSeconds(1_000_000_u32)); } }
- 对我来说,关键是要了解可以从
Peripherals
调用split
方法,因为stm32l1xx-hal
为split
中定义的结构实现了split
14=]。换句话说,HAL crate 不仅定义了新的结构,而且还扩展了现有结构的功能。我需要全神贯注于特征设计模式。