分享使用Rust学习stm32的日志-1

本人第一次编写文章,文章会有所垃圾,如果有什么问题望指正

设备介绍

电脑

  • 拯救者r7000笔记本

系统

  • Archlinux

使用设备

  • stm32f103c8t6最小系统板
  • PWLINK2 Lite烧录器,使用cmsis-dap

软件安装

OpenOCD

OpenOCD(Open On-Chip Debugger)开源片上调试器,是一款开源软件,最初是由Dominic Rath同学还在大学期间发起的(2005年)项目。OpenOCD旨在提供针对嵌入式设备的调试、系统编程和边界扫描功能 (源于知乎)
安装

sudo pacman -S arm-none-eabi-gdb qemu-arch-extra openocd

添加udev规则

以下内容源于The Embedded Rust Book , stm32f1xx-hal
这个规则可以让你在不使用超级用户权限的情况下,使用OpenOCD和Discovery开发板

某些Linux发行版可能并不需要这一步,比如我的,你可以先不做这一步操作

生成包含下列内容的 /etc/udev/rules.d/70-st-link.rules 文件

# STM32F3DISCOVERY rev A/B - ST-LINK/V2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", TAG+="uaccess"

# STM32F3DISCOVERY rev C+ - ST-LINK/V2-1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", TAG+="uaccess"

这里设置的是ST-LINK烧录器,根据具体设备配置,相应可以Google一下
重载所有udev规则

sudo udevadm control --reload-rules

插上烧录器,运行这个命令查看usb设备

lsusb 

如果找不到命令,执行下面命令

sudo  pacman -S usbtils

你可能会看到输出

...
Bus 003 Device 003: ID 0d28:0204 NXP ARM mbed
...

这个是我的烧录器,如果不知道哪个的话,可以拔插查看具体是哪一个设备,如果你使用JLink或者STLink应该名字会很明显

记住bus和device号,使用这些数字组合成一个像是 /dev/bus/usb/<bus>/<device> 这样的路径。然后像这样使用这个路径:

getfacl /dev/bus/usb/003/003 | grep user

输出

user::rw-
user:<username>:rw-

如果在没添加udev规则时,username是你当前用户名,那么就不需要添加udev规则,如果没有,请检查udev规则是否添加,是否正确,是否生效

环境配置

确保你已经安装Rust
如果未安装运行下面命令进行安装

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

由于stm32f103c8t6的架构是ARM Cortex-M3,所以需要添加交叉编译工具链

rustup target add thumbv7m-none-eabi

cargo-binutils

cargo-binutils是一个Cargo命令的子集,它让我们能轻松使用Rust工具链带来的LLVM工具。这些工具包括LLVM版本的objdump,nm和size,用来查看二进制文件。
在GNU binutils之上使用这些工具的好处是

  • (a)无论你的操作系统是什么,安装这些LLVM工具都可以用同一条命令(rustup component add llvm-tools-preview)。
  • (b)像是objdump这样的工具,支持所有rustc支持的架构–从ARM到x86_64–因为它们都有一样的LLVM后端
    输入下面命令安装
    cargo install cargo-binutils
    rustup component add llvm-tools-preview

    环境验证

    我们已经搭建好环境了,接下来我们检验一下是否可以正常进行开发
    我们主要要的库
  • stm32f1xx-hal STM32F1系列微控制器的HAL
  • cortex-m 提供cortex-m的底层接口
  • cortex-m-rt 提供运行时
    输入下面命令新建一个基础库
    cargo new base
    cd base
    编辑Cargo.toml,直接参考stm32f1xx-hal的github
    [package]
    name = "base"
    version = "0.1.0"
    edition = "2021"
    [dependencies]
    embedded-hal = "0.2.7"
    nb = "1"
    cortex-m = "0.7.6"
    cortex-m-rt = "0.7.1"
    cortex-m-semihosting = "0.5.0"
    panic-halt = "0.2.0"
    [dependencies.stm32f1xx-hal]
    version = "0.10.0"
    features = ["rt", "stm32f103", "medium"]
    项目目录新建文件与文件夹
    mkdir .cargo
    touch .cargo/config
    touch openocd.cfg
    touch openocd.gdb
    touch memory.x
    编辑openocd.gdb
    target remote :3333
    break main
    monitor arm semihosting enable
    load
    stepi
    第一行是连接烧录器调试的命令,第二行在main函数设置断点,第三行是启用单片机的semihosting,可以使单片机打印信息回到电脑终端,第四行将程序烧录至单片机,第四行会启动进程但会立即停止处理器
    编辑openocd.cfg,这是openocd的启动配置文件
    source [find interface/cmsis-dap.cfg]
    source [find target/stm32f1x.cfg]
    一个是烧录器的配置,另一个是目标芯片的配置,你可以从这里找到你所使用的烧录器与目标芯片配置
    编辑.cargo/config
    [target.thumbv7m-none-eabi]
    runner = 'arm-none-eabi-gdb -x openocd.gdb'
    rustflags = [
    "-C", "link-arg=-Tlink.x",
    ]
    [build]
    target = "thumbv7m-none-eabi"
    runner 定义你使用cargo run使用的命令,rustflags指定编译器编译时的参数选项,并不需要太多关心,target指定我们使用的编译工具链

编辑memory.x

MEMORY
{
  FLASH : ORIGIN = 0x08000000, LENGTH = 64K
  RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

设置存储区区信息,根据所使用的芯片设置,国产的芯片可能与ST官方有所不同

第一个程序

编写src/main.rs

#![no_std]
#![no_main]

use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
use panic_halt as _;
use stm32f1xx_hal; // 目前没啥用,但是必须引入

// 入口
#[entry]
fn main() -> ! {
    loop {
        hprintln!("Hello World!");
        hprintln!("Hello Rust!");
    }
}

#![no_std]意味并不需要使用标准库,转而使用core,有兴趣可以去了解一下
#![no_main]意味并不使用标准入口函数main

cortex_m_rt::entry 引入运行时的入口
cortex_m_semihosting::hprintln 引入hprintln,我们需要使用它向控制台打印信息
panic_hale 我们并不希望恐慌,所以使用use panic_halt as _,表示忽略它
stm32f1xx_hal必须引入,需要实现embedded-hal,否则编译时会报找不到函数定义等错误

#[entry] 定义入口,函数名可以不为main,-> !意味这此无返回值
然后开始循环打印

开启一个新终端,在项目目录运行下面命令,确保你已经编写openocd.cfg

openocd

否则

openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg

不要关闭运行着openocd的终端,在原来项目目录运行

cargo  run

根据下面输入命令

(gdb) continue
Continuing.

Breakpoint 1, base::__cortex_m_rt_main_trampoline () at src/main.rs:10
10    #[entry]
(gdb) 
Continuing.

第一输入continue,然后直接回车
openocd那边就会有输出了

...
Hello World!
Hello Rust!
Hello World!
Hello Rust!
...

退出gdbgdb控制台输入quit

关于gdb使用可以自行网络搜寻
关于使用Rust嵌入式开发的总览

参考

跟我一起学OpenOCD(一) 知乎
The Embedded Rust Book 电子书
stm32f1xx_hal Github

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!