将 Rust crates 用于 STM32 微控制器板

问题描述

我目前正在尝试学习 Rust(专门用于嵌入式),来自嵌入式系统和 Python 的 C 背景。 到目前为止,我一直在阅读 Rust Programming LanguageRust for Embedded,并在网上阅读了一些博客文章

我希望我的第一个项目是一个简单的“Blinky”,其中 LED 无限闪烁。我有一块带有 stm32l152 芯片的 stm32l152CdisCOVERY 板(与 STM32L151 基本相同),它是 Cortex M3。

我想利用现有的 crate 和 HAL,而不是从头开始实施所有内容。我发现了两个看起来很有希望的:stm32l1stm32l1xx-hal。我已经尝试阅读每个文档的文档以及部分源代码,但我仍然无法弄清楚如何正确使用它们。

有几个关于 Rust 和板条箱的问题:

  1. 我发现 stm32l1xx-hal 依赖于 stm32l1。我是否需要将两者都添加为我的 Cargo.toml 文件中的依赖项?还是会造成与所有权相关的问题?

  2. 这是添加它们的正确方法吗?为什么第二个是这样添加[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"]
    
    
  3. 要使 LD4(连接到 PB4 PB6)闪烁,我必须启用 RCC 寄存器中的 GPIOB,然后将引脚配置为推挽输出。通过检查 stm32l1xx-hal 的文档,我发现有一个 RCC struct一个 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 社区获得了一些帮助。答案是(由我修改了一点):

  1. stm32l1xx-hal 已经依赖于 stm32l1 作为 seen here。没有必要导入两次。添加到 Cargo.toml 就足够了:

    [dependencies.stm32l1xx-hal]
    version = "0.1.0"
    default-features = false
    features = ["stm32l151","rt"]
    
    
  • 请注意,default-features = false 是可选的,但如果没有它,编译器就会给我一个错误。
  1. 语法是等价的,但正如我上面所说的,我只需要添加 HAL 一个。您可以在第一个样式中添加花括号{}来添加选项,例如:

    stm32l1xx-hal = { version = "0.1.0",features = ["stm32l151","rt"]}
    
    
  2. 进行闪烁的正确代码是:

    #![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));
        }
    }
    
    
  • 对我来说,关键是要了解可以从 split 调用 Peripherals 方法,因为 stm32l1xx-hal 为 {{1} 中定义的结构实现了 split }.换句话说,HAL crate 不仅定义了新结构,而且还扩展了现有结构的功能。我需要围绕 trait 设计模式。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...