Difference between revisions of "DevGuide/GDB OpenOCD Debug"

From PaparazziUAV
Jump to navigation Jump to search
 
 
(23 intermediate revisions by 9 users not shown)
Line 1: Line 1:
== JTAG debugging ==
== GDB ==
Paparazzi boards do not have a JTAG interface. The one time we needed a JTAG debugger because of some strange problems we used Keil/Olimex LPC2148 boards with a professional JTAG tool. All the parallel port Wiggler adapters and the software for that showed poor performance and were abandoned.


Recently some new JTAG adapters that use the FTDI2232 USB-parallel converter were introduced through OpenOCD (you can try your Wiggler with that, too). The USB JTAG adapters are available from Olimex or Amontec and work fine with Windows (Yagarto). Getting them to work with Linux is still a little adventure. This is collected info from various sites. The paparazzi-dev packages should be installed.
Commands can often be issued without typing the entire command. Here are some commonly used commands; many of them can be invoked using only the first letter:
(gdb) quit – exit the debugger
(gdb) file – load an executable file
(gdb) break line-number/function name -- Set a break-point on a line/at start of function
(gdb) run <args> -- start running the program; if there are command-line arguments, put them after the run invocation
(gdb) cont -- continue running, after a break
(gdb) next -- Next program line (step over function calls)
(gdb) step -- Step into function calls.
(gdb) finish - Step out of the present function
(gdb) print expression -- Show value of a variable or expression
(gdb) list – List 10 lines of the program being debugged. The sixth line is the preset statement. Subsequent, consecutive entry of list will list the next 10 lines.
(gdb) where – obtain a backtrace showing all function calls before the current statement
(gdb) up – Move to the function that called the present function. Useful if your program crashes in a library function; use up to get to the last function call in your program
(gdb) down – Reverses the action of up
(gdb) delete – Removes breakpoint by number (see example following). If no number, all deleted.
(gdb) kill – Terminates the program.


== Install ==
== GDB - OpenOCD - Floss JTAG ==
The low level interfacing is done by libftdi, get it from http://www.intra2net.com/de/produkte/opensource/ftdi/ It is possible to use a closed source version from FTDI, too.


wget http://www.intra2net.com/de/produkte/opensource/ftdi/TGZ/libftdi-0.10.tar.gz
Connecting OpenOCD to a Floss JTAG (Lisa/L in this case) an GDB to OpenOCD.
tar xvfz libftdi-0.10.tar.gz
cd libftdi-0.10
./configure
make
make install


Get the OpenOCD software http://openfacts.berlios.de/index-en.phtml?title=Building_OpenOCD It needs some additional packages to be built.
# Start openocd in a new shell since this process needs to remain running.
#* STM targets
#: To connect to the Lisa/L board run the command
#:<pre>openocd -f interface/lisa-l.cfg -f board/lisa-l.cfg</pre>
#:  To connect to the Lisa/M board via FLOSS-JTAG run the command:
#:<pre>openocd -f interface/flossjtag.cfg -f board/lisa-l.cfg</pre>
#* NXP LPC targets
#:  To connect to the LPC based board via OLIMEX ARM-USB-OCD dongle run the command:
#:<pre>openocd -f interface/olimex-arm-usb-ocd.cfg -f target/lpc2148.cfg</pre>
#:  To connect to the LPC based board via OLIMEX ARM-USB-OCD-H dongle run the command:
#:<pre>openocd -f interface/olimex-arm-usb-ocd-h.cfg -f target/lpc2148.cfg</pre>


apt-get install autoconf
# Compiler Debug Options
apt-get install automake
#: On LPC target build your ap file with debug options. See https://github.com/elemhsb/paparazzi/blob/v4.0/conf/Makefile.lpc21 .
apt-get install subversion
svn checkout svn://svn.berlios.de/openocd/trunk
cd trunk
./bootstrap
./configure --enable-ft2232_libftdi
make
make install


For some debian distributions you might have to add '/usr/local/lib' to /etc/ld.so.conf.d/i486-linux-gnu.conf and call
# Start GDB with an argument of the elf file created and uploaded to the board.
#: If you programmed with the ap target then the command would be along the lines of
#:<pre>/opt/paparazzi/arm-multilib/bin/arm-none-eabi-gdb var/<airframe>/ap/ap.elf</pre>
#: Replace <airframe> with the name of the airframe that has been built.


