eclipse STM32 GDB/OpenOCD 命令和 Flash 和 Ram 调试的初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5535110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 20:06:22  来源:igfitidea点击:

STM32 GDB/OpenOCD Commands and Initialization for Flash and Ram Debugging

eclipsedebugginggdbstm32openocd

提问by user690605

I am looking for assistance with the proper GDB / OpenOCD initializion and run commands (external tools) to use within Eclipse for flash and ram debugging, as well as the proper modifications or additions that need to be incorporated in a make file for flash vs ram building for this mcu, if this matters of course.

我正在寻求有关正确 GDB / OpenOCD 初始化和运行命令(外部工具)的帮助,以便在 Eclipse 中使用以进行闪存和 ram 调试,以及需要合并到闪存与 ram 的 make 文件中的适当修改或添加为这个 MCU 构建,如果这当然重要的话。

mcu: STM32F103VET6

单片机:STM32F103VET6

I am using Eclipse Helios with Zylin Embedded CDT, Yagarto Tools and Bins, OpenOCD .4, and have an Olimex ARM-USB-OCD Jtag adapter.

我将 Eclipse Helios 与 Zylin Embedded CDT、Yagarto Tools and Bins、OpenOCD .4 一起使用,并且有一个 Olimex ARM-USB-OCD Jtag 适配器。

I have already configured the ARM-USB-OCD and added it as an external tool in Eclipse. For initializing OpenOCD I used the following command in Eclipse. The board config file references the stm32 mcu:

我已经配置了 ARM-USB-OCD 并将其添加为 Eclipse 中的外部工具。为了初始化 OpenOCD,我在 Eclipse 中使用了以下命令。电路板配置文件引用了 stm32 mcu:

"openocd -f interface/olimex-arm-usb-ocd-h.cfg -f board/stm32f10x_128k_eval.cfg"

“openocd -f 接口/olimex-arm-usb-ocd-h.cfg -f 板/stm32f10x_128k_eval.cfg”

When I run this within Eclipse everything appears to be working (GDB Interface, OpenOCD finds the mcu, etc) . I can also telnet into OpenOCD and run commands. So, I am stuck on the next part; initialization and commands for flash and ram debugging , as well as erasing flash.

当我在 Eclipse 中运行它时,一切似乎都在工作(GDB 接口,OpenOCD 找到了 mcu 等)。我还可以远程登录到 OpenOCD 并运行命令。所以,我被困在下一部分;flash 和 ram 调试的初始化和命令,以及擦除 flash。

I read through several tutorials, and scoured the net, but have not been able to find anything particular to this processor. I am new to this, so I might not be recognizing an equivent product for an example.

我通读了几个教程,并在网上搜索,但未能找到任何与该处理器有关的内容。我对此很陌生,因此我可能无法识别等效产品作为示例。

JimT

吉姆

回答by spade78

I'm working with the same tool chain to program and debug a STM32F107 board. Following are my observations to get an STM32Fxxx chip programmed and debugged under this toolchain.

我正在使用相同的工具链来编程和调试 STM32F107 板。以下是我在此工具链下对 STM32Fxxx 芯片进行编程和调试的观察结果。



Initial Starting Point

初始起点

So at this point you've got a working OpenOCD to ARM-USB-OCD connection and so you should be all set on that end. Now the work is on getting Eclipse/Zylin/Yagarto GDB combination to properly talk to the STM32Fxxx through the OpenOCD/Olimex connection. One thing to keep in mind is that all the OpenOCD commands to issue are the run modecommands. The configuration scripts and command-line options to invoke the OpenOCD server are configuration modecommands. Once you issue the initcommand then the server enters run mode which opens up the set of commands you'll need next. You've probably done it somewhere else but I tack on a '-c "init"' option when I call the OpenOCD server like so:

