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
整个操作完成,可以看到板子开始闪亮。