For those who don't like Eclipse or VS Code, don't have the budget for Lautherbac, JLink, or iSystems, and aren't tech-savvy enough to debug using the command line, I present a convenient alternative called gdbgui — a web-based visual frontend for GDB. (Note: gdbgui is not a complete debugger; it only provides a graphical interface to control GDB). To use it, you'll need to have the usual tools installed on your Linux machine: make
, gcc
, gdb
, arm-none-eabi-gdb
, and openocd
.
If you do not have installed these tools in your Arch Linux, just type: ( python comes by default but not pip )
$ sudo pacman Sy base-devel gdb arm-none-eabi-gdb, arm-none-eabi-gdb arm-none-eabi-gdb openocd python-pip
Install gdbgui using the Python pip
package manager. However, before doing so, create a folder for your project and set up a Python virtual environment, as Arch Linux will not allow you to install anything with pip
outside of one.
$ mkdir test
$ cd test
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install gdbgui
We are going to test gdbgui with a simple program compiled for our PC using our old friend GCC. First, create a main.c
file and write a basic main program, something simple like:
#include <stdio.h>
void print( char *str );
int main( void )
{
for( int i = 0; i < 10; i++ )
{
print( "Hello, World!\n" );
}
return 0;
}
void print( char *str )
{
printf( "%s\n", str );
}
You will also need a special file that gdbgui will use when it invokes GDB. This file should contain instructions to load your program, set a breakpoint in main()
, and run up to the breakpoint. The file should be named .gdbinit
.
file main
break main
run
Build the program with GCC, then run the gdbgui server. It will display the IP address and port where you can access its web interface.
$ gcc main.c -g3 -o main
main mian.c
$ gdbgui --gdb-cmd='gdb -iex "set auto-load safe-path ."'
Opening gdbgui with default browser at http://127.0.0.1:5000
View gdbgui dashboard at http://127.0.0.1:5000/dashboard
exit gdbgui by pressing CTRL+C
What’s next? Well, open your web browser and enter the address shown in the terminal. Hit Enter, and you should see our glorious debugger in action! From there, you can set breakpoints, watch variables, and much more—the possibilities are endless. If you want to learn more, you can watch these old and outdated videos on YouTube
localhost
, even though it’s running inside your WSL instance.Going Embedded
That was great for simple programs running on our computer, but we’re working with embedded software now. Let’s try something using our old friend OpenOCD with an STM32G0 template project. First, clone the repository, then build the project to generate the ELF file.
$ git clone https://modularmx-admin@bitbucket.org/modularmx/template-g0.git project
$ cd project
$ make
...
arm-none-eabi-objcopy -Oihex Build/temp.elf Build/temp.hex
arm-none-eabi-objdump -S Build/temp.elf > Build/temp.lst
arm-none-eabi-size --format=berkeley Build/temp.elf
text data bss dec hex filename
2188 20 1572 3780 ec4 Build/temp.elf
Run OpenOCD in one terminal. Remember, the template project includes a makefile with a target to open a connection to your board. It will listen for GDB connections on localhost
at port 3333.
$ make open
openocd -f board/st_nucleo_g0.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 2000 kHz
Info : STLINK V2J45M31 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.223576
Info : [stm32g0x.cpu] Cortex-M0+ r0p1 processor detected
Info : [stm32g0x.cpu] target has 4 breakpoints, 2 watchpoints
Info : starting gdb server for stm32g0x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Before launching gdbgui as we did in the previous example, we need to fine-tune a few details. Open the makefile and locate the debug
target. Comment out the existing line, and then add a second one to invoke gdbgui. This server call, in turn, launches GDB but specifically for ARM devices.
#---launch a debug session, NOTE: is mandatory to previously open a debug server session-----------
debug :
# arm-none-eabi-gdb Build/$(TARGET).elf -iex "set auto-load safe-path /"
gdbgui --gdb-cmd=/usr/bin/arm-none-eabi-gdb --gdb-cmd='gdb -iex "set auto-load safe-path ."'
Next, open the .gdbinit
file and add the line file Build/temp.elf
before the load
instruction. This is how we specify the binary to use when programming the microcontroller's memory. At the moment, I haven’t found a way to specify the binary files directly from the command line.
#---connect and load program
target remote localhost:3333
file Build/temp.elf
load
mon reset halt
break main
continue
To call GDGUI just type make debug, it will open the server and …
$ make debug
Opening gdbgui with default browser at http://127.0.0.1:5000
View gdbgui dashboard at http://127.0.0.1:5000/dashboard
exit gdbgui by pressing CTRL+C
* Serving Flask app 'gdbgui.server.app'
* Debug mode: off
And of course open your web browser
I really like this project for many reasons, but my heart was broken when I found out that the project seems to be abandoned —or at least that's what it looks like. Here are a few things to keep in mind:
- Specifying the ELF file: I couldn’t figure out how to specify the ELF file directly from the command line when invoking gdbgui, which is why I added it to the
.gdbinit
file. This isn’t ideal, because if we change the name of the ELF file, we’ll need to update it in the.gdbinit
as well. Unfortunately, I don't know of a better way to do it. - No support for .SVD files: There’s currently no way to load .SVD files with MCU register information. This means you’ll have to rely on a lot of
printf
statements to see what’s going on with the MCU registers. - Lack of updates: It's been about a year since the official project repo was last updated. Something tells me that updates are pretty slow, or the project might be abandoned altogether.