所以在这一点上,你已经有了一个可以工作的 OpenOCD 到 ARM-USB-OCD 的连接,所以你应该在这方面做好一切准备。现在的工作是让 Eclipse/Zylin/Yagarto GDB 组合通过 OpenOCD/Olimex 连接正确地与 STM32Fxxx 通信。要记住的一件事是要发出的所有 OpenOCD 命令都是运行模式命令。调用 OpenOCD 服务器的配置脚本和命令行选项是配置模式命令。一旦您发出init命令,服务器就会进入运行模式,这会打开您接下来需要的一组命令。您可能已经在其他地方完成了它,但是当我像这样调用 OpenOCD 服务器时,我添加了一个 '-c "init"' 选项:

openocd -f /path to scripts/olimex-arm-usb-ocd-h.cfg -f /path to targets/stm32f107.cfg -c "init"

The following commands I issue next are done by the Eclipse Debug Configurationsdialogue. Under the Zylin Embedded debug (Native)section, I create a new configuration, give it a name, Project (optional), and absolute path to the binary that I want to program. Under the Debugger tab I set the debugger to Embedded GDB, point to the Yagarto GDB binary path, don'tset a GDB command file, set GDB command set to Standard, and the protocol to mi.

我接下来发出的以下命令是由 Eclipse调试配置对话框完成的。在Zylin Embedded debug (Native)部分下,我创建了一个新配置,给它一个名称、项目(可选)和我想要编程的二进制文件的绝对路径。在 Debugger 选项卡下,我将调试器设置为Embedded GDB,指向 Yagarto GDB 二进制路径,不要设置 GDB 命令文件,将 GDB 命令设置为Standard,将协议设置为mi



The Commands Tab - Connect GDB to OpenOCD

命令选项卡 - 将 GDB 连接到 OpenOCD

So the next tab is the Commandstab and that's where the meat of the issue lies. You have two spaces Initializeand Run. Not sure exactly what the difference is except to guess that they occur pre- and post-invocation of GDB. Either way I haven't noticed a difference in how my commands are run.

所以下一个选项卡是命令选项卡,这就是问题的关键所在。您有两个空格InitializeRun。除了猜测它们在 GDB 调用之前和之后发生之外,不确定到底有什么区别。无论哪种方式,我都没有注意到我的命令运行方式有什么不同。

But anyway, following the examples I found on the net, I filled the Initializebox with the following commands:

但无论如何,按照我在网上找到的示例,我用以下命令填充了Initialize框:

set remote hardware-breakpoint limit 6
set remote hardware-watchoint-limit 4
target remote localhost:3333
monitor halt
monitor poll

First two lines tell GDB how many breakpoints and watchpoints you have. Open OCD Manual Section 20.3says GDB can't query for that information so I tell it myself. Next line commands GDB to connect to the remote target at the localhost over port 3333. The last line is a monitor commandwhich tells GDB to pass the command on to the target without taking any action itself. In this case the target is OpenOCD and I'm giving it the command halt. After that I tell OpenOCD to switch to asynchronous mode of operation. As some of the following operations take a while, it's useful not to have OpenOCD block and wait for every operation.

前两行告诉 GDB 你有多少断点和观察点。打开 OCD 手册第 20.3 节说 GDB 无法查询该信息,所以我自己告诉它。下一行命令 GDB 通过端口 3333 连接到本地主机上的远程目标。最后一行是一个监视器命令,它告诉 GDB 将命令传递到目标而不采取任何行动。在这种情况下,目标是 OpenOCD,我给它命令halt。之后我告诉 OpenOCD 切换到异步操作模式。由于以下某些操作需要一段时间,因此最好不要让 OpenOCD 阻塞并等待每个操作。

Sidenote #1:If you're ever in doubt about the state of GDB or OpenOCD then you can use the Eclipse debug console to send commands to GDB or OpenOCD (via GDB monitor commands) after invoking this debug configuration.

