BeagleBoardOpenOCD
This page is about how to use open source OpenOCD JTAG software with BeagleBoard. With this, it will be possible to have OMAP3 JTAG debug using cheap JTAG hardware, e.g. Flyswatter.
As of April 2009, OpenOCD has basic support for OMAP3 on Beagle Board, but still lacks ARM Cortex A8 support. This is work in progress (some history).
Status:
- You need at least OpenOCD revision 1570 (using svn). With this revision you will have basic access to OMAP3 and CoreSight components can be accessed. This does mean, that OpenOCD is able to configure scan chain correctly to access ARM TAP ("JTAG controller") and explore CoreSight AccessPoints.
- Next step is to add ARM Cortex A8 support, i.e. ARM Cortex A8 awareness to OpenOCD (still open)
- Recent status as of June 2009:
- Status summary
- Magnus Cortex A8 sample code (needs clean up and adaption for recent OpenOCD trunk)
Contents
Hardware
To be able to use OpenOCD with OMAP3 based BeagleBoard, make sure that your JTAG Dongle supports:
- 1.8V devices. Many JTAG dongles are 3.3V only! Verify that your dongle supports 1.8V! Else the dongle will overpowering the input to OMAP3 and may cause damage.
- Your JTAG dongle is able to switch EMU0 & EMU1 pins high.
Flyswatter dongle supports both requirements. If you use BeagleBoard Adapter Kit with Flyswatter, make sure you plug the JTAG adapter the correct way. There are several possible ways, though. See connection picture how to do it the right way. In contrast to the picture EMU0 & EMU1 jumpers at JTAG adapter should be both at 1-2 position (touching J2).
Build OpenOCD
OpenOCD build instructions describe how to build OpenOCD. For questions you can use OpenOCD Mailing list.
Get OpenOCD code via svn:
> svn checkout svn://svn.berlios.de/openocd/trunk openocd
For Flyswatter you additionally need libftd2xx or libFTDI. While libFTDI is available in source, libftd2xx is supposed to be 50% faster than libFTDI. The libtfd2xx binaries are available booth as shared library or linkable archive.
If you downloaded OpenOCD svn and have libftd2xx or libFTDI, build OpenOCD (assuming you extracted/built FTDI library already):
> cd openocd > ./bootstrap > ./configure --enable-ft2232_ftd2xx --with-ftd2xx-linux-tardir=<path_to>/libftd2xx0.4.16 --prefix=/home/user/bin/openOCD or (depending which FTDI library you use, see above) > ./configure --enable-ft2232_libftdi --prefix=/home/user/bin/openOCD > make > make install
Note: By default (make & make install) only .info documentation is installed. You can get PDF or HTML documentation by
make pdf
or
make html
Resulting documentation can be found in openocd/doc, then.
Note: If you like to save some disk space and don't plan to debug OpenOCD binary itself, you can strip this (remove unneeded debug symbols):
> cd <openocd_install_dir>/bin > strip openocd
(e.g. with OpenOCD 1.0 this reduced binary size from ~3MB to ~700kB)
Note: If you don't have libftdi in standard path, you might like to extend library search path:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<path_to>/lib
if you e.g. get
> ./openocd ./openocd: error while loading shared libraries: libftdi.so.1: cannot open shared object file: No such file or directory
Starting OpenOCD
OpenOCD runtime is controlled by several configuration files. OpenOCD comes with basic configuration files for BeagleBoard (board/ti_beagleboard.cfg) and OMAP3 (target/omap3530.cfg).
Assuming that you use Flyswatter and it is switched on (attached to USB), you can now start OpenOCD with:
openocd -s <path_to_config_files> // e.g. <path_of_openocd_install_dir>/lib/openocd -f <path_to_jtag_interface> -f <path_to_beagle_config>
This should result in
> openocd -s lib/openocd/ -f interface/flyswatter.cfg -f board/ti_beagleboard.cfg Open On-Chip Debugger 1.0 (2009-04-29-20:38) svn:1570 BUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS $URL: svn://svn.berlios.de/openocd/trunk/src/openocd.c $ jtag_speed: 1 Warn : JTAG command queued, while TRST is low (TAP in reset) current endstate: RUN/IDLE Info : JTAG tap: omap3.jrc tap/device found: 0x0b7ae02f (Manufacturer: 0x017, Part: 0xb7ae, Version: 0x0) Info : JTAG Tap/device matched Warn : no telnet port specified, using default port 4444 Warn : no gdb ports allocated as no target has been specified Warn : no tcl port specified, using default port 6666
This shows that your (Flyswatter) JTAG dongle basically works and that you are able to see OMAP3 JRC. OpenOCD now runs as deamon.
Controlling OpenOCD
Once OpenOCD runs as daemon like above, you can connect using telnet or GDB
telnet
Connect to OpenOCD daemon. Assuming you do it on your local machine, open a second terminal window and do (assuming port 4444 as configured in above openocd.cfg):
> telnet localhost 4444 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Open On-Chip Debugger >
This should give you
Info: accepting 'telnet' connection from 0
in window where OpenOCD daemon is started.
At OpenOCDs telnet prompt you can now issue OpenOCD commands. E.g. help should result in
> help cpu <name> - prints out target options and a comment on CPU which matches name debug_level adjust debug level <0-3> drscan execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ... endstate finish JTAG operations in <tap_state> exit exit telnet session fast fast <enable/disable> - place at beginning of config files. Sets defaults to fast and dangerous. fast_load loads active fast load image to current target - mainly for profiling purposes fast_load_image same args as load_image, image stored in memory - mainly for profiling purposes find <file> - print full path to file according to OpenOCD search rules ft2232_device_desc the USB device description of the FTDI FT2232 device ft2232_latency set the FT2232 latency timer to a new value ft2232_layout the layout of the FT2232 GPIO signals used to control output-enables and reset signals ft2232_serial the serial number of the FTDI FT2232 device ft2232_vid_pid the vendor ID and product ID of the FTDI FT2232 device gdb_breakpoint_override hard/soft/disabled - force breakpoint type for gdb 'break' commands.The raison d'etre for this option is to support GDB GUI's without a hard/soft breakpoint concept where the default OpenOCD behaviour is not sufficient gdb_detach gdb_flash_program enable or disable flash program gdb_memory_map enable or disable memory map gdb_port daemon configuration command gdb_port gdb_report_data_abort enable or disable report data help Tcl implementation of help command init initializes target and servers - nop on subsequent invocations interface try to configure interface irscan execute IR scan <device> <instr> [dev2] [instr2] ... jtag perform jtag tap actions jtag_device jtag_device <ir_length> <ir_expected> <ir_mask> jtag_khz same as jtag_speed, except it takes maximum khz as arguments. 0 KHz = RTCK. jtag_nsrst_delay jtag_nsrst_delay <ms> - delay after deasserting srst in ms jtag_ntrst_delay jtag_ntrst_delay <ms> - delay after deasserting trst in ms jtag_rclk fallback_speed_khz - set JTAG speed to RCLK or use fallback speed jtag_reset toggle reset lines <trst> <srst> jtag_speed set jtag speed (if supported) log_output redirect logging to <file> (default: stderr) ocd_array2mem convert a TCL array to memory locations and write the values ocd_flash_banks return information about the flash banks ocd_mem2array read memory and return as a TCL array for script processing power_restore Overridable procedure run when power restore is detected. Runs 'reset init' by default. production <serialnumber> - Runs production procedure. Throws exception if procedure failed. Prints progress messages. Implement this procedure in the target script. production Runs test procedure. Throws exception if procedure failed. Prints progress messages. Implement in target script. production_info Displays information on production procedure for target script. Implement this procedure in target script. profile profiling samples the CPU PC reset_config runtest move to Run-Test/Idle, and execute <num_cycles> scan_chain print current scan chain configuration script <filename> - filename of OpenOCD script (tcl) to run shutdown shut the server down sleep <n> [busy] - sleep for n milliseconds. "busy" means busy wait srst_deasserted Overridable procedure run when srst deassert is detected. Runs 'reset init' by default. target configure target targets change the current command line target (one parameter) or lists targets (with no parameter) tcl_port port on which to listen for incoming TCL syntax telnet_port port on which to listen for incoming telnet connections verify_ircapture verify value captured during Capture-IR <enable|disable> version show OpenOCD version virt2phys translate a virtual address into a physical address xsvf run xsvf <file> flash bank flash bank <driver> <base> <size> <chip_width> <bus_width> <target> [driver_options ...] mflash bank mflash bank <soc> <base> <chip_width> <bus_width> <RST pin> <WP pin> <DPD pin> <target #> nand device pld device
Now, we can try to print recent OMAP3 scan chain configuration and enable Cortex-A8 manually (by configuring JRC):
> scan_chain TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr ---|--------------------|---------|------------|------------|------|------|------|--------- 0 | omap3.cpu | n | 0x00000000 | 0x0b6d602f | 0x04 | 0x01 | 0x00 | 0x0f 1 | omap3.jrc | Y | 0x0b7ae02f | 0x0b7ae02f | 0x06 | 0x01 | 0x0f | 0x3f > jtag tapenable omap3.cpu Enabling Cortex-A8 @ OMAP3 Cortex-A8 @ OMAP3 enabled 1 > scan_chain TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr ---|--------------------|---------|------------|------------|------|------|------|--------- 0 | omap3.cpu | Y | 0x00000000 | 0x0b6d602f | 0x04 | 0x01 | 0x00 | 0x0f 1 | omap3.jrc | Y | 0x0b7ae02f | 0x0b7ae02f | 0x06 | 0x01 | 0x0f | 0x3f
To verify that scan chain is configured correctly, now we should be able to access "ARM" cpu and read ID code of "ARM's" JTAG controller (TAP):
> irscan omap3.cpu 0xE > drscan omap3.cpu 32 0x0 0B6D602F
As mentioned above, next step is now to add ARM Cortex A8 awareness to OpenOCD.
GDB
tbd.
GDB ARM
To debug an ARM target with GNU debugger (GDB), you need a GDB understanding ARM processor. If your ARM cross compilation tool chain doesn't include a GDB, you can easily build it your self.
- Download latest GDB sources. OpenOCD docu recommends to use GDB 6.7 or newer. Here, we use GDB 6.8 which is the recent version while writing this.
- Extract, configure and build GDB for ARM. Afterwards remove temporary stuff. Options are:
- <path_where_ARM_gdb_shall_be_installed_to> : Directory where you want to install the resulting tool to. E.g. /home/user/arm-gdb/
- <ARM_toolchain_prefix> : The prefix of your ARM GCC toolchain, e.g. arm-linux or arm-none-linux-gnueabi (CodeSourcery tool chain).
> tar xfj gdb-6.8.tar.bz2 > mkdir build-gdb > cd build-gdb/ build-gdb > ../gdb-6.8/configure --prefix=<path_where_ARM_gdb_shall_be_installed_to> --target=<ARM_toolchain_prefix> i686-pc-linux-gnu build-gdb > make -j4 build-gdb > make install build-gdb > cd .. > rm -rf gdb-6.8 build-gdb > export PATH=$PATH:<path_where_ARM_gdb_shall_be_installed_to>/bin
Test:
bin> ./arm-none-linux-gnueabi-gdb GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 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-linux-gnu --target=arm-none-linux-gnueabi". (gdb)
Cortex A8 support
As mentioned above, OpenOCD still lacks ARM Cortex A8 support. Rick Altherr wrote (thanks!) a nice intro how to help with Cortex A8 support for OpenOCD:
The Cortex-M3 support is very similar to Cortex-A8 up to a certain layer. The ARM debug interface is designed as a set of layers that build on each other and can do automatic discovery. The cortex-swjdp support in OpenOCD is a good start, but it assumes which AHB and APB ports are available. The first item would be to verify the cortex-swjdp portion against the documents for the CoreSight debug interface.
To really get started, familiarize yourself with the following docs:
- ARM IHI 0031A (ARM Debug Interface v5) - only available to registered ARM customers
- ARM IHI 0029B (CoreSight v1.0) - only available to registered ARM customers
- ARM DDI 0316D (CoreSight DAP-Lite)
- ARM DDI 0314F (CoreSight Components TRM)
- ARM DDI 0344H (Cortex-A8 TRM, primarily chapter 12)
These should be listed in the right order for getting up to speed. Basically the Cortex-A8 debug registers are accessed externally via CoreSight. CoreSight is an implementation of the ARM Debug Interface v5.
The cortex-swjdp implementation in OpenOCD deals with CoreSight but makes some assumptions about which CoreSight components are available. For Cortex-A8, that will likely need to change a bit as the set of components will be different.
After cortex-swjdp is patched to handle the new components, a cortex-a8 target implementation can be started by using the cortex-swjdp layer to access the various debug registers and memory locations.
For discussion about this, see mail #1, mail #2 and mail #3.
Note: With revision ~1570 the cortex-swjdp module in OpenOCD has been renamed to arm_adi_v5 and updated to remove all dependencies on Cortex-M3 specific features and as far as possible only use the ARM Debug Interface v5 features. The Cortex-M3 specifics has been moved to cortex_m3 module. This is a step in preparing OpenOCD for full Cortex-A8 support.
Using OpenOCD svn revision 1570 you can examine CoreSight APs:
> version Open On-Chip Debugger 1.0 (2009-04-29-20:38) svn:1570 > jtag tapenable omap3.cpu Enabling Cortex-A8 @ OMAP3 Cortex-A8 @ OMAP3 enabled 1 > scan_chain TapName | Enabled | IdCode Expected IrLen IrCap IrMask Instr ---|--------------------|---------|------------|------------|------|------|------|--------- 0 | omap3.cpu | Y | 0x00000000 | 0x0b6d602f | 0x04 | 0x01 | 0x00 | 0x0f 1 | omap3.jrc | Y | 0x0b7ae02f | 0x0b7ae02f | 0x06 | 0x01 | 0x0f | 0x3f > target create omap3.cpu cortex_m3 -endian little -chain-position omap3.cpu > dap apsel 0 ap 0 selected, identification register 0x14770001 > dap info 0 ap identification register 0x14770001 Type is mem-ap AHB ap debugbase 0xffffffff No ROM table present > dap info 1 ap identification register 0x04770002 Type is mem-ap APB ap debugbase 0x80000000 ROM table in legacy format CID3 0xb1, CID2 0x5, CID1 0x10, CID0, 0xd MEMTYPE system memory not present. Dedicated debug bus ROMTABLE[0x0] = 0xd4010003 Component base address 0x54010000, pid4 0x4, start address 0x54010000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x10, PID2 0x2b, PID1 0xb9, PID0, 0x21 ROMTABLE[0x4] = 0xd4011003 Component base address 0x54011000, pid4 0x4, start address 0x54011000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x10, PID2 0x2b, PID1 0xbc, PID0, 0x8 ROMTABLE[0x8] = 0xd4012003 Component base address 0x54012000, pid4 0x0, start address 0x54012000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x9, PID1 0x71, PID0, 0x13 ROMTABLE[0xc] = 0xd4013002 Component not present ROMTABLE[0x10] = 0xd4019003 Component base address 0x54019000, pid4 0x4, start address 0x54019000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x1b, PID1 0xb9, PID0, 0x12 ROMTABLE[0x14] = 0xd401b003 Component base address 0x5401b000, pid4 0x4, start address 0x5401b000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0xb, PID1 0xb9, PID0, 0x7 ROMTABLE[0x18] = 0xd401d003 Component base address 0x5401d000, pid4 0x0, start address 0x5401d000 Component cid1 0xf0, class is Non standard layout CID3 0xb1, CID2 0x5, CID1 0xf0, CID0, 0xd PID3 0x0, PID2 0x9, PID1 0x73, PID0, 0x43 ROMTABLE[0x1c] = 0xd4500003 Component base address 0x54500000, pid4 0x0, start address 0x54500000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x19, PID1 0x71, PID0, 0x20 ROMTABLE[0x20] = 0x0 End of ROM table > dap apsel 1 ap 1 selected, identification register 0x04770002 > dap apsel 2 ap 2 selected, identification register 0x14760010 > dap info 2 ap identification register 0x14760010 Type is jtag-ap ap debugbase 0x00000000 No ROM table present > dap apsel 3 ap 3 selected, identification register 0x00000000 > dap info 3 ap identification register 0x00000000 No AP found at this apsel 0x3 No ROM table present >
ROMTable
To interpret content of above ROMTable, have a look to
- OMAP35x Technical Reference Manual (Rev. B) (spruf98b.pdf, 39622 Kbytes), Table 5-105
- CoreSight Components TRM (ARM DDI 0314F), Table 2-3
- Cortex-A8 TRM (ARM DDI 0344H)
With this, we get (first three entries are in the MPU SS Module, address range 0x54010000 - 0x54018000, part number is given by PID1[3-0] and PID0[7-0]):
ROMTABLE[0x0] = 0xd4010003 Component base address 0x54010000, pid4 0x4, start address 0x54010000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x10, PID2 0x2b, PID1 0xb9, PID0, 0x21
- Part number is 0x921: ETM module. See Cortex-A8 TRM chapter 14.
ROMTABLE[0x4] = 0xd4011003 Component base address 0x54011000, pid4 0x4, start address 0x54011000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x10, PID2 0x2b, PID1 0xbc, PID0, 0x8
- Part number is 0xC08: This is the Debug Register Interface. See table 12-3 in the Cortex-A8 TRM.
ROMTABLE[0x8] = 0xd4012003 Component base address 0x54012000, pid4 0x0, start address 0x54012000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x9, PID1 0x71, PID0, 0x13
- Part number 0x113: This is ????
ROMTABLE[0x10] = 0xd4019003 Component base address 0x54019000, pid4 0x4, start address 0x54019000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x1b, PID1 0xb9, PID0, 0x12
- Part number 0x912: TPIU Module.
ROMTABLE[0x14] = 0xd401b003 Component base address 0x5401b000, pid4 0x4, start address 0x5401b000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0xb, PID1 0xb9, PID0, 0x7
- Part number 0x907: ETB Module.
ROMTABLE[0x18] = 0xd401d003 Component base address 0x5401d000, pid4 0x0, start address 0x5401d000 Component cid1 0xf0, class is Non standard layout CID3 0xb1, CID2 0x5, CID1 0xf0, CID0, 0xd PID3 0x0, PID2 0x9, PID1 0x73, PID0, 0x43
- Part number 0x343: DAP CTL Module.
ROMTABLE[0x1c] = 0xd4500003 Component base address 0x54500000, pid4 0x0, start address 0x54500000 Component cid1 0x90, class is CoreSight component CID3 0xb1, CID2 0x5, CID1 0x90, CID0, 0xd PID3 0x0, PID2 0x19, PID1 0x71, PID0, 0x20
- Part number 0x120: SDTI Module.
Debug Register Interface
With above info about debug register interface and table 12-3 in the Cortex-A8 TRM we are able to access this interface using OpenOCDs mdw command:
> omap3.cpu mdw 0x54011000 0x54011000 15141012
This is the debug ID register. See table 12-11 of Cortex-A8 TRM:
Bits | Field | Value & Function |
---|---|---|
[31-28] | WRP | 0x1 -> 2 WRPs are implemented |
[27-24] | BRP | 0x5 -> 6 BRPs are implemented |
[23-20] | Context | 0x1 -> 2 BRPs have context ID capability |
[19-16] | Debug architecture version | 0x4 -> ARMv7 debug |
[12] | security | 0x1 -> Security extensions implemented |
[7-4] | variant | 0x1 |
[3-0] | revision | 0x2 |
> omap3.cpu mdw 0x54011FF0 0x54011ff0 0000000d > omap3.cpu mdw 0x54011FF4 0x54011ff4 00000090 > omap3.cpu mdw 0x54011FF8 0x54011ff8 00000005 > omap3.cpu mdw 0x54011FFC 0x54011ffc 000000b1
These are the component identification registers. See table 12-51 of Cortex-A8 TRM.