使用 openocd 调试 STM32F103

背景

AWTK 在 STM32 上运行时,默认是使用的 Keil 管理工程。一般买开发板时,厂家提供的都是 keil 工程,移植起来比较方便,上手简单,但是后续维护比较麻烦:

  • AWTK 经常增加新的文件(比如新控件),同步到 keil 很麻烦,每个工程都要修改,文档也需要同步更新。

  • AWTK 的注释是中文,为了保证每个编译器都能正常编译,AWTK 源文件一般使用 UTF-8 With BOM 的编码。如果用 Keil 修改了代码,保存后它把 BOM 给去掉了,之后还得用其它工具把 BOM 加回去。

另外,我个人也不太喜欢在 Windows 下工作。一直希望用 gcc 来编译,用 gdb 来调试。以前尝试过,没有成功。最近看 rust-embedded,发现可以用 openocd 来调试,亲测可以使用。

我手上有块 stm32f103ze 板子,和 rust-embedded 提供的例子有些不同,需要做些改进。这里先做个笔记,供以后改造 AWTK 编译脚本时使用。

1. 安装相关软件包

Mac 下的安装方法如下:

# Rust
brew install rust

# GDB
brew install armmbed/formulae/arm-none-eabi-gcc

# OpenOCD
brew install openocd

# QEMU
brew install qemu

安装之后需要把 cargo 的 bin 目录加入到环境变量 PATH 中。

export PATH="$HOME/.cargo/bin:$PATH""
error[E0463]: can't find crate for `core`
  |
  = note: the `thumbv7m-none-eabi` target may not be installed

安装 cargo-generate

cargo install cargo-generate

2. 生成一个 rust 工程

运行下列命令,项目名输入 app

cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart

进入 app

cd app

3. 修改配置

设置 target,STM32F103 使用的是 thumbv7m-none-eabi

rustup target add thumbv7m-none-eabi

4. 修改 memory.x

MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  /* TODO Adjust these memory regions to match your device memory layout */
  /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */
  FLASH : ORIGIN = 0x00000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 64K
}

stm32f103ze 的 flash 的地址是 0x8000000,大小是 512K,改成如下内容:

MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  /* TODO Adjust these memory regions to match your device memory layout */
  /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */
  FLASH : ORIGIN = 0x8000000, LENGTH = 512K
  RAM : ORIGIN = 0x20000000, LENGTH = 64K
}

5. 编译

cargo build

文档中,提供的几个命令,用来查看生成的可执行文件,貌似不能用:

cargo readobj --bin app -- -file-headers

提示错误:

Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Failed to execute tool: readobj

可以直接使用 arm-none-eabi-xxx 命令代替吧:

arm-none-eabi-readelf -h target/thumbv7m-none-eabi/debug/app

我们可以看看代码的位置和大小(主要是确认是否和 memory.x 一致)

arm-none-eabi-size -A -x target/thumbv7m-none-eabi/debug/app

输出:

target/thumbv7m-none-eabi/debug/app  :
section              size         addr
.vector_table       0x400    0x8000000
.text               0x558    0x8000400
.rodata             0x138    0x8000958
.data                 0x0   0x20000000
.bss                  0x0   0x20000000
.uninit               0x0   0x20000000
.debug_abbrev      0x1432          0x0
.debug_info       0x21e99          0x0
.debug_aranges     0x1ca0          0x0
.debug_ranges     0x17f30          0x0
.debug_str        0x2b41f          0x0
.debug_pubnames    0x9800          0x0
.debug_pubtypes     0xad8          0x0
.ARM.attributes      0x32          0x0
.debug_frame       0x5b5c          0x0
.debug_line       0x2643b          0x0
.debug_loc          0x17e          0x0
.comment             0x6d          0x0
Total             0x9f1d6

6. 调试

修改 openocd.cfg

原来内容如下:

# Sample OpenOCD configuration for the STM32F3DISCOVERY development board

# Depending on the hardware revision you got you'll have to pick ONE of these
# interfaces. At any time only one interface should be commented out.

# Revision C (newer revision)
source [find interface/stlink-v2-1.cfg]

# Revision A and B (older revisions)
# source [find interface/stlink-v2.cfg]

source [find target/stm32f3x.cfg]

因为我用的是 jlink,所以改成如下内容:

# Sample OpenOCD configuration for the STM32F3DISCOVERY development board

# Depending on the hardware revision you got you'll have to pick ONE of these
# interfaces. At any time only one interface should be commented out.

# Revision C (newer revision)
source [find interface/jlink.cfg]

source [find target/stm32f3x.cfg]

启动 openocd

正常输出如下,提示监听 3333 端口:

Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V9 compiled Dec 30 2018 15:35:20
Info : Hardware version: 9.20
Info : VTarget = 3.229 V
Info : clock speed 1000 kHz
Info : JTAG tap: stm32f3x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x3)
Warn : JTAG tap: stm32f3x.cpu       UNEXPECTED: 0x3ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x3)
Error: JTAG tap: stm32f3x.cpu  expected 1 of 1: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: stm32f3x.bs tap/device found: 0x06414041 (mfg: 0x020 (STMicroelectronics), part: 0x6414, ver: 0x0)
Error: Trying to use configured scan chain anyway...
Warn : Bypassing JTAG setup events due to errors
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f3x.cpu on 3333
Info : Listening on port 3333 for gdb connections

启动 gdb。项目目录下的 openocd.gdb 中有些初始化命令,可以直接使用,免得手工输入。

arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/app -x openocd.gdb

后续的调试方法就和 gdb 一样了。

05-30 00:45