旁注 #1:如果您对 GDB 或 OpenOCD 的状态有疑问,那么您可以在调用此调试配置后使用 Eclipse 调试控制台将命令发送到 GDB 或 OpenOCD(通过 GDB 监视器命令)。



The Commands Tab - Setting up the User Flash

命令选项卡 - 设置用户 Flash

Next are commands I give in the Runcommands section:

接下来是我在运行命令部分给出的命令:

monitor flash probe 0
monitor flash protect 0 0 127 off
monitor reset halt
monitor stm32x mass_erase 0
monitor flash write_image STM3210CTest/test_rom.elf
monitor flash protect 0 0 127 on
disconnect
target remote localhost:3333
monitor soft_reset_halt

to be explained in the following sections...

将在以下部分中解释...

Setting up Access to User Flash Memory

设置对用户闪存的访问

First I issue an OpenOCD query to see if it can find the flash module and report the proper address. If it responds that it found the flash at address 0x08000000 then we're good. The 0 at the end specifies to get information about flash bank 0.

首先,我发出一个 OpenOCD 查询以查看它是否可以找到闪存模块并报告正确的地址。如果它响应它在地址 0x08000000 找到闪存,那么我们很好。末尾的 0 指定获取有关闪存库 0 的信息。

Sidenote #2:The STM32Fxxx part-specific data sheets have a memory map in section 4. Very useful to keep on hand as you work with the chip. Also as everything is accessed as a memory address, you'll come to know this layout like the back of your hand after a little programming time!

旁注 #2:STM32Fxxx 部件特定的数据表在第 4 节中有一个存储器映射。在您使用芯片时随时掌握非常有用。此外,由于所有内容都作为内存地址访问,因此经过一些编程时间后,您会像手背一样了解这种布局!

So after confirming that the flash has been properly configured we invoke the command to turn off write protection to the flash bank. PM0075describes everything you need to know about programming the flash memory. What you need to know for this command is the flash bank, starting sector, ending sector, and whether to enable or disable write protection. The flash bank is defined in the configuration files you passed to OpenOCD and was confirmed by the previous command. Since I want to disable protection for the entire flash space I specify sectors 0 to 127. PM0075 explains how I got that number as it refers to how the flash memory is organized into 2KB pages for my (and your) device. My device has 256KB of flash so that means I have 128 pages. Your device has 512KB of flash so you'll have 256 pages. To confirm that your device's write-protection has been disabled properly, you can check the FLASH_WRPR register at address 0x40022020 using the OpenOCD command:

因此,在确认闪存已正确配置后,我们调用命令关闭闪存库的写保护。PM0075描述了您需要了解的有关闪存编程的所有信息。此命令需要了解的是闪存库、起始扇区、结束扇区以及是否启用或禁用写保护。闪存库是在您传递给 OpenOCD 的配置文件中定义的,并由上一个命令确认。因为我想禁用对整个闪存空间的保护,所以我指定了扇区 0 到 127。PM0075 解释了我是如何得到这个数字的,因为它指的是我(和您的)设备的闪存如何组织成 2KB 页面。我的设备有 256KB 的闪存,这意味着我有 128 页。您的设备有 512KB 的闪存,因此您将拥有 256 页。要确认您的设备的写保护已被正确禁用,您可以使用 OpenOCD 命令检查地址 0x40022020 处的 FLASH_WRPR 寄存器:

monitor mdw 0x40022020

The resulting word that it prints will be 0xffffffff which means all pages have their write protection disabled. 0x00000000 means all pages have write protection enabled.

它打印的结果字将是 0xffffffff,这意味着所有页面都禁用了写保护。0x00000000 表示所有页面都启用了写保护。

Sidenote #3:On the subject of the memory commands, I bricked my chip twice as I was messing with the option bytes at the block starting at address 0x1ffff800. First time I set the read protection on the flash (kind of hard to figure out what your doing if you do that), second time I set the hardware watchdog which prevented me from doing anything afterwards since the watchdog kept firing off! Fixed it by using the OpenOCD memory access commands. Moral of the story is: With great power comes great responsibility.... Oranother take is that if I shoot myself in the foot I can still fix things via JTAG.

