Usage of GDB debugger
Friday, 2025-06-06 Comments
How to use the GDB debugger with a Raspberry Pi Pico 2 W.
Previous post: Logging with defmt over RTT.
Debugging with GDB
Once you start creating slightly more complicated embedded programs, you might want to:
- introspect the values of local variables
- follow the execution flow
For this, you need a piece of software called a debugger. The most commonly used debugger for Rust and C is GDB.
Remark: In VS Code, you can install the probe-rs-debug
extension to use the probe-rs
toolkit for debugging. It uses a different protocol than gdb
. See instructions.
Setup of cargo-embed
Adjust the Embed.toml
file in the root of this repository if necessary. This file configures the behavior of the cargo embed
command when run on your laptop.
For example, if the configuration contains the following, a GDB debug server session will be started, and the loaded program will be reset to the first instruction.
[default.gdb]
enabled = true
[default.reset]
halt_afterwards = true
Prevent lines from being merged or reordered during the build step of your program. These kinds of changes can make it harder for the debugger to stop at the right breakpoints. Add the following to Cargo.toml
:
[profile.dev]
debug = 2
opt-level = 0
To be sure the new configuration is used, you can clear the target
build cache with cargo clean
and then build again:
cargo clean
cargo build --example [BINARY_EXAMPLE_NAME]
Starting a GDB Client
While searching for an appropriate GDB package, look for one that supports the architecture of your target chip. In the case of a Pico 2, gdb
needs ARM
support built in.
Install the multi-architecture version of gdb
:
sudo apt-get install gdb-multiarch
Then run the following command to create and connect a gdb
debugging client:
gdb-multiarch target/thumbv8m.main-none-eabi/debug/[BINARY_EXAMPLE_NAME]
Note: The command may also be gdb
.
Within the gdb
client on your laptop, you have to connect to the running GDB
server on the debug Pico probe:
target remote :1337
monitor reset halt # optionally resets to the first instruction
tui enable
Alternatively, you can tell gdb
to execute these commands automatically by writing them in a .gdbinit
file in the root of this repository.
Common GDB Commands
Breakpoints can be set in the gdb
client by using the break
command followed by a line number or function name:
break [FUNCTION_NAME] # Set a breakpoint at a specific function
break [LINE_NUMBER] # Set a breakpoint at a specific line number
break [FILE_NAME]:[LINE_NUMBER] # Set a breakpoint at a specific line in a file
You can also write hardware breakpoints directly in your code with cortex_m::asm::bkpt()
.
To progress through the execution of your debugged program, you can use:
continue # Continue execution until the next breakpoint is hit
next # Step to the next line of code
For introspection of variables:
print [VAR_NAME]