OpenOCD
OpenOCD是一款开源的针对嵌入式设备的调试器,可以用来烧录、调试很多嵌入式设备。
安装
在mac上面安装OpenOCD非常简单,使用brew
安装就好。需要注意的是,brew
里面默认的版本比较老旧,在安装时最好使用:
|
|
在Windows上面安装则更为简单:去OpenOCD的Github的Release页面下载最新版本的OpenOCD安装文件即可。
OpenOCD入门
OpenOCD内置了对很多MCU和开发板的支持,这些都可以去${安装目录}/share/openocd/scripts
下获取。一般来说,只需要在interface
文件夹下面找到你使用的debugger,然后在board
文件夹下面找到你所使用的板子或者在target
目录下找到你使用的MCU,即可以不做任何改动,直接使用OpenOCD进行烧录和调试:
|
|
这是默认选项,也是大多数人的用法。不过在这里,如果我们想要对OpenOCD的烧录、调试选项做更加深入细致地定制的话,就必须熟悉OpenOCD的配置文件,也就是-f
选项后面的文件。OpenOCD自带的这些文件是很好的参考,后面我们也会参考这些文件,针对我们自己的板子写出对应的配置文件。
OpenOCD的配置文件
OK,到现在为止我们已经入门了OpenOCD,现在就进一步学习OpenOCD的配置文件。默认情况下(即不使用-f
指定配置文件时),OpenOCD会使用当前目录下的openocd.cfg
文件作为配置文件。
在写我们自己的配置文件时,我们仍然可以复用scripts
目录下的配置文件,像这样:
# 引用stlink.cfg
source [find interface/stlink.cfg]
大多数情况下,你所使用的debugger的配置文件都会随OpenOCD提供,引用即可。
下面,针对我们使用的debugger,需要去指定通信类型。比如,对于stlink,我们使用hla_swd
:
# Choose transport interfance
transport select hla_swd
或者对于cmsis-dap
,我们使用swd
:
source [find interface/cmsis-dap.cfg]
transport select swd
再然后,就可以看一下我们使用的MCU是否在targets里面了。绝大多数情况下,是在的,那么我们可能需要进行一些些的配置。比如,指定芯片名称:
set CHIPNAME stm32h7x
再比如,打开octo-spi的开关:
# Enable stmqspi
if {![info exists OCTOSPI1]} {
set OCTOSPI1 1
set OCTOSPI2 0
}
然后直接引用对应的内置配置文件即可:
# Use built-in stm32h7 openocd configs
source [find target/stm32h7x.cfg]
source [find board/stm32h7x_dual_qspi.cfg]
这里,由于我们已经事先看了这两个文件,知道打开octo-spi要把OCTOSPI1
配置为1。对于不同的MCU,最好去看一下对应target
下的配置文件,这样你就能够知道可以配置哪些东西,需要配置哪些东西。
OpenOCD提供了非常非常多的配置选项,其内置的各种target的选项就是非常好的参考。如果发现有命令不太明白,可以去官方文档查询。当你能够看明白一个MCU的完整的配置文件,那么相信自己写一写也不在话下了。
OpenOCD的命令
在写完配置文件之后,我们就可以使用OpenOCD进行实际的调试了。在调试之前,我们需要学习一下最常用的OpenOCD的命令,这些命令在调试中都非常常用。
-
halt:暂停CPU运行,在执行烧录命令之前必须先halt,否则CPU不会理你的
-
flash:flash实际上包含很多子命令,常用的有
flash info
,flash list
,falsh banks
,flash write_image
,flash verify_image
等。具体用法参见官方手册- flash write_image erase [filename] [address]:烧录指定文件到对应地址。对于stm32h7,如果烧录elf文件,不需要加地址。而如果烧录bin文件,则需要加地址:
flash write_image erase build/h7b0.bin 0x08000000 # 或者 flash write_image erase build/h7b0.elf
-
reset:复位
-
init:初始化MCU
-
reset halt:复位并且立刻暂停CPU
-
mdx(mdd/mdw/mdh/mdb):显示对应地址的数据(memory display),mdd是64bit,mdw是32bit,mdh是16bit,mdb是8bit
-
mwx(mwd/mww/mwh/mwb):往对应地址写入,各个命令和上面类似
-
program: OpenOCD提供了program命令,相当于是flash命令的高级封装。可以直接使用如下一条命令,完成初始化、停止、烧录、重启、退出等一系列命令可以完成的事情:
1 2 3 4 5 6 7 8 9
# 一条命令完成烧写 program build/h7b0.elf verify reset exit # 下面一堆命令也一样 init halt flash write_image erase build/h7b0.elf reset shutdown
stmqspi
OpenOCD支持stm32系列MCU的qual-spi和octo-spi,可以使用spi把外部flash映射到内部的地址空间,这些flash可以自动地被OpenOCD检测到。在这种模式下,MCU可以直接读取对应的内存,执行flash里面的代码。不过需要注意的是,MCU不能直接从外置flash区域启动。因此,在具体的实现代码里面,必须在内置flash区(或者说boot代码里面),配置好qspi或者ospi的memory mapping。这样OpenOCD才能使用地址映射去操作这部分内存。下面是测试命令:
|
|
可以看到,OpenOCD甚至连外部flash的芯片型号(w25q64)都能都读取到。除了list
和info
命令外,还可以使用banks
和probe
命令:
这里需要注意的是,在OpenOCD进行烧录的时候,通常不会启动芯片。因此对于外置SPI Flash,一般还需要通过手动写寄存器的方式来进行时钟的初始化和SPI外设的初始化。这样才能让OpenOCD正确地识别到目标芯片。如果你使用的芯片在OpenOCD已经内置,那么一般可以直接使用,直接source
即可。如果没有内置或者你有自己的设置(比如SPI GPIO配置不同),那么就需要自己写了。下面是一个例子:
|
|
OpenOCD官方有提供根据你的Pin的配置自动生成SPI GPIO配置的工具,在官方库的gpio_gen.pl
文件中,需要perl执行。这样就不用对照着手册一个一个地自己去算寄存器的值了,非常的方便。