如何使用 gdb 在目标 ARM MCU 上调试闪存程序
Posted
技术标签:
【中文标题】如何使用 gdb 在目标 ARM MCU 上调试闪存程序【英文标题】:How to debug a flash program on target ARM MCU with gdb 【发布时间】:2021-04-24 22:09:00 【问题描述】:我正在尝试使用 gdb
在目标 MCU 上调试 ARM 闪存程序
我正在使用jlinkgdbserver
在目标系统 (cortex-m7) 上设置 gdbserver。我已经准备好调试精灵了。
第一次用下面的方法调试就可以了
> 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 程序已经烧录到介质中,我只是想让目标重新设置自己并再次从入口点运行。但我尝试了monitor reset
和run
之类的东西。但是目标M7不能从头再来。
还有其他的 gdb 命令可以尝试吗?
【问题讨论】:
您使用的 Cortex-M7 的品牌/型号是什么?这将有助于为您提供准确的答案。 【参考方案1】:我使用 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 引脚的接线方式,即它是否在您的板上被下拉。
免责声明:我是一个软件人,所有与硬件相关的问题的解释错误都是我的......
【讨论】:
@Eric Sun:答案是否足够清楚,还是需要改进?谢谢。 感谢您的回答,我了解到您正在从 ROM 启动检索初始 SP 和 PC,并让代码再次从启动运行。但这与HARD RESET
不同,后者会重新初始化所有寄存器和 SOC 模块。我在想是否有一些内置的 JTAG 重置命令可以实现这一点。
在这种情况下,我建议修改您的问题并使用您在评论中公开的“硬重置”注意事项来扩充But the target M7 both can't start from beginning again.
。您可以通过发出“类型 2”复位来实现您的目标,如 this article 中所述,当然还有 JLink 文档的相应部分,具体取决于您的复位信号的连接方式。
我相应地扩充了我的答案,我认为它现在应该回答你的问题了。【参考方案2】:
gdb 命令load 将刷新图像,前提是您没有专门设置链接地址。 你有两种生存方式:
-
设置链接地址/调整链接描述文件,使程序完全在RAM中。或者
保持地址不变,但每次代码更改和编译后,只使用一次load(以使闪存被编程),然后使用symbol-file 仅加载符号的命令。
【讨论】:
以上是关于如何使用 gdb 在目标 ARM MCU 上调试闪存程序的主要内容,如果未能解决你的问题,请参考以下文章
嵌入式arm linux环境中gdb+gdbserver调试
使用 Infineon XMC4800 MCU 和 Segger 进行 GDB 调试中断而无断点