[原创] 使用rust创建嵌入式项目

bigbat   2022-6-25 17:54 楼主

rust用于嵌入式开发,这个网上有一些文章,但是大部分都是使用一些现成的项目。这次我将从零开始建立一个独立的项目。本次使用的是STM32F103CBT6的芯片。项目的目标就是点亮LED

首先是安装rust环境了,开发工具我选择vscode,仿真使用ST Link V2.1,

第一:设置rust环境

1、rustup update

2、rustup target install thumbv7m-none-eabi

3、cargo install cargo-flash

这个工具是可以直接烧写flash的。

第二:建立项目

1、cargo init rusty-blink

使用cargo建立项目,项目名称<rust-blink>

2、在.cargo目录下新建config文件,.cargo/config

# .cargo/config
[build]
# Always compile for the instruction set of the STM32F1
target = "thumbv7m-none-eabi"

# use the Tlink.x scrip from the cortex-m-rt crate
rustflags = [ "-C", "link-arg=-Tlink.x"]

3、在项目的目录建立memory.x文件

/* memory.x - Linker script for the STM32F103C8T6 */
MEMORY
{
  /* Flash memory begins at 0x80000000 and has a size of 64kB*/
  FLASH : ORIGIN = 0x08000000, LENGTH = 64K
  /* RAM begins at 0x20000000 and has a size of 20kB*/
  RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

4、修改Cargo.toml文件,项目根目录

# Cargo.toml
[package]
edition = "2018"
name = "blinky-rust"
version = "0.1.0"

[profile.release]
opt-level = 'z' # turn on maximum optimizations. We only have 64kB
lto = true      # Link-time-optimizations for further size reduction

[dependencies]
cortex-m = "^0.6.3"      # Access to the generic ARM peripherals
cortex-m-rt = "^0.6.12"  # Startup code for the ARM Core
embedded-hal = "^0.2.4"  # Access to generic embedded functions (`set_high`)
panic-halt = "^0.2.0"    # Panic handler

# Access to the stm32f103 HAL.
[dependencies.stm32f1xx-hal]
# Bluepill contains a 64kB flash variant which is called "medium density"
features = ["stm32f103", "rt", "medium"]
version = "^0.7.0"

项目中使用了stm32f1xx-hal这个Rust项目,该项目目前的版本为0.9.0,如果想使用新版修改Cargo.toml文件就可以了,

5、修改main.rs文件

// src/main.rs

// std and main are not available for bare metal software
#![no_std]
#![no_main]

use cortex_m_rt::entry; // The runtime
use embedded_hal::digital::v2::OutputPin; // the `set_high/low`function
use stm32f1xx_hal::{delay::Delay, pac, prelude::*}; // STM32F1 specific functions
#[allow(unused_imports)]
use panic_halt; // When a panic occurs, stop the microcontroller

// This marks the entrypoint of our application. The cortex_m_rt creates some
// startup code before this, but we don't need to worry about this
#[entry]
fn main() -> ! {
    // Get handles to the hardware objects. These functions can only be called
    // once, so that the borrowchecker can ensure you don't reconfigure
    // something by accident.
    let dp = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

    // GPIO pins on the STM32F1 must be driven by the APB2 peripheral clock.
    // This must be enabled first. The HAL provides some abstractions for
    // us: First get a handle to the RCC peripheral:
    let mut rcc = dp.RCC.constrain();
    // Now we have access to the RCC's registers. The GPIOC can be enabled in
    // RCC_APB2ENR (Prog. Ref. Manual 8.3.7), therefore we must pass this
    // register to the `split` function.
    let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
    // This gives us an exclusive handle to the GPIOC peripheral. To get the
    // handle to a single pin, we need to configure the pin first. Pin C13
    // is usually connected to the Bluepills onboard LED.
    let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);

    // Now we need a delay object. The delay is of course depending on the clock
    // frequency of the microcontroller, so we need to fix the frequency
    // first. The system frequency is set via the FLASH_ACR register, so we
    // need to get a handle to the FLASH peripheral first:
    let mut flash = dp.FLASH.constrain();
    // Now we can set the controllers frequency to 8 MHz:
    let clocks = rcc.cfgr.sysclk(8.mhz()).freeze(&mut flash.acr);
    // The `clocks` handle ensures that the clocks are now configured and gives
    // the `Delay::new` function access to the configured frequency. With
    // this information it can later calculate how many cycles it has to
    // wait. The function also consumes the System Timer peripheral, so that no
    // other function can access it. Otherwise the timer could be reset during a
    // delay.
    let mut delay = Delay::new(cp.SYST, clocks);

    // Now, enjoy the lightshow!
    loop {
        led.set_high().ok();
        delay.delay_ms(1_000_u16);
        led.set_low().ok();
        delay.delay_ms(1_000_u16);
    }
}

到此步骤,整个项目就完成了,程序

let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);

这两句可以定义成你自己的引脚。

编译程序 cargo build --release

如果顺利将获得一个带调试的目标文件,但是这个文件是不能用的,需要转换成bin文件

arm-none-eabi-objcopy -O binary target/thumbv7m-none-eabi/release/blinky-rust blinky-rust.bin

烧写文件到板子。

cargo flash --chip stm32f103C8 --release

整个操作完成,可以看到板子开始闪亮。

 

 

 

回复评论 (2)

rust也能玩转单片机,第一次接触,谢谢楼主分享!
点赞  2022-6-25 23:50

怎么调试呢?

默认摸鱼,再摸鱼。2022、9、28
点赞  2022-6-29 20:21
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复