ldconfig
# Now connect GDB to the board
#:<pre>target remote localhost:3333</pre>
# Now we need to set some break points in the code.
#: In this example the ap target was part of the rotorcraft and main.c contains the main program. Open rotorcraft sw/airborne/firmwares/rotorcraft/main.c and find a line at which you'd like to set a break point.
#: <pre>break main.c:113</pre>
# Stop the currently running code
#: <pre>monitor reset halt</pre>
# Reset the code back to the start
#: <pre>monitor reset init</pre>
# Now we can run the program which will stop at the break point we set.
#:<pre>continue</pre>


Put an entry with the vendor/device ID into your udev rules directory to get the correct access rights (or use the file from cvs in paparazzi3/conf/system/udev/rules). This applies to Yagarto.
== Black Magic Probe specific ==


add 'BUS=="usb", SYSFS{idVendor}=="0403", SYSFS{idProduct}=="cff8", GROUP="dialout"'  
# Start GDB for arm
#: Open GDB with the correct binary file
#:<pre>/opt/paparazzi/arm-multilib/bin/arm-none-eabi-gdb ./var/AIRFRAME/ap/ap.elf</pre>
#: Set Black Magic Probe as Target over the serial link (see ls /dev/ttyACM*):
#:<pre>target extended-remote /dev/ttyACM0</pre>
#: Probe via JTAG to get a list of devices:
#:<pre>mon jtag_scan</pre>
#: (for [[Lisa/S]], use ''swdp_scan'' instead of ''jtag_scan'')
#:
#: Attach to a device:
#:<pre>attach 1</pre>
# Happy Debugging!


Generate an OpenOCD config - this one worked for me, might need some polishing
=== Useful GDB commands ===


