如何使用 gdb 在目标 ARM MCU 上调试闪存程序

How to debug a flash program on target ARM MCU with gdb

我正在尝试使用 gdb

在目标 MCU 上调试 ARM 闪存程序

我正在使用 jlinkgdbserver 在目标系统 (cortex-m7) 上设置 gdbserver。我有一个准备调试的小精灵。

我第一次用下面的debug就OK了

> arm-none-eabi-gdb flash_program.elf
(gdb)> target remote localhost:2331     # connect to gdb server on target
(gdb)> load                             # since it is a flash program, jlink will flash the program
                                        # target is reset to elf entry point
(gdb)> .... (debugging begins)

但是调试到某个地方,又想从入口点调试,我想的办法是再刷一次

(gdb)> Ctrl+D               # disconnect the gdbserver
> arm-none-eabi-gdb flash_program.elf
(gdb)> target remote localhost:2331
(gdb)> load
(gdb)> .... (debugging from start again)

所以这似乎有点多余,而且它一遍又一遍地擦除和编程同一个闪存区域,我担心我最终会通过调试损坏存储。

flash程序已经烧录到介质中了,我只是想让target自己复位,然后运行从入口点重新开始。但是我尝试了 monitor resetrun 之类的东西。但是目标M7都无法从头开始。

还有其他我可以尝试的 gdb 命令吗?

我使用 STM32F103C8T6 来提供答案,但您只需将其 ROM 基地址 (0x20000000) 替换为您的 Cortex-M7 使用的地址即可:在我的例子中,我从 0x20000000 加载堆栈指针的初始值,从 0x20000000+4.

加载程序计数器的初始值

要调试的程序是 stm32f103c8t6.elf,已经刷写并且确实包含调试符号。

arm-none-eabi-gdb

target remote localhost:2331
0x20000480 in ?? ()
(gdb) monitor halt
(gdb) monitor reset 0
Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
(gdb) monitor reset 1
Resets the core only, not peripherals.
(gdb) monitor reset 2
Resets core & peripherals using RESET pin.
(gdb) symbol-file stm32f103c8t6.elf
Reading symbols from stm32f103c8t6.elf...
(gdb) set $sp = *0x20000000
(gdb) set $pc = *0x20000004
(gdb) stepi
0x200003c2      121     {
(gdb)
0x200003c4      121     {
(gdb) stepi
122       SystemInit();                             /* CMSIS System Initialization */
(gdb)
SystemInit () at /opt/arm/ARM.CMSIS.5.6.0//Device/ARM/ARMCM3/Source/system_ARMCM3.c:61
61      {
(gdb)

根据您要使用的重置策略类型,您可能必须在 monitor reset 命令中明确说明:

如 Segger 文档和 this great article 中所述,您可以使用策略编号 0、1 或 2:

# Normal
monitor reset
monitor reset 0

# Core
monitor reset 1

# ResetPin
monitor reset 2

我的理解是,能否使用策略 #2 取决于您的 RESET 引脚的接线方式,即它是否被下拉或未在您的板上。

免责声明:我是软件人,所有硬件相关问题的解释错误都是我的...

gdb 命令 load 将刷新映像,前提是您没有专门设置 link 地址。 你有两个生存选择:

  1. 设置link地址/调整linker脚本,这样程序就完全在RAM中了。或者
  2. 保持地址不变,但每次代码更改和编译后,只使用加载一次(使闪存被编程),然后再使用symbol-file 命令只加载符号。