Introduction to Open OnChip Debugger (OpenOCD)
The Open On-Chip Debugger (OpenOCD) is an Open-source middle-ware between Embedded Target Processor and host PC aimed to provide debugging, in-system programming and boundary-scan testing for embedded target devices.
In introduction to Embedded Systems debugging tutorial (here ) we mentioned that there are three things involved in Embedded Systems debugging.
- The Front End: This runs on host PC and controls SoC debugging e.g. GNU GDB.
- The Interface: The physical connection between host PC and target SoC e.g. JTAG, SWD.
- The debug hardware: It mainly consists of onchip debug hardware (In Circuit Emulator) or a debug stub compiled with application program to send program and SoC hardware state to the Front End program via an interface.
Of all the above three only the third one i.e. on-chip debug hardware is the one that is build on chip. The remaining two are the ones you have to pay for – separately. Now where is the problem?
The front-end debug program normally ship with toolchain integrated in an IDE providing complete out of the box solution for supported Embedded Processors. The main problem with these IDEs (with toolchains) are:
- Most of these toolchains are not free/only free to certain limits like code size etc. In order to unlock the full features, you have to purchase its license.
- Each toolchain has support for limited No. of Interfaces. The problem becomes more severe when the toolchain is provided by the SoC vendors. They normally restrict interface support to the ones that are supported by their SoCs. e.g. Keil has no support for FTDI based debug interfaces.
- Another major problem is portability. Most of the Embedded toolchains runs on Windows OS. If you are using a different OS like Linux or MacOS, either you have to find a supported versions of the toolchain or simply you are out of options.
On-Chip Debugger (OpenOCD) bring the benefit of both being Open-source and portable. It was initially written by Dominic Rath as part of a diploma thesis at the University of Applied Sciences Augsburg for providing Open-source debug solution to ARM7TDMI based processors. Currently OpenOCD has support wide range of processors and is one of the most extensively used debugging tool in the the world of deep embedded targets specifically in the case of debugging and bring up Embedded Linux.
At the time of writing this tutorial, following are the OpenOCD supported CPU types .
- arm11 – this is a generation of ARMv6 cores
- arm720t – this is an ARMv4 core with an MMU
- arm7tdmi – this is an ARMv4 core
- arm920t – this is an ARMv4 core with an MMU
- arm926ejs – this is an ARMv5 core with an MMU
- arm966e – this is an ARMv5 core
- arm9tdmi – this is an ARMv4 core
- avr – implements Atmel’s 8-bit AVR instruction set. (Support for this is preliminary and incomplete.)
- cortex_a – this is an ARMv7 core with an MMU
- cortex_m – this is an ARMv7 core, supporting only the compact Thumb2 instruction set
- aarch64 – this is an ARMv8-A core with an MMU
- dragonite – resembles arm966e
- dsp563xx – implements Freescale’s 24-bit DSP. (Support for this is still incomplete.)
- fa526 – resembles arm920 (w/o Thumb)
- feroceon – resembles arm926
- mips_m4k – a MIPS core
- xscale – this is actually an architecture, not a CPU type. It is based on the ARMv5 architecture.
- openrisc – this is an OpenRISC 1000 core. The current implementation supports three JTAG TAP cores:
- ls1_sap – this is the SAP on NXP LS102x CPUs, allowing access to physical memory addresses independently of CPU cores.
1. When will you need OpenOCD?
- When using GNU GDB for debugging Embedded Software.
- When the target is Remote.
- When you don’t have support in vendor supplied toolchain.
- When you need portable debugging solution.
2. How does OpenOCD Works?
As mentioned earlier OpenOCD itself acts as a middle-ware between GNU gdb and embedded software. BUT why we need OpenOCD as a middle-ware? Why can’t GNU gdb just talk directly to embedded SoC?
To answer these question let’s get back in short history! GNU gdb was originally designed for native debugging on UNIX like Systems. In native debugging gdb attaches to a process for debugging using System Calls (
ptrace). GDB commands and its responses are communicated back-and-forth between gdb and target process via OS System Calls. When remote debugging feature (debugging over remote serial protocol) was added to gdb, it made its way to embedded software debugging via gdb stub. i.e. a small piece of software running on embedded processor along side main application and responds to gdb serial commands sent via gdb remote serial protocol. The method was inefficient because of limited memory and other resources on Embedded Systems.
With the introduciton of on-chip debug logic the use of GNU gdb and subsequently gdb stub left behind in embedded system debugging race. Modern debugger (front-ends) developed were able to communicate directly with the on-chip debug logic. As gdb lacked that facility of talking directly to on-chip debug logics thats why it itself was no more useful to debug Embedded Software. BUT gdb has an advantage ….. its open-source and has support for wide range of processor architecture. The only problem is gdb can’t talk directly to on-chip debug logic.. neither can the on-chip logic understand or respond – Figure-2.
In order to establish link between gdb and on-chip debug hardware logic, a middle-ware acting like a translator; is required. This is exactly what OpenOCD does. When OpenOCD is started, it first tries to establish communication link with on-chip debug hardware logic via some physical interface like JTGA, STLINK, ICDI, FTDI etc. etc. Once the link is established, it opens two TCP/IP ports (server ports). The port no. 3333 which is the default port for gdb remote connection and port no. 4444 for telnet connection. The OpenOCD remains in waiting state listening for gdb or telnet connection request while keeping the connection established with the target processor via physical interface.
When one of the remote agent e.g. gdb or telnet connects to the OpenOCD, for the rest of the debugging time OpenOCD simply acts like a translator. It receives commands from gdb/telnet (TCL commands) and convert it into interface (STLINK, ICDI, JTAG) acceptable format and forward it to interface. Similarly the response received from the SoC via the same interface is converted back to gdb/telnet acceptable format – Figure-3.
By doing so OpenOCD just established connection between two non-compatible entities as shown in Figure-2 to compatible ones as shown in Figure-4.
3. How to use OpenOCD?
Now that you have better idea of how OpenOCD works! Let’s move on to the next important step i.e. How to use OpenOCD? In order to debug with OpenOCD, you need the following things.
- GNU gdb: You will need GNU gdb cross-compiled for your target processor architecture. This normally comes pre-compiled with your cross-compiled GNU toolchain. You can compile one yourself as demonstrated here . For Bare-metal ARM (arm-none-eabi), you can get pre-compiled complete toolchain from .
- OpenOCD: You will need OpenOCD cross-compiled for your target Operating System. Either you can cross-compile it yourself from source code  or you can get a pre-compiled one for your target OS from .
- OpenOCD Supported SoC: OpenOCD has support for limited no of Processors listed above.
For the purpose of demonstration we will be using STM32F4-Discovery board (ARM Crotex-M4). At this point I am assuming that you have already installed GNU ARM toolchain and OpenOCD on your target OS (in my case windows). If you have a problem with that, you can refer section-1,2 in this tutorial.
Let’s get started. Following are the steps.
1. The first step is to have an embedded software to be compiled, downloaded to target board and to debug. For the purpose of demonstration, i have compiled a simple blinky project for STm32F4-discovery board that can be downloaded from here. Extract it in some directory (preferable without spaces).
2. The next step is to connect OpenOCD with STM32F4-Discovery board connected to host PC via ST-Link USB cable. For this purpose we need to tell OpenOCD which target (ARM, MIPS etc.) we need to debug over which Interface (JTAG, ST-Link, ICDI etc.). The is done via a configuration script (Jim-TCL). OpenOCD already ships with configuration scripts for almost all supported interfaces (see the
scripts/board directory inside OpenOCD installation directory). You can create you own one or port existing one for you target hardware. Lucky the board we are using (STM32F4-Discovery) already has script for it in
board directory under the name
stm32f4discovery.cfg. So the next step is to connect STM32F4-Discovery board to host PC, open command prompt/terminal and enter the following command.
openocd -f board/stm32f4discovery.cfg
If connection is successful, you will see the following screen.
Now the OpenOCD has established connection to STM32F4-Discovery and actively listening for gdb/telnet to connect.
3. Leave the terminal window open and open a new command prompt/terminal window. Get to the directory where you have extracted the blinky binaries (in our case its
cd E:\Development\Workspace e:
4. Now enter the following commands one by one. I am assuming you already have
STM_Blinky.elf in the current working directory (in our case its
E:\Development\Workspace). This will cause gdb to connect to OpenOCD on port 3333.
arm-none-eabi-gdb STM_Blinky.elf target remote :3333
5. Reset and halt the processor. Also enable arm semihosting (for printf).
monitor reset init monitor halt monitor arm semihosting enable
6. Now upload the STM_Blinky.elf binaries to STM32F4-Discovery board, reset the processor and halt it.
load STM_Blinky.elf monitor reset halt monitor halt
7. Put a Temporary breakpoint at main function. This will cause the processor to stop upon entering main function.
8. Finally Let the processor run with “continue” command.
From now onward the processor is totally under your control. This point onward debugging totally depends on how well you have command over GNU gdb. see the GNU reference manual for various debugging commands like setting breakpoints, watching registers etc. etc.
A sample video is given for assistance.
4. Video Demonstration:
Click the full screen button for more clear view.
If you want to download code via telnet, following are the commands .
telnet localhost 4444 reset init halt arm semihosting enable flash write_image erase "E:/Development/Workspace/STM_Blinky.elf" (forward slash important) reset run
 – OpenOCD – Source Code
 – ARM GNU Toolchain
 – OpenOCD for various OS