#daemon configuration
Also look at [[DevGuide/GDB_OpenOCD_Debug#GDB]] for general GDB commands
telnet_port 4444
gdb_port 3333
#interface
interface ft2232
ft2232_layout "jtagkey"
ft2232_vid_pid 0x0403 0xcff8
jtag_speed 2
# reset_config <signals> [combination] [trst_type] [srst_type]
reset_config trst_and_srst
#jtag scan chain
jtag_device 4 0x1 0xf 0xe
jtag_nsrst_delay 333
jtag_ntrst_delay 333
#target configuration, what to do on a target reset
target arm7tdmi little run_and_halt 0 arm7tdmi-s_r4
run_and_halt_time 0 30
daemon_startup reset
#target_script 0 reset openocd.script
working_area 0 0x40000000 0x4000 nobackup
 
# flash bank lpc2000 <base> <size> 0 0 <variant> <target#> <clock> ['calc_checksum']
# mthomas: LPC2138 @ 12MHz 0x7D000 from 500*1024 (not 512!)
flash bank lpc2000 0x0 0x7D000 0 0 lpc2000_v2 0 12000 calc_checksum


Get Eclipse 3.2.2 (Debian Eclipse package did not work for me - some problem with JRE 1.4.x?)
To display some commands for BMP
  monitor help
example output fot STM32F4
<pre>
General commands:
version -- Display firmware version info
help -- Display help for monitor commands
jtag_scan -- Scan JTAG chain for devices
swdp_scan -- Scan SW-DP for devices
targets -- Display list of available targets
morse -- Display morse error message
connect_srst -- Configure connect under SRST: (enable|disable)
ARM Cortex-M specific commands:
vector_catch -- Catch exception vectors
STM32F4 specific commands:
erase_mass -- Erase entire flash memory
option -- Manipulate option bytes


wget http://download.eclipse.org/eclipse/downloads/drops/R-3.2.2-200702121330/download.php?dropFile=eclipse-SDK-3.2.2-linux-gtk.tar.gz
</pre>
tar xvfz eclipse-SDK-3.2.2-linux-gtk.tar.gz


Unzip the Eclipse embedded CDT from Zylin for embedded debugging http://www.zylin.com/embeddedcdt.html
* We probably want to ignore the interrupt calls for the moment so we can step through the code as it's being called. Note that we don't always want to do this. (STM32 command only)
*:<pre>monitor cortex_m3 maskisr on</pre>
* A stack trace can be printed with the command
*:<pre>bt</pre>
* show the variable of a variable
*:<pre>print i2c1.status</pre>
* Show (eXamine) the value of the 9 bytes hardware register at address 0x40005800 and show them in hex format:
*:<pre>x/9x 0x40005800</pre>
* In some cases you may not be able to access some memory areas in the mcu, in that case you should try:
*:<pre>set mem inaccessible-by-default off</pre>


wget http://www.zylin.com/embeddedcdt-linux-gtk-20060908.zip
=== .gdbinit for BMP ===
wget http://www.zylin.com/zylincdt-20060908.zip
cd eclipse
unzip embeddedcdt-linux-gtk-20060908.zip
unzip zylincdt-20060908.zip


Now you have to get used to Eclipse...start eclipse, close the welcome screen and change outline to C/C++: Window->Open Perspective->Other->C/C++
The standard commands like setting the ttyACM0 port, searching for targets and attaching one can be automated. Either with a ".gdbinit" file or if your work with Eclipse, there is a box at Debug configutations/Startup.
Add openocd support: Run->External Tools->External Tools Program, Name: OpenOCD, Location: /usr/local/bin/openocd, Arguments: -f <wher_your_cfg_lives>
 
Try to use the debugger: Run->Debug Embedded debug (Native), Commands: ?
One Example from [http://docs.armstrap.org/en/latest/getting-started-eclipse-development-tools.html| armstrap]
 
<pre>
target extended-remote /dev/ttyACM0
mon swdp_scan
attach 1
monitor vector_catch disable hard
set mem inaccessible-by-default off
set print pretty
</pre>
 
=== Setting up .gdbinit for BMP and gdb-regview ===
 
If you use gdb just with a BMP, you can set some initialization commands in ~/.gdbinit that will run when gdb is started, improving workflow.
 
A very useful plug-in called gdb-regview [https://github.com/fnoble/gdb-regview (available on GitHub)] can really speedup debugging stm32 processors by providing a pretty-printed summary of register contents.
 
A sample file for debugging Lisa/M 2.0 would be:
<pre>
set target-async on
set mem inaccessible-by-default off
#for gdb-regview plugin
source /path/to/gdb-regview/gdb-regview.py
regview load /path/to/gdb-regview/defs/STM32F10X_CL.xml
tar ext /dev/BMP_DEVICE
mon version
mon swdp_scan
att 1
</pre>
 
This should be saved in <tt>~/.gdbinit</tt>.
 
Then, after one starts gdb as described above, you can view registers easily, for example:
<pre>(gdb) regview show ADC_CR1</pre>
 
=== Load new binary from gdb with BMP ===
 
It is also easy to rebuild and reload a program from inside gdb. Calling make from the gdb command line will call make in your current directory:
<pre>(gdb) make</pre>
 
To load a new elf file into gdb after compiling elsewhere (only required when changing the name of the file):
<pre>(gdb) file file_name.elf</pre>
 
To upload the binary as per the currently loaded elf:
<pre>(gdb) load</pre>
This assumes you have attached to the target already (as per the .gdbinit example just above).
 
To restart the program from the beginning:
<pre>(gdb) run</pre>
and enter <tt>y</tt>.
 
gdb should detect that the elf has changed when loading the new binary, so if the file name has not changed, one should just be able to rebuild (make from inside gdb if appropriate) and then call load and run.
 
[[Category:Hardware]] [[Category:Software]] [[Category:Developer_Documentation]]

Latest revision as of 04:31, 14 April 2015

GDB

Commands can often be issued without typing the entire command. Here are some commonly used commands; many of them can be invoked using only the first letter:

(gdb) quit – exit the debugger
(gdb) file – load an executable file
(gdb) break line-number/function name -- Set a break-point on a line/at start of function
(gdb) run <args> -- start running the program; if there are command-line arguments, put them after the run invocation
(gdb) cont -- continue running, after a break
(gdb) next -- Next program line (step over function calls)
(gdb) step -- Step into function calls.
(gdb) finish - Step out of the present function
(gdb) print expression -- Show value of a variable or expression
(gdb) list – List 10 lines of the program being debugged. The sixth line is the preset statement. Subsequent, consecutive entry of list will list the next 10 lines.
(gdb) where – obtain a backtrace showing all function calls before the current statement
(gdb) up – Move to the function that called the present function. Useful if your program crashes in a library function; use up to get to the last function call in your program
(gdb) down – Reverses the action of up
(gdb) delete – Removes breakpoint by number (see example following). If no number, all deleted.
(gdb) kill – Terminates the program.

GDB - OpenOCD - Floss JTAG

Connecting OpenOCD to a Floss JTAG (Lisa/L in this case) an GDB to OpenOCD.

  1. Start openocd in a new shell since this process needs to remain running.
    • STM targets
    To connect to the Lisa/L board run the command
    openocd -f interface/lisa-l.cfg -f board/lisa-l.cfg
    To connect to the Lisa/M board via FLOSS-JTAG run the command:
    openocd -f interface/flossjtag.cfg -f board/lisa-l.cfg
    • NXP LPC targets
    To connect to the LPC based board via OLIMEX ARM-USB-OCD dongle run the command:
    openocd -f interface/olimex-arm-usb-ocd.cfg -f target/lpc2148.cfg
    To connect to the LPC based board via OLIMEX ARM-USB-OCD-H dongle run the command:
    openocd -f interface/olimex-arm-usb-ocd-h.cfg -f target/lpc2148.cfg
  1. Compiler Debug Options
    On LPC target build your ap file with debug options. See https://github.com/elemhsb/paparazzi/blob/v4.0/conf/Makefile.lpc21 .
  1. Start GDB with an argument of the elf file created and uploaded to the board.
    If you programmed with the ap target then the command would be along the lines of
    /opt/paparazzi/arm-multilib/bin/arm-none-eabi-gdb var/<airframe>/ap/ap.elf
    Replace <airframe> with the name of the airframe that has been built.
  1. Now connect GDB to the board
    target remote localhost:3333
  2. Now we need to set some break points in the code.
    In this example the ap target was part of the rotorcraft and main.c contains the main program. Open rotorcraft sw/airborne/firmwares/rotorcraft/main.c and find a line at which you'd like to set a break point.
    break main.c:113
  3. Stop the currently running code
    monitor reset halt
  4. Reset the code back to the start
    monitor reset init
  5. Now we can run the program which will stop at the break point we set.
    continue

Black Magic Probe specific

  1. Start GDB for arm
    Open GDB with the correct binary file
    /opt/paparazzi/arm-multilib/bin/arm-none-eabi-gdb ./var/AIRFRAME/ap/ap.elf
    Set Black Magic Probe as Target over the serial link (see ls /dev/ttyACM*):
    target extended-remote /dev/ttyACM0
    Probe via JTAG to get a list of devices:
    mon jtag_scan
    (for Lisa/S, use swdp_scan instead of jtag_scan)
    Attach to a device:
    attach 1
  2. Happy Debugging!

Useful GDB commands

Also look at DevGuide/GDB_OpenOCD_Debug#GDB for general GDB commands

To display some commands for BMP

monitor help

example output fot STM32F4

General commands:
	version -- Display firmware version info
	help -- Display help for monitor commands
	jtag_scan -- Scan JTAG chain for devices
	swdp_scan -- Scan SW-DP for devices
	targets -- Display list of available targets
	morse -- Display morse error message
	connect_srst -- Configure connect under SRST: (enable|disable)
ARM Cortex-M specific commands:
	vector_catch -- Catch exception vectors
STM32F4 specific commands:
	erase_mass -- Erase entire flash memory
	option -- Manipulate option bytes

  • We probably want to ignore the interrupt calls for the moment so we can step through the code as it's being called. Note that we don't always want to do this. (STM32 command only)
    monitor cortex_m3 maskisr on
  • A stack trace can be printed with the command
    bt
  • show the variable of a variable
    print i2c1.status
  • Show (eXamine) the value of the 9 bytes hardware register at address 0x40005800 and show them in hex format:
    x/9x 0x40005800
  • In some cases you may not be able to access some memory areas in the mcu, in that case you should try:
    set mem inaccessible-by-default off

.gdbinit for BMP

The standard commands like setting the ttyACM0 port, searching for targets and attaching one can be automated. Either with a ".gdbinit" file or if your work with Eclipse, there is a box at Debug configutations/Startup.

One Example from armstrap

target extended-remote /dev/ttyACM0
mon swdp_scan
attach 1
monitor vector_catch disable hard
set mem inaccessible-by-default off
set print pretty

Setting up .gdbinit for BMP and gdb-regview

If you use gdb just with a BMP, you can set some initialization commands in ~/.gdbinit that will run when gdb is started, improving workflow.

A very useful plug-in called gdb-regview (available on GitHub) can really speedup debugging stm32 processors by providing a pretty-printed summary of register contents.

A sample file for debugging Lisa/M 2.0 would be:

set target-async on
set mem inaccessible-by-default off
#for gdb-regview plugin
source /path/to/gdb-regview/gdb-regview.py
regview load /path/to/gdb-regview/defs/STM32F10X_CL.xml
tar ext /dev/BMP_DEVICE
mon version
mon swdp_scan
att 1

This should be saved in ~/.gdbinit.

Then, after one starts gdb as described above, you can view registers easily, for example:

(gdb) regview show ADC_CR1

Load new binary from gdb with BMP

It is also easy to rebuild and reload a program from inside gdb. Calling make from the gdb command line will call make in your current directory:

(gdb) make

To load a new elf file into gdb after compiling elsewhere (only required when changing the name of the file):

(gdb) file file_name.elf

To upload the binary as per the currently loaded elf:

(gdb) load

This assumes you have attached to the target already (as per the .gdbinit example just above).

To restart the program from the beginning:

(gdb) run

and enter y.

gdb should detect that the elf has changed when loading the new binary, so if the file name has not changed, one should just be able to rebuild (make from inside gdb if appropriate) and then call load and run.