Writing programs that just work would make the development of embedded systems a lot easier. In practice, however, a considerable amount of time is devoted to finding and removing bugs from the code. This process is commonly known as debugging and there is no way of avoiding it. In this article, we will give an overview of the software and hardware tools required for debugging microcontroller programs.
Using today’s modern Integrated Development Environments (IDEs) provided by MCU vendors, we as developers may not need to know the detailed setup of the debug tools. It is always preferable however to be familiar with these tools as complex projects may require setting up a development environment from scratch, not relying on a pre-configured IDE.
The basic functionality needed for debugging a program include:
- set/remove breakpoints
- step-by-step execution
- read values from memory addresses
The following components are required for enabling the debug functionalities:
- Target device (Microcontroller)
- Debug probe
- Debug software (debug server/debug client)
The target device is the microcontroller (MCU) on which our embedded application will be run. Debugging a program, while it is running on the target device is known as on-chip debugging. For supporting such functionality the MCU must have dedicated hardware resources. These resources include a dedicated interface (JTAG, SWD, etc.), internal hardware units allowing functionalities such as memory reads, program execution control (watchpoints, breakpoints, step-by-step execution, etc.).
Almost all microcontrollers today support the basic on-chip debugging functionalities. Depending on the complexity of the application, additional extended debug functionalities may be needed, so make sure to check the debug capabilities when choosing the MCU for your next project.
As we already established, the on-chip debugging requires a dedicated communication interface. These interfaces are not available on desktop computers, and an additional component called debug probe (aka debug adapter, programmer) is needed.
The function of the debug probe is to interpret the commands from the USB and relate them to the target device (MCU) using a specific communication interface protocol (e.g JTAG, SWD). It is important to note that a debug probe must be aware of the CPU it is communicating to. Usually, debug probes are provided by the MCU vendor. For popular CPU cores such as ARM, there are third-party probes available (e.g J-Link, ULINK, PowerDebug, etc.).
In recent years there is a trend that a debug adapter is implemented as part of the entry-level development and evaluation boards for MCUs. This approach reduces the cost for developers, as the only thing you need to start debugging is a development board and a host computer with a proper software toolchain.
The last piece of the debug toolset is the computer software we use to communicate with the debug probe and control the debug process. One of the most popular debug software is the GDB debugger and we will use it as an example in this chapter.
GBD Server/Client Setup
GDB is the most popular choice for embedded systems debugging as it can be run on a host computer and the application that has to be debugged can be run on the target device. This is made possible by the GDB server (gbdserver) and the “GDB Remote Serial Protocol”.
The GDB Remote Serial Protocol (RSP) provides a high level protocol allowing GDB to connect to any target remotely. If a target’s architecture is defined in GDB and the target implements the server side of the RSP protocol, then the debugger will be able to connect remotely to that target.” Howto: GDB Remote Serial Protocol ” by Jeremy Bennett of Embecosm
In the most common embedded environment setup, a gbdserver can’t be run on the actual target device, instead, it is run on the same host computer as the GDB client (see Fig. 3).
The server and the client communicate using the GBD Remote Serial Protocol via TCP/IP connection. The debug server must be aware of the specific probe commands and the target MCU that is going to be debugged.
Some of the popular GDB debug servers are:
- ST-Link GBD
A command for starting a gdbserver is shown below:
JLinkGDBServerCL -device nrf52840_xxaa -if swd -port 2332
The GDB client issues commands to the gdbserver, requestioning information or an action that has to be performed.
The interface to the client can be:
- GUI that has different views showing you memory, registers, and all kinds of visual debug related information.
- Command line interface
The GDB client for ARM microprocessors is arm-none-eabi-gbd. An example command for connecting to a remote gbdserver is shown below:
target remote localhost:2332
Debugging embedded programs is a complex task. Modern development environments provide pre-configured toolchains and easy to use GUIs that can be a big time saver. It is however recommended that every embedded systems designer is familiar with the steps involved in the debug process and the tools that make it possible. Always check the debug capabilities of the microcontroller you are going to use and the supported debug probes.