December 24, 2023

STM32H747I-DISCO "Discovery kit with STM32H747XI MCU" -- debugging using Gdb

Back in 2016 under Fedora 24, the arm-none-eabi-gdb package was readily available in the Fedora package collection. Then for some reason it vanished. I just got very lucky and tripped over the following: So, arm-none-eabi-gdb is available in Fedora "copr".
I follow the instructions. I already have dnf-command installed, so:
dnf copr enable rleh/arm-none-eabi-gdb
dnf install arm-none-eabi-gdb
It works! I start it and "show version" gives me "GNU gdb (GDB) 14.1".

How to start Gdb with openocd

I have some notes from when I played with this and the STM32F103. I end up using at least 4 windows: In the gdb window, you type:
arm-none-eabi-gdb --eval-command="target remote localhost:3333" blink.elf
I put this into a little script "gdb_start".

A side note

Along with "gdb -tui" there is cgdb and ddd. One fellow says that "GDB is not simply a tool, it’s a debugging framework for you to build upon".

How to use gdb

Compile with the "-g" flag to make things pleasant.
If you forget the elf file at the end of the gdb line use "file blink.elf" to get the debug information.
Here are some gdb commands:
i r -- shows the registers
stepi -- execute one assembly instruction
nexti -- as above, but a function call is executed until it returns
disas 0x50, 0x60 - disassemble from start to end
x/nfu 0x40 - examines memory
    n = how many
    f = format (usually x for hex), maybe x, i, s
    u = how big b, h, w, g are 1,2,4,8 byte objects
continue -- run to breakpoint (or forever)
    note that "reset halt" in openocd window will get control

gdb -tui

Here "tui" stands for "text user interface". Also note that "-tui" is a switch to gdb.

Once again, I put the command to start this into a little bash script "tui_start" which has:

arm-none-eabi-gdb -tui --eval-command="target remote localhost:3333" debug.elf
Once you get it started, type this to get an assembly listing in the upper pane:
layout asm
Next you should type Control-X s to put it into single key mode, then the following will be single key shortcuts for longer commands:
s = step
n = next
c = continue
r = run
f = finish
d = down
u = up
w = where
v = info locals

New frontiers

Some searching led me to this: Although it deals with embedded linux rather than bare metal, it is very good and I learned many valuable things.

There is a program "ddd" that is a gui front end for gdb. It is old, Motif based, and works by "scraping" the gdb console output, but people like the end result. I should give it a try.

There is also "cgdb" which is a curses based front end to gdb, reportedly better than "gdb -tui"

And there is this wonderful quote from Brian W. Kernighan:
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
This Gdb tutorial is very good:

What I do to debug a STM32 system

I load the code by typing "program xyz.elf" in the telnet window. I do not do reset so it will be waiting for gdb to set breakpoints or whatever. Then in the "tui" window, I do: There is plenty more to learn, but this gets me going in a basic way. Amazingly, breakpoints work even with code in flash.

Be sure to compile with the -g option. Consider using the -Og option which limits the optimizer to using only gdb friendly optimizations. Some variables may need to be declared volatile if you intend to use them as sentinels for gdb

More about gdb

I am still not sure what the best way is to make changes, recompile, and then load the program to get going again. I exit "tui" and use the telnet window to "program xyz.elf", then restart the "tui" window, set breakpoints and on we go. Maybe typing "file xyz.elf" in gdb would do it. Dumping memory: Interestingly, there is no explicit way to modify memory, but you can do this: I got tired of it asking me about subprocesses every time I told it to quit.
To avoid this, I put this into my .gdbinit:
define hook-quit
    set confirm off
end

Restarting

This did not work until I made this change to start gdb:
#arm-none-eabi-gdb -tui --eval-command="target remote localhost:3333" blink.elf
arm-none-eabi-gdb -tui --eval-command="target extended-remote localhost:3333" blink.elf
Now, with "extended-remote" I can type "r" to run, and this nicely restarts the code. This means that I don't need to exit gdb to reload the software. I use "program xyz.elf" in the telnet window connected to openocd, then I can do:
b rcc_init
r
And it sets a breakpoint and runs the new code. Very nice.

Fancy keyboard stuff

Consider putting this into your .inputrc file (this will also affect bash).
set editing-mode vi

I tried it, and it turns out that is only half the story. Another trick is required. Type "focus cmd" and you will be able to use arrow keys. And with the above line in your .inputrc, you will get the full vim style line editing as well. Typing "focus src" lets you scroll the top window.

Control-X does all kinds of interesting stuff. Ctrl-X A toggles in and out of TUI mode. Ctrl-X s enters TUI single key mode. There is more.

Colors

Gdb tries to do syntax highlighting. My terminal has a black background and the blue used for addresses is all but unreadable. Here are several options: You can put commands like this into a .gdbinit file.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org