Olimex ARM-USB-OCD


Don't have a lot of money to spend on an ABATRON BDI-2000 JTAG unit (USD $2700)? Why not look into a simpler, cheaper, solution? While the parallel port wigglers may be one solution, they are not one that I have found to be very reliable. The USB wiggler appears to be a more effective solution, although a little more expensive than a wiggler. I ordered mine from Sparkfun Electronics for about USD $70.

The unit comes with an installation CD to install a lot of Windows stuff (probably under cygwin). Since I abandoned the use of MicroSoft Windows as a developement platform, the CDROM is pretty much useless for a Linux user. Heh, seems that these days, everything sold must have some sort of a Windows CDROM of some kind...

This page describes how I setup OpenOCD and the Olimex ARM-USB-OCD JTAG pod to work on a Mandriva 2007 Linux system (2.6 kernel).


TopInstall the libftd2xx0 driver

Unfortunately, the OPENOCD website seems to lean heavily towards the Windows user, but does make references to using thier software with Linux. Curious. However, After doing some reading from various websites and discussion forums, I finally divined that I should be using the libftd2xx0 version 4.13 driver .
Get the driver for the Linux operating system from the ftdichip website untar it and follow the README.DAT installation instructions. The version that I used is 4.13 and did the following under Mandriva 2007, as root:

  • copied the dynamic lib with cp libftd2xx.so.0.4.13 /usr/local/lib/
  • created symlink of ln -s /usr/local/lib/libftd2xx.so.0.4.13 /usr/local/lib/libftd2xx.so
  • created symlink of ln -s /usr/local/lib/libftd2xx.so.0.4.13 /usr/lib/libftd2xx.so
  • copied ftd2xx.h and WinTypes.h into /usr/include
  • edited /etc/ld.so.conf and added the line /usr/local/lib
  • run ldconfig from a console to rebuild the runtime loader database of available libraries
  • edited /etc/fstab to add a line of none /proc/bus/usb usbfs defaults,devmode=0666 0 0
  • run mount -a from a console to mount the new USB filesystem

    Whenever you boot the system, this USB filesystem and libary will there to use. You do not need to do these steps again.


  • TopBuilding OpenOCD

    Now that the communications layer to the ftdi232 chip has been installed, it is now time to build the layer that will reside between that and gdb (insight). First, we get the OpenOCD source from the svn repository. As a user, make a directory mkdir ~/OpenOCD and change to it cd ~/OpenOCD. Fetch the source with svn checkout http://svn.berlios.de/svnroot/repos/openocd/trunk. This will pull in the svn sources for OpenOCD.

  • go into the downloaded dir: cd trunk

    Next, we read the INSTALL textfile, it is good to do this, things may change! I built OpenOCD, as a user, by following the INSTALL steps of:

  • ./bootstrap to create the configure file.
  • prepare the source: ./configure --enable-ft2232_ftd2xx
  • make to build the binary.
  • as root user, do make install

    This installed 'openocd' in the /usr/local/bin directory.


  • TopCreating the Config File

    If you have looked around on this website, you will see that I am using LPC2000 processors and my own build of ARM binutils, gcc and Insight debugger. If you have something else, YMMV as to these steps. While a GUI is nice, at times, I primarily use command line tools. The Insight debugger is an exception, this is where a GUI is of benefit.

    First off, this is important, NEVER ASSUME! When in doubt, RTFM. In this case, it is 'info openocd'. The method of creating a configuration file has recently changed with openocd. We have two things that have to be specified: the inteface (what type of JTAG there is) and the target (the processor that we are plugged into).

    There is no ready-to-use configuration for an LPC2214 using the Olimex ARM-USB-OCD dongle. We need to build our openocd.cfg file to describe the interface and target. So, in /usr/local/lib/openocd, there is an interface directory and a target directory. I will build my config file with cat /usr/local/lib/openocd/interface/olimex-arm-usb-ocd.cfg /usr/local/lib/openocd/target/lpc2294.cfg > ~/openocd.cfg as the lpc2294 is close enough to the lpc2214.

    I did have to edit this configuration (openocd.cfg) and add 'jtag_speed 2' to slow down the jtag clockrate so that it would see the processor. Otherwise it would come up with an error.


    TopA Quick Test

    At this point, we should have a working JTAG pod. To see if this is so, go to the directory where the newly created openocd.cfg file is located and run openocd. Without having the JTAG connected to the target board, you should see something like this printed out:

    [tom@laptop ~]$ openocd
    Open On-Chip Debugger 1.0 (2008-09-10-22:39) svn:983
    $URL: http://svn.berlios.de/svnroot/repos/openocd/trunk/src/openocd.c $
    jtag_speed: 2
    Error: JTAG communication failure, check connection, JTAG interface, target power etc.
    Error: trying to validate configured JTAG chain anyway...
    Error: Error validating JTAG scan chain, IR mismatch, scan returned 0x00
    Error: Could not validate JTAG chain, continuing anyway...

    This is good! OpenOCD sees the pod! Now, connect up an LPC2000 development board and see if it works with the JTAG on the CPU. Power the development board, plug the JTAG connector into the board, then re-run openocd (you can stop openocd with ctrl-C) as before and I get:

    [tom@laptop ~]$ openocd
    Open On-Chip Debugger 1.0 (2008-09-10-22:39) svn:983
    $URL: http://svn.berlios.de/svnroot/repos/openocd/trunk/src/openocd.c $
    jtag_speed: 2
    Info: JTAG device found: 0x4f1f0f0f (Manufacturer: 0x787, Part: 0xf1f0, Version: 0x4)
    Warning:no telnet port specified, using default port 4444
    Warning:no gdb port specified, using default port 3333
    Warning:no tcl port specified, using default port 6666

    Now, telnet into the openocd daemon to see if that works: 'telnet localhost 4444'. You should connect and get:

    [tom@jtag trunk]$ telnet localhost 4444
    Trying 127.0.0.1...
    Connected to localhost (127.0.0.1).
    Escape character is '^]'.
    Open On-Chip Debugger
    >


    At this point here, we have a working connection to JTAG of the target CPU. You can type 'help' at the command prompt and take a look at some of the commands OpenOCD offers from the telnet prompt. All those commands do seem to work as I was able to erase and program the Flash memory of an LPC2214 board. Ahem, that was after I went back and carefully edited my openocd.cfg file and setup the flash statement to match what was in the LPC2214. If you recall, I just used the lpc2294.cfg file as it was "close enough" to the LPC2214 processor?


    TopTest with Insight Debugger

    Using openocd with Insight (gdb) is very straight forward, if you have used gdb and a remote tcp debug session before. If not, I will walk you through this. First, build your ARM toolchain (I suggest you use my toolchain, but other should work fine as well). You should have openocd still running from the previous test. Launch Insight.

    Insight is really gdb with a pretty face, it does make working with a remote target easier than entering commands into the gdb console command line. From Insight, choose 'File | Target Settings', set the Connections to: 'Target: Remote/TCP', 'Hostname: localhost' and 'Port: 3333'.

    Try to connect to the target now with 'Run | Connect to Target' and you should get a report of 'Successfully Connected'. That is it! You now have a working JTAG POD over the USB + OpenOCD. What is left now is to fine tune the contents of the arm7_ft2232.cfg file and to create a usable target_script.


    TopLPC2214 Config

    I have an LPC2214 project where there is an external 256K x 16bit SRAM connected to it. The SRAM is mapped out at 0x81000000. This is the arm7_ft2232.cfg contents:

    telnet_port 4444
    gdb_port 3333
    interface ft2232
    ft2232_device_desc "Olimex OpenOCD JTAG"
    ft2232_layout jtagkey
    ft2232_vid_pid 0x15ba 0x0003
    jtag_speed 2
    reset_config trst_and_srst srst_pulls_trst
    jtag_device 4 0x1 0xf 0xe
    daemon_startup reset
    target arm7tdmi little run_and_halt 0 arm7tdmi-s_r4
    target_script 0 reset h2214_init.script
    run_and_halt_time 0 30
    working_area 0 0x40000000 0x40000 nobackup
    flash bank lpc2000 0x0 0x40000 0 0 lpc2000_v1 0 14765 calc_checksum
    flash bank cfi 0x80000000 0x400000 2 2 0


    TopInit script for LPC2214

    The target_script referred to in the arm7_ft2232.cfg:

    arm7_9 write_xpsr 0x000000d3 0
    mww 0xE01FC040 0x00000001 #MEMMAP: User flash mode
    mww 0xE01FC080 0x00000000 #PLLCON:
    mww 0xE01FC084 0x00000000 #PLLCFG:
    mww 0xE01FC08C 0x000000AA #PLLFEED:
    mww 0xE01FC08C 0x00000055 #PLLFEED:
    sleep 10
    mww 0xE002C014 0x0D002914 #config P2 pins for 256Kx16 EXRAM.
    mww 0xFFE00004 0x1000040F #config CS1 select at 0x81000000.
    sleep 10
    #arm7_9 force_hw_bkpts enable # program resides in Flash
    arm7_9 force_hw_bkpts disable # program resides in RAM


    TopComments about ARM-USB-OCD

    As with anything, you get what you pay for. The ARM-USB-OCD and OpenOCD do a credible job to replace the ABATRON BDI2000 (I have one of these) but does not perform as well. You can program / erase the flash memory from the telnet session, and you can download code into the target RAM. You can also run breakpoints, and single step, examine registers, etc..

    However, you cannot do these things as quickly as with the BDI2000. For example, to download a 40K program into RAM with the OpenOCD + USB takes about 6 seconds, with the BDI2000 it takes about a second. Single stepping assembler code with the OpenOCD + USB is slow, each step takes about 2 seconds. Single stepping the same code with the BDI2000 is very rapid with no noticable delay.

    It does depend on your expectations. For the price, the ARM-USB-OCD + OpenOCD combination would be great for that occasional "thing", or for Production people to use to bang hardware. I would not use them everyday to do serious code development as I tend to be an impatient chap who dislikes waiting for things to happen. ;-)