modified on 17 June 2010 at 17:13 ••• 12,681 views

Using OpenOCD/2

From Manuals

Jump to: navigation, search


Debugging using GDB Commands

OpenOCD – Open On-Chip Debugger

The Open On-Chip Debugger (OpenOCD) provides debugging, in-system programming and boundary-scan testing for embedded target devices. It allows debuggers to execute JTAG functions on embedded targets either from a local system or across a network. The Micromint Eagle BSP installer in the Tools CD can be used to install a version of OpenOCD for Windows configured to use the LMI FTDI interface via USB. OpenOCD for Linux can also be downloaded from the web. Below are the most important files installed:

  • openocd-ftd2xx.exe - OpenOCD application for Windows32
  • eagle-50.cfg - OpenOCD configuration file for the Micromint Eagle using LMI FTDI
  • program.script - Script file to transfer a binary image to the LMI controller
  • FTD2xx.dll – Library to interface with FTDI-based devices (part of the Micromint Eagle USB driver)
  • openocd.bat – batch file to start OpenOCD

By default OpenOCD reads the file configuration file “openocd.cfg” in the current directory. To specify a different configuration file, you need to use the “-f” option. The batch file included (openocd.bat) starts OpenOCD with the eagle-50.cfg configuration. Figure 2-1 shows how to invoke OpenOCD directly from the command line using the “-f” option to specify the configuration file.

OpenOCD starting session
Figure 2-1: Example of OpenOCD starting session

Once started, OpenOCD connects to the JTAG device via the USB LMI FTDI interface and runs as a daemon, waiting for connections from clients (telnet, GDB or others). There are many ways you can configure OpenOCD and start it up. A simple way to organize them involves keeping a separate directory for each board with its processor and JTAG configurations. When you start OpenOCD it searches the current directory first for configuration files, scripts, and for code you upload to the target board. It is also the natural place to write log files and data to be download from the board upon startup. By pressing ctrl –c, the OpenOCD daemon is stopped, ending communication with the embedded device. You will need to stop OpenOCD when using the LMI Flash Programmer, to update firmware on the board.

OpenOCD uses a hardware interface to communicate with JTAG (IEEE 1149.1) compliant TAPs on your target board. A TAP is a “Test Access Port”, a module which processes special instructions and data. In the Micromint Eagle 50 the USB debug port implements a TAP that is compatible with the FTDI interface in OpenOCD. TAPs can be daisy-chained within and between chips and boards.

OpenOCD currently supports many types of JTAG interfaces: USB based, parallel port based and even standalone boxes that run OpenOCD internally. Examples include USB FTDI FT2232, USB J-Link, USB RLINK, PC Parallel Printer Port and others. More information about OpenOCD is available from these references:

Open On-Chip Debugger

OpenOCD User’s Guide

GDB – GNU Project Debugger

The purpose of a debugger is to allow you to monitor a program while it executes to identify and correct any undesired behavior. GDB (GNU Project Debugger) allows developers to debug applications by providing four important capabilities:

  • Load the program in memory and start it with any parameters that may affect its behavior.
  • Place breakpoints to stop the program on specified conditions.
  • Watch variables and processor registers when the program stops to examine what has happened
  • Change instructions and data in the program to test alternatives to correct program bugs before changing the source code and rebuilding the executable.

GDB is included with popular GNU ARM toolchains like devkitARM, Sourcery G++ Lite, WinARM and YAGARTO.

Introduction to GDB Commands

There are two important considerations when compiling an application to be debugged. To be able to view the source code when debugging , the executable must be compiled with debugging data (-g). To separate application bugs from compiler bugs it is a good practice to first compile without any compiler optimization (-O0 and no -Os). Once the application is working as expected, you can debug the final executable with the desired optimization level.

There are some essential commands needed to perform basic debugging tasks using GDB. The first thing you need to do is start GDB from the command line, usually from the directory containing the application binary to be debugged. The command used to invoke the GDB included with devkitARM is ‘arm-eabi-gdb project_name.out’. Figure 2-2 shows a sample debugging session using blinky.out.

C:\Projects\ARM\blinky\gcc> arm-eabi-gdb blinky.out
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-mingw32 --target=arm-eabi"...
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x00000000 in ?? ()
(gdb) load
Loading section .text, size 0x288 lma 0x2000
Start address 0x2000, load size 648
Transfer rate: 2 KB/sec, 648 bytes/write.
(gdb) b blinky.c:78
Breakpoint 1 at 0x2198: file blinky.c, line 78.
(gdb) b blinky.c:90
Breakpoint 2 at 0x21ce: file blinky.c, line 90.
(gdb) j ResetISR
Continuing at 0x20f4.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at blinky.c:78
78              GPIO_PORTE_DATA_R |= 0x02;

GDB can connect to a remote JTAG such as OpenOCD using the command ’target remote host:port’. The host may be either a hostname or a numeric IP address; port must be a decimal number. In Figure 2-2, localhost:3333 connects to the OpenOCD daemon running in port 3333 of the local machine. If the remote target is running on the same machine as your debugger session, you can omit the hostname.

The GDB ’load’ command as can be used to load the application binary to the device. GDB will use the memory addresses specified when the application was linked. OpenOCD allows GDB access to the JTAG functions required to flash the firmware to the current TAP device.