旁注 #3:关于内存命令的主题,我把我的芯片变砖了两次,因为我在从地址 0x1ffff800 开始的块中弄乱了选项字节。第一次我在闪存上设置了读保护(如果你这样做,很难弄清楚你在做什么),第二次我设置了硬件看门狗,这阻止了我之后做任何事情,因为看门狗一直在开火!使用 OpenOCD 内存访问命令修复了它。这个故事的寓意是:能力越大,责任越大...或者另一种看法是,如果我用脚开枪,我仍然可以通过 JTAG 解决问题。

Sidenote #4:One thing that'll happen if you try to write to protected flash memory is the FLASH_SR:WRPRTERR bit will be set. OpenOCD will report a more user-friendly error message.

旁注 #4:如果您尝试写入受保护的闪存,将会发生的一件事是 FLASH_SR:WRPRTERR 位将被设置。OpenOCD 将报告更加用户友好的错误消息。

Erasing the Flash

擦除闪存

So after disabling the write protection, we need to erase the memory that you want to program. I do a mass erase which erases everything, you also have the option to erase by sector or address (I think). Either way you need to erase first before programming as the hardware checks for erasure first before allowing a write to occur. If the FLASH_SR:PGERR bit (0x4002200c) ever gets set during programming then you know you haven't erased that chunk of memory yet.

所以禁用写保护后,我们需要擦除要编程的内存。我进行了一次擦除所有内容的批量擦除,您还可以选择按扇区或地址擦除(我认为)。无论哪种方式,您都需要在编程之前先擦除,因为硬件在允许写入之前首先检查擦除。如果 FLASH_SR:PGERR 位 (0x4002200c) 在编程期间被设置,那么您就知道您还没有擦除那块内存。

Sidenote #5:Erasing a bit in flash memory means setting it to 1.

旁注 #5:擦除闪存中的一点意味着将其设置为 1。

Programming Your Binary

编程你的二进制文件

The next two lines after erasure writes the binary image to the flash and reenables the write protection. There isn't much more to say that isn't covered by PM0075. Basically any error that occurs when you issue flash write_imageis probably related to the flash protection not being disabled. It's probably NOTOpenOCD though if you're curious you can take enable the debug output and follow what it does.

擦除后的下两行将二进制映像写入闪存并重新启用写保护。PM0075 没有涵盖的内容不多说了。基本上,当您发出flash write_image时发生的任何错误都可能与未禁用 flash 保护有关。它可能不是OpenOCD,但如果您好奇,您可以启用调试输出并遵循它的功能。

GDB Debugging

GDB调试

So finally after programming I disconnect GDB from the remote connection and then reconnect it to the target, do a soft-reset, and my GDB is now ready to debug. This last part I just figured out last night as I was trying to figure out why, after programming, GDB wouldn't properly stop at main() after reset. It kept going off into the weeds and blowing up.

所以最后在编程后,我断开 GDB 与远程连接的连接,然后将其重新连接到目标,进行软重置,现在我的 GDB 已准备好进行调试。这最后一部分我昨晚才弄明白,因为我试图弄清楚为什么在编程之后,GDB 在重置后不会正确地停止在 main() 处。它不断进入杂草并爆炸。

My current thinking and from what I read in the OpenOCD and GDB manuals is that the remote connection is, first and foremost, meant to be used between GDB and a target that has already been configured and running. Well I'm using GDB to configure before I run so I think the symbol table or some other important info gets messed up during the programming. The OpenOCD manual says that the server automatically reports the memory and symbols when GDB connects but all that info probably becomes invalid when the chip gets programmed. Disconnecting and reconnecting I think refreshes the info GDB needs to debug properly. So that has led me to create another Debug Configuration, this one just connects and resets the target since I don't necessarily need to program the chip every time I want to use GDB.

