ðŊ Debugging Firmware with PyOCD - A Beginner's Guide
What is PyOCD?
PyOCD is a Python-based debugging tool specifically designed for ARM Cortex-M microcontrollers. Think of it as a bridge between your computer and your microcontroller that lets you inspect and control your program while it's running. While it only works with ARM processors, it's much more user-friendly than alternatives like OpenOCD.
Setting Up Your Environment
1. Install PyOCD
python3 -m pip install pyocd
2. Connect Your Hardware
-
You'll need:
- Your development board
- A debugger (like STLinkV2)
- Appropriate connecting cables
-
Make the physical connections:
- For SWD (most common):
- Connect GND (Ground)
- Connect SWDIO (Data line)
- Connect SWDCLK (Clock line)
- If your board uses JTAG:
- Connect GND, TDI, TMS, TCK, and TDO pins
- If you have a JTAG device that supports SWD
- Connect GND
- Connect JTAG TMS to MCU SWDIO
- Connect JTAG TCK to MCU SWDCLCK
- For SWD (most common):
Important
Double-check all connections! Incorrect wiring can damage your board, debugger, or computer.
Starting a Debug Session
1. Launch PyOCD Server
First, start the PyOCD server for your specific device:
# For LPC40xx boards:
pyocd gdbserver --target=lpc4088 --persist
# For STM32F103xx boards:
pyocd gdbserver --target=stm32f103rc --persist
Not sure about your target? Run pyocd list --targets
to see all options.
2. Connect GDB
Open a new terminal and launch GDB:
arm-none-eabi-gdb -ex "target remote :3333" -tui your_program.elf
This command:
- Opens GDB with a text-based UI (
-tui
) - Connects to PyOCD (
target remote :3333
) - Loads your program (
your_program.elf
)
Tip
arm-none-eabi-gdb
command not found? No worries, build an project for an
arm based device like so conan build . -pr stm32f103c8 -pr arm-gcc-12.3
.
There is a file called generators/conanbuild.sh
which provides your
command line access to the paths to the ARM compiler toolchain where GDB
resides. Sourcing those environment variables would look like this, but
replace stm32f103c8
with your platform and MinSizeRel
with your build
type:
source build/stm32f103c8/MinSizeRel/generators/conanbuild.sh
Basic Debugging Commands
Essential GDB Commands
# Start your debug session
b main # Set breakpoint at main()
monitor reset halt # Reset the CPU and stop at the beginning
c # Continue execution
# Navigate through code
n (or next) # Execute next line (skip function details)
s (or step) # Step into functions
finish # Run until current function returns
c (or continue) # Run until next breakpoint
# Inspect values
p variable_name # Print variable value
info registers # View all CPU registers
Tip
If you are familiar with GDB, you notice that the command "run" was not used. In this context, there is no program, just the CPU. The debugger is controlling and stopping the CPU from executing. So there is no need to "run" the program, its already running. You simply have to continue.
Viewing Memory and Registers
To access hardware registers and memory:
# Enable access to all memory
set mem inaccessible-by-default off
# View register values
p gpio_reg->CTRL # View specific register
Managing Breakpoints
b function_name # Break at function start
b filename.cpp:123 # Break at specific line
info breakpoints # List all breakpoints
delete 1 # Remove breakpoint #1
delete # Remove all breakpoints
Updating Your Program
If you make changes to your code:
- Build your program in another terminal
- In GDB:
monitor erase # Erase current firmware image
load # Flash the new program
monitor reset halt # Reset to start and halt CPU
Tips for Beginners
- Start with simple programs to get comfortable with the debugging process
- Use frequent breakpoints to understand program flow
-s build_type=Debug
builds are easy to debug with a debugger than-s build_type=MinSizeRel
or-s build_type=Release
builds- Remember that embedded debugging is different from regular program debugging because your code is running on actual hardware and you are controlling the cpu
- If you can't see source code lines initially, don't worry - this is normal
with bootloaders (like on LPC40xx boards), proceed with the
continue
command and you should end up at your first breakpoint whenever it is reached
For a complete reference of GDB commands, check out this GDB Cheat Sheet.