To jump to a specific location, you just need to invoke the GDB ’jump location’ command where location specifies the address, label or source code location to start or continue execution. Commonly used GDB commands allow a shortcut. In the case of ’jump’ you can also use ’j’. In the example on Figure 2-2 ’j ResetISR’ jumps to the location of ResetISR and continues execution until a breakpoint is found.

(gdb) b blinky.c:78
Breakpoint 1 at 0x2198: file blinky.c, line 78.
(gdb) b blinky.c:90
Breakpoint 2 at 0x21ce: file blinky.c, line 90.
(gdb) watch ulLoop
Hardware watchpoint 3: ulLoop
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x00002198 in main at blinky.c:78
        breakpoint already hit 1 time
2       breakpoint     keep y   0x000021ce in main at blinky.c:90
3       hw watchpoint  keep y              ulLoop
(gdb) b blinky.c:83
Breakpoint 4 at 0x21b0: file blinky.c, line 83.
(gdb) cond 4 ulLoop=1000
(gdb) c
Breakpoint 4, main () at blinky.c:83
83              for(ulLoop = 0; ulLoop < 200000; ulLoop++)
(gdb) p ulLoop
$2 = 1000

A breakpoint makes your program stop when a specified location in the program is reached. You can add conditions to the breakpoints to only stop when a specified behavior is found, allowing finer control when debugging. You can set breakpoints with the GDB ’break location’ command or its shortcut ’b location’. In Figure 2-3 the ’ b blinky.c:78’ command sets a breakpoint on line 78 of blinky.c You can list the current breakpoints by using the ’info break’ command.

A watchpoint is an expression defined with ’watch’ command that can be monitored during execution of the application. The expression may be a value of a variable, or it could involve values of one or more variables combined by operators, such as ‘a + b’. You can enable, disable, and delete both breakpoints and watchpoints using the same commands. Likes breakpoints, you can see all your declared watchpoints using the info watch command. Figure 2-3 also shows watchpoints declaration.

An expression can also be used as a condition for a breakpoint. When a condition is specified on a breakpoint it is evaluated each time the program reaches it, stopping execution only if the condition is true. When setting a conditional breakpoint you need to know breakpoint’s number and declare the expression going to be evaluated to a specify value. This command is useful when you are working with instructions that are executed many times but need to be debugged only when specific values are reached. In Figure 2-3, ’ cond 4 ulLoop=1000’ sets breakpoint 4 to stop only when variable uLoop has a value of 1000 . That breakpoint was previously declared at line 83 of blinky.c.

Table 2-1 shows essential GDB commands. More information about GDB is available online from this reference:

GDB Documentation

Command Description Example
b functionset breakpoint at functionb blinky.c:78
btdisplays program stackbt
ccontinue running your programc
cond n [expr]new conditional expression on breakpoint n; make unconditional if no exprcond 4 ulLoop=1000
info break or info watchshow defined breakpoints or watchpointsinfo break
j line or j *addressresume execution at specified line or addressj ResetISR
loadload program to your target load
nnext line, stepping over function callsn
p exprdisplay the value of an expressionp ulLoop
runstart your program with current argument listr
snext line, stepping into function callss
target remote host:port debugging using a TCP connection to port on host target remote localhost:3333

Table 2-1: Common GDB Commands

Using GDB from the CodeBlocks IDE

GDB can be invoked from the CodeBlocks IDE using the proper settings. The GDB commands are the same as with the command line example in the previous section, but the IDE provides toolbar buttons to reduce typing and simplify its use. Figure 2-4 shows the location of the debugger command line in Codeblocks.

Debugger command line
Figure 2-4: Debugger command line in Codeblocks

The following buttons can be accessed with the debugging toolbar in the IDE:

Start Start/Continue – Start or continue the debugging process

Line Next line – Step over function calls

Instruction Next instruction – Step to the next instruction of a function

Into Step into – Step into function calls

Out Step out – Step out of function calls

Run Run to cursor – Run program to cursor current position

StopStop debugger – Stop the debugging process

Breakpoints can be set by clicking the mouse next to the line number of the line in the source code where you want to stop the program. You can also set a conditional breakpoint by right clicking on the breakpoint location and specifying the desired condition. Two conditional options are available: ignoring the breakpoint for a specified number of counts before break or break when a specified expression is true. Both can be very useful to make the debugging process more efficient. Figure 2-5 shows where breakpoints are set and the window used to edit them.

Setting breakpoints
Figure 2-5: Setting breakpoints

The debugger invoked by the Codeblocks IDE can be specified by selecting ‘Settings’, ‘Compiler and debugger’ on the menu, as shown on Figure 2-6.

Compiler and debugger selection
Figure 2-6: Compiler and debugger selection

On the ‘Compiler and debugger’ settings window, look for Global compiler settings and click on Toolchain executables. When using the devkitARM toolchain your Debugger should be set to arm-eabi-gdb.exe. This is the default value but it should be verified if your debugging sessions are not working as expected. Figure 2-7 shows an example of the proper configuration of toolchain executables.

Setting the Debugger
Figure 2-7: Setting the Debugger to GDB on Codeblocks