我目前的想法以及我在 OpenOCD 和 GDB 手册中读到的内容是,远程连接首先是为了在 GDB 和已经配置并运行的目标之间使用。好吧,我在运行之前使用 GDB 进行配置,所以我认为符号表或其他一些重要信息在编程过程中会被弄乱。OpenOCD 手册说,当 GDB 连接时,服务器会自动报告内存和符号,但是当芯片被编程时,所有这些信息都可能变得无效。断开和重新连接我认为刷新 GDB 需要正确调试的信息。所以这导致我创建了另一个调试配置,这个配置只是连接并重置目标,因为我不一定每次想使用 GDB 时都需要对芯片进行编程。



Whew! Done! Kind of long but this took me 3 weekends to figure out so isn't too terribly bad I think...

哇!完毕!有点长,但这花了我 3 个周末才弄明白,所以我认为还不算太糟糕......

Final sidenote:During my time debugging I found that OpenOCD debug output to be invaluable to me understanding what OpenOCD was doing under the covers. To program a STM32x chip you need to unlock the flash registers, flip the right bits, and can only write a half-word at a time. For a while I was questioning whether OpenOCD was doing this properly but after looking through the OpenOCD debug output and comparing it against what the PM0075 instructions were, I was able to confirm that it did indeed follow the proper steps to do each operation. I also found I was duplicating steps that OpenOCD was already doing so I was able to cut out instructions that weren't helping! So moral of the story: Debug output is your friend!

最后的旁注:在我调试期间,我发现 OpenOCD 调试输出对于我理解 OpenOCD 在幕后所做的事情是无价的。要对 STM32x 芯片进行编程,您需要解锁闪存寄存器,翻转正确的位,并且一次只能写入一个半字。有一段时间我怀疑 OpenOCD 是否正确执行此操作,但在查看 OpenOCD 调试输出并将其与 PM0075 指令进行比较后,我能够确认它确实按照正确的步骤执行每个操作。我还发现我正在重复 OpenOCD 已经在做的步骤,所以我能够删除没有帮助的指令!这个故事的寓意是:调试输出是你的朋友!

回答by Mike Jones

I struggled getting JLink to work with a STM3240XX and found a statement in the JLink GDB server documentation saying that after loading flash you must issue a "target reset":

我努力让 JLink 与 STM3240XX 一起工作,并在 JLink GDB 服务器文档中找到了一条声明,说在加载闪存后,您必须发出“目标重置”:

"When debugging in flash the stack pointer and the PC are set automatically when the target is reset after the flash download. Without reset after download, the stack pointer and the PC need to be initialized correctly, typically in the .gdbinit file."

“在闪存中调试时,当闪存下载后重置目标时,堆栈指针和 PC 会自动设置。下载后无需重置,堆栈指针和 PC 需要正确初始化,通常在 .gdbinit 文件中。”

When I added a "target reset" in the Run box of the debugger Setup of Eclipse, suddenly everything worked. I did not have this problem with a Kinetis K60.

当我在 Eclipse 的调试器设置的运行框中添加“目标重置”时,突然一切正常。我用 Kinetis K60 没有这个问题。

The document also explains how to manually set the stack pointer and pc directly if you don't want to issue a reset. It may not be the disconnect/connect that solves the problem but the reset.

该文档还解释了如果您不想发出重置,如何直接手动设置堆栈指针和pc。解决问题的可能不是断开/连接,而是重置。

回答by German Ortiz

What i use after the last sentence in the Comannd Tab - 'Run' Commands, is:

我在命令选项卡的最后一句之后使用的 - “运行”命令是:

symbol-file STM3210CTest/test_rom.elf
thbreak main
continue

The thbreak mainsentence is what makes gdb stop at main.

thbreak main句话是让 gdb 停在 main 的原因。