Introduction
Let’s set up the J-Link GDB Server and GNU ARM Debugger in order to take a complete control of the our program execution flow. In the previous post, we described the installation process of the necessary things to make this possible.
Setting-up
Our hardware is SiLabs EFM32PG22 microcontroller and Linux PC with Kubuntu 22.04.3 LTS.
First step is to start J-Link GDB Server in order to be able to communicate with the on-chip debugger on the SiLabs board. It will be necessary to specify proper flags to the GDB Server.
JLinkGDBServer -if SWD -device EFM32PG22CxxxF512 -endian little -speed 1000 -port 2331 -swoport 2332 -telnetport 2333 -ir -localhostonly 1 -singlerun -strict -timeout 0 -nogui
If successful, the command should print something like Waiting for GDB connection…
Next, in a separate terminal, run the following command to start the GDB debugger and load the program:
arm-none-eabi-gdb switch_led_interrupt3_1.out
Commands
After starting the J-Link GDB Server with the previous command, it starts to listen for incoming connections from a GDB client on port 2331 (reason why we specified -port 2331 flag). To establish a connection from GDB to the J-Link GDB Server, this command is used:
(gdb) target remote localhost:2331
Next, we will flash the program.
(gdb) load switch_led_interrupt3_1.out
Now, we will reset our device to ensure it starts from a known, clean state and after that we will halts the execution of the target device in order to start from the first instruction of our program.
(gdb) monitor reset
(gdb) monitor halt
Now we will divide our terminal in 3 panes: source code, disassembly and GDB command input/output.
(gdb) layout split
Since these commands are useful and frequently used, it would be a good idea to execute them all together. We can create a .txt file containing all the commands and then execute them with a single command:
(gdb) source commands.txt
You can set a breakpoint using either a function name or a specific address.
(gdb) break GPIO_ODD_IRQHandler
(gdb) break *0xf14
Alternatively, you can use the letter b instead of the full word break. Breakpoints can be listed with this command:
(gdb) info breakpoints
It will display all breakpoints along with their numbers, allowing you to remove a breakpoint by specifying its number:
(gdb) delete 1
Lets talk about steping our program. There are few options. The si command stands for step instruction. It allows to execute a single machine level instruction in the program.
(gdb) si
The s command stands for step, and it is used to step through the program at the source code level, not machine instructions.
(gdb) s
The c command stands for continue. It resumes the program’s execution until the next breakpoint or the program terminates.
(gdb) c
The values on certain addresses (for example 0x40008064) can be printed with the command:
(gdb) p *((volatile uint32_t*) 0x40008064)
Also, regitsers values can be showed, for example r1 here:
(gdb) info register r1
You can navigate through the command history using Ctrl+p or Ctrl+n. At the end, to exit debugging mode, use the following intuitive command:
(gdb) exit
Sources
- Silicon Labs, EFM32PG22 Gecko MCU Family Data Sheet (link)
