This page is is part of my embedded system notes.

OpenOCD Notes

Contents

Introduction

OpenOCD stands for Open On-Chip Debugger. The project home page is:

http://openocd.sourceforge.net/
and the documentation is at:
http://openocd.sourceforge.net/doc/html/index.html

Overview

While the first chapter of the documentation does try to answer the question "What is OpenOCD?", it could really benefit from a slightly higher overview. Below is what I think are the important aspects of OpenOCD:

With this overview information in hand, it might be worth trying to read the OpenOCD first chapter:
http://openocd.sourceforge.net/doc/html/About.html

Debug Adapter Selection

The next issue is to select with interface adapter to use. The list of supported adapters is in the second chapter:

http://openocd.sourceforge.net/doc/html/Debug-Adapter-Hardware.html
What is really desired is a table that lists the various debug adapters and their various features. Unfortunately, that table does not exist. The table below summarizes the ones I researched:
Vendor Product Host
Interface
RTCK RS-232 Target
Interface
Cost
JTagKey2 480 Mbps Yes ? ? €$75 (OEM)
Signalizer H2 480 Mbps Yes ? ? $79 (Canadian)
Olimex ARM-USB-OCD-H 480 Mbps Yes Yes 20-pin $54.95
Olimex ARM-USB-Tiny-H 480 Mbps Yes No 20-pin $39.95
Tin Can Tools Flyswatter2 480 Mbps Yes Yes 20-pin $89.00
Tin Can Tools Flyswatter 12 Mbps No Yes 14-pin $49.95
SeeedStudio
Dangerous Prototypes
Bus Blaster 2 12 Mbps Yes No 20-pin $34.95
I basically decided that I wanted a USB dongle that used USB 2.0 High Speed mode (480 Mpbs). Further, I was looking for a dongle that supported RTCK (also known as adaptive clocking.) This adaptive clocking issue is discussed in the OpenOCD FAQ:
http://openocd.sourceforge.net/doc/html/FAQ.html#FAQ-RTCK
I only include the Flyswatter (version 1) because I own one of them. For my purposes, the ARM-USB-Tiny-H from Olimex looks like it has the right features at a reasonable cost. The Bus Blaster2 looks nice as well, but it uses the second port on the FT2232H for programming the CPLD rather than for a serial connection.

Bringing Up OpenOCD

The next task is to get OpenOCD installed on your machine. For a Linux distribution that uses .deb packages (e.g. the Ubuntu distribution), a precompiled version of OpenOCD can be obtained via the following command:

    sudo apt-get install openocd				
Unfortunately, there is a good chance this will be an older version of OpenOCD.

Instead, OpenOCD site recommends that you download the source code and compile from scratch. I decided to follow this advice, and my experiences are listed below.

Like many people, I have a downloads directory that I use to download and build software. For Linux, the following tasks get the job done:

    # Create the directories, download the code and unpack:
    cd ~/download	# My down load directory
    mkdir openocd
    cd openocd
    wget http://superb-dca2.dl.sourceforge.net/project/openocd/openocd/0.6.1/openocd-0.6.1.zip
    unzip openocd-0.6.1.zip
    cd openocd-0.6.1						
Now the everything is downloaded.

The most natural thing to do is type (hint: do not do this):

    ./configure
    make
    sudo make install						
Unfortunately, that will create a version of OpenOCD that does not have any transports compiled into it. (I found this out by accident.)

The correct thing to do is to read the README file that explains that you need to add one or more --enable--{interface} options to ./configure.

The correct process is list the contents of the tcl/interface directory:

    ls tcl/interface
    # List of available interfaces is shown:		
Next, find the interface files that correspond to each of your debug adapters. For each .cfg file, search for the wordinterface. In my case, the correct file is tcl/interface/flyswatter.cfg and I get the following:
    grep interface tcl/interface/flyswatter.cfg
    interface ft2232					
In this case, the needed interface is ft2232.

Once you know the correct interface name, read through the README file and follow the instructions to properly configure that interface. In the case of the ft2232 interface, there are two options -- use the proprietary closed source driver from FTDI or use the an open source driver. I selected the latter. Thus, the steps for configuring OpenOCD for my flyswatter are:

    # Get the FTDI libraries for the FTDI USB to serial chip:
    sudo apt-get install libftdi-dev libftdi1
    # Password may be necessary:

    # Get everything cleaned, configured, compiled and installed:
    make clean
    ./configure --enable-ft2232_libftdi
    sudo make install
    # Password may be necessary:				

Until the permissions of the USB connection are fixed up, I run openocd as root using the sudo program. When I run the command, I get the following output results:
    sudo openocd -f interface/flyswatter.cfg -f target/lpc1768.cfg
    #Password may be necessary:
    Open On-Chip Debugger 0.5.0 (2012-04-09-00:20)
    Licensed under GNU GPL v2
    For bug reports, read
        http://openocd.berlios.de/doc/doxygen/bugs.html
    Info : only one transport option; autoselect 'jtag'
    Error: An adapter speed is not selected in the init script. Insert a call to adapter_khz or jtag_rclk to proceed.
    in procedure 'init'						
These error messages are pretty straight-forward.

Section 8 of the OpenOCD documentation explains about the adapter_khz and jtag_rclk features:

http://openocd.sourceforge.net/doc/html/Debug-Adapter-Configuration.html#JTAG-Speed
While the flyswatter2 does support RCLK, the original flyswatter (which I have) does not; so adapter_khz is the command to use for me. The following is what happened next:
    sudo openocd -f interface/flyswatter.cfg \
      -c "adapter_khz 1000" -f target/lpc1768.cfg
    Open On-Chip Debugger 0.5.0 (2012-04-09-00:20)
    Licensed under GNU GPL v2
    For bug reports, read
        http://openocd.berlios.de/doc/doxygen/bugs.html
    Info : only one transport option; autoselect 'jtag'
    1000 kHz
    adapter_nsrst_delay: 200
    jtag_ntrst_delay: 200
    10 kHz
    Info : clock speed 10 kHz
    Error: JTAG scan chain interrogation failed: all ones
    Error: Check JTAG interface, timings, target power, etc.
    Error: Trying to use configured scan chain anyway...
    Error: lpc1768.cpu: IR capture error; saw 0x0f not 0x01
    Warn : Bypassing JTAG setup events due to errors
    Warn : Invalid ACK 0x7 in JTAG-DP transaction
    Polling target failed, GDB will be halted. Polling again in 100ms
    Polling target failed, GDB will be halted. Polling again in 300ms
    Polling target failed, GDB will be halted. Polling again in 700ms
    ...								
In another terminal window, I was able to connect to the OpenOCD network service as follows:
    telnet localhost 4444
    Trying ::1...
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Open On-Chip Debugger
    Polling target failed, GDB will be halted. Polling again in 6300ms
    Polling target failed, GDB will be halted. Polling again in 6300ms
    > 
    ...								
This looks like success to me, since I do not actually have a microcontroller connected to the other end of Flyswatter yet.

Dealing with Linux UDEV

For Linux, there is a file called contrib/openocd.udev that needs to be renamed to 52-openocd.rules:

    cd /tmp
    cp .../contrib/openocd.udev 52-openocd.rules		
After the file is copied over to /tmp. we need to make sure that each user that needs to access in the debug adapter is in the plugdev group. Running the groups command will list all the groups that user is in. If plugdev is not listed, change all occurrences of plugdev in 52-openocd.rules to the different group. For me, I changed plugdev to users using an editor. Finally, copy the file up to /etc/udev/rules.d/.
    cd /tmp
    sudo cp 52-openocd.rules /etc/udev/rules.d			

Eventually, we want to be able to support more than one debug adapter at once so that we can debug a system that has more than one microcontroller. The following URL's, explain how to deal with the semi-random order in which Linux assigns devices that are plugged into USB sub-system using the UDEV system:

The first link gave me the most insight as to what UDEV is doing. The other links are a bit more specific to binding new names to specific links.

The high level concept is that the Linux kernel in conjunction with UDEV manage the contents of the /dev directory. My understanding is that the kernel uses the devfs file system to construct all of the device nodes in /dev. (For Ubuntu, devfs file system is mounted at /sys.) The UDEV system is notified by devfs when there are any additions, modifications, or deletions to /dev. UDEV is responsible for changing permissions, adding symbolic links, etc. to /dev using a bunch of rules files. The system wide rules files live in /lib/udev/rules.d, and the use supplied rules files live in /etc/udev/rules.d.

In general, /sys is organized as a hierarchical tree of device nodes. The USB sub system shows up a tree with a USB root device, zero, one or more, USB hubs (arranged as a tree), with a number of USB devices sprinkled through out the tree.

The first step is to plug the serial USB cable into a USB socket. The first USB serial is assigned to /dev/ttyUSB0. A full dump of such a serial port is found with something like:

    udevadm info -a -p /class/tty/ttyUSB0
								
This results in a fairly long list of data:
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4.3/1-4.3:1.0/ttyUSB0/tty/ttyUSB0':
    KERNEL=="ttyUSB0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4.3/1-4.3:1.0/ttyUSB0':
    KERNELS=="ttyUSB0"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="ftdi_sio"
    ATTRS{latency_timer}=="1"
    ATTRS{port_number}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4.3/1-4.3:1.0':
    KERNELS=="1-4.3:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="ftdi_sio"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceSubClass}=="ff"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{modalias}=="usb:v0403p6001d0600dc00dsc00dp00icFFiscFFipFF"
    ATTRS{supports_autosuspend}=="0"
    ATTRS{interface}=="FT232R USB UART"

  looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-4/1-4.3':
    KERNELS=="1-4.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bMaxPower}==" 90mA"
    ATTRS{urbnum}=="15"
    ATTRS{idVendor}=="0403"
    ATTRS{idProduct}=="6001"
    ATTRS{bcdDevice}=="0600"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="90"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{product}=="FT232R USB UART"
    ATTRS{serial}=="A800I7X0"

{And some more for good measure!}
								
The first section corresponds to the device, the next levels ups correspond to the USB hubs (if any), leading up to the root of the /sys/devices tree.

A rule file has a name of the form ##-name, where ## is a two digit decimal number. Lower numbers are processed before higher numbers. name is user selected name that suggests what the rules file contains. For us, the file name is 52-openocd.rules

The file contains a list of rules, where each rule is on a single line. The left half of the rule is a sequence of one or more patterns to match, and the right have is a sequence of one or more operations to perform.

The patterns are of the form:

and The first three patterns can only match the top-most device listed above. The remaining patterns can only match "parent" devices listed above. The actions that matter for this task are: These actions create symbolic links, change access modes, and device group membership.

In order to properly match the device, at least one KERNEL, SUBSYSTEM, or DRIVER patter must be specified. In our case, KERNEL=="ttyUSB*" and/or SUBSYSTEM=="tty" will work. If neither of these are present, the symbolic link will probably be attached to the wrong device node (e.g. /dev/bus/usb/001/003.)

The serial number, vendor id, and product id are excellent values to further refine the device selection. For example, ATTRS{idVendor}=="0403" and ATTRS{idVendor}=="6001" will match a typical FTDI serial USB cable. ATTRS{serial}=="serial_number" will match a specific serial number.

There is the final catch, the "parent" patterns must only match one parent node. (I do not know why, but what little documentation is out there is pretty adamant about this.)

NXP Checksums

OpenOCD is perfectly happy to let gdb download an executable image into a microcontroller attached to a debug adapter. For the NXP series of microcontrollers, there is an issue concerning checksums.

The ROM bootloader in the NXP LPCxxxx embedded microcontrollers (ARM Cortex M1-4) will not transfer control to the code in flash memory unless the first eight 32-bit words in the flash memory starting at 0x00000000 sum to 0. This quick little consistency check is to prevent transferring control from the ROM bootloader to "incorrect" code in flash memory.

The location where the checksum is stored varies depending upon which version of the chip is used. Some NXP chips store the checksum in the 7th word and others store it in the 5th word. OpenOCD has different variants for the NXP driver. The code below is extracted from OpenOCD and show what the variants are and how the checksum is computed:

http://code.google.com/p/micropendousx/source/browse/trunk/MicropendousX/Vector_Checksum_Calculator.c

The solution to this problem is to have a program that reads in the executable image, computes the correct checksum, and writes the updated executable back out again. I searched the net for such a program and could not find it. So, I wrote my own program to perform the checksum modification called nxp_checksum:

http://gramlich.net/projects/nxp_checksum/nxp_checksum.c
I am providing nxp_checksum to the net just in case other people find it useful.

If the checksum is not properly computed, the following error message will show up from OpenOCD:

    Verification will fail since checksum in image (...) to be written to flash is different from calculated vector checksum (...).
    To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.
								
I suspect that it would not be too difficult for OpenOCD to write the checksum into the correct location, but until it does, at least it detects the problem and lets you know.

Fun with Clocks

Clocking can be a real chore on microcontrollers that have the ability to change their clock speed. The NXP LPCxxxx microcontrollers have this capability. When they first start, they are running off the internal RC oscillator which runs at 4 MHz. In order, to successfully use the JTAG interface, it should be running slower than that. Eventually, the microcontroller can switch over to a PLL (Phase locked loop) connected to an external crystal, at which time the computer can run at a substantially higher speed (e.g. 100 MHz.) The wide disparity in clock speeds causes issues with JTAG clocking.

The simplest solution is to use the RTCK signal that is available on some ARM microcontrollers. If the debug adapter supports RTCK, the debug adapter will automatically adapt to changes in microcontroller clock speed. For example, the LPC176x microcontrollers (QFP-100) have RTCK and the LPC175x (QFP-80) do not. When designing a board, if you have the option of choosing a ARM microcontroller with RTCK support, it can simplify the JTAG clocking issue.

If RTCK is not an option, messing around with clock speeds is needed. The issues are discussed in section 6.2.4 in the OpenOCD documentation:

http://openocd.sourceforge.net/doc/html/Config-File-Guidelines.html#index-config-file_002c-board-22

The basic solution is to start with the debug adapter clock speed slow immediately after a reset. Another command can be used to "jam" a faster clock speed into the microcontroller and then update the adapter clock speed to be faster.

An example of this can be found in the board/mcb1700.cfg configuration file that ships with OpenOCD. This file is reproduced below:

# Keil MCB1700 PCB with 1768
# 
# Reset init script sets it to 100MHz
set CCLK 100000

source [find target/lpc1768.cfg] 

global MCB1700_CCLK
set MCB1700_CCLK $CCLK

$_TARGETNAME configure -event reset-start {
        # Start *real slow* as we do not know the
    # state the boot rom left the clock in
        jtag_khz 10
}

# Set up 100MHz clock to CPU
$_TARGETNAME configure -event reset-init {
    # PLL0CON: Disable PLL
        mww 0x400FC080 0x00000000
    # PLLFEED
        mww 0x400FC08C 0x000000AA
    # PLLFEED
        mww 0x400FC08C 0x00000055

    # CCLK=PLL/4 (=100 MHz)
        mww 0x400FC104 0x00000003
    # CLKSRCSEL: Clock source = internal RC oscillator
        mww 0x400FC10C 0x00000000

    # PLL0CFG: M=50,N=1 -> PLL=400 MHz
        mww 0x400FC084 0x00000031
    # PLLFEED
        mww 0x400FC08C 0x000000AA
    # PLLFEED
        mww 0x400FC08C 0x00000055

        # PLL0CON: Enable PLL
        mww 0x400FC080 0x00000001
    # PLLFEED
        mww 0x400FC08C 0x000000AA
    # PLLFEED
        mww 0x400FC08C 0x00000055

        sleep 50

    # PLL0CON: Connect PLL
        mww 0x400FC080 0x00000003
    # PLLFEED
        mww 0x400FC08C 0x000000AA
    # PLLFEED
        mww 0x400FC08C 0x00000055

        # Dividing CPU clock by 8 should be pretty conservative
        #
        # 
        global MCB1700_CCLK
        jtag_khz [expr $MCB1700_CCLK / 8]

        # Do not remap 0x0000-0x0020 to anything but the flash (i.e. select
        # "User Flash Mode" where interrupt vectors are _not_ remapped,
        # and reside in flash instead).
        #
        # See Table 612. Memory Mapping Control register (MEMMAP - 0x400F C040) bit description
        # Bit Symbol Value Description Reset
        # value
        # 0 MAP Memory map control. 0
        # 0 Boot mode. A portion of the Boot ROM is mapped to address 0.
        # 1 User mode. The on-chip Flash memory is mapped to address 0.
        # 31:1 - Reserved. The value read from a reserved bit is not defined. NA
        #
        # http://ics.nxp.com/support/documents/microcontrollers/?scope=LPC1768&type=user

        mww 0x400FC040 0x01
}								
There are two OpenOCD event handlers called reset-start and reset-init. The target event handers are briefly discussed in section 11.5 of the documentation:
http://openocd.sourceforge.net/doc/html/CPU-Configuration.html#Target-Events

The first event handler is called when the processor is reset via the following command issued in GDB:

								
monitor reset halt						
This causes the reset-start event code to be executed. In the example above, this sets the adapter speed to 10 kHz using:
								
jtag_khz 10							
In actually, the jtag_khz command has been superseded by the adapter_khz command.

The code for the second event handler uses a bunch of memory write word (mww) commands to load up and start the on board microcontroller PLL (phase locked loop.) This code can be manually initiated by the following command from GDB:

								
monitor reset init						
After executing this code, the PLL is updated to run at a speed of 100 MHz and the adapter clock rate is updated substantially.

Putting It All Together

The following steps seem to work for me:

  1. The code to downloaded and debugged is compiled using the appropriate Gnu compiler tool chain. In most cases, this involves using a Gnu compiler configured as a cross compiler.
  2. The resultant ELF executable is run through nxp_program.
    nxp_checkusm your_executable_in_ELF_format
  3. Start up gdb. I currently use the gdbtui textual interface, although there are others. It is extremely important that the correct version be started. There is no consistency check between gdb and the OpenOCD server to verify that gdb is correct for the specified microcontroller architecture.
    {correct_arm_toolchain_path}/gdbtui
  4. From gdb load the file to be debugged:
    file your_executable_in_ELF_format
  5. Turn power to the microcontroller on.
  6. Fire up the OpenOCD server with the correct configuration files. I typically do this in a dedicated window so I can see what logging messages OpenOCD emits. For me, the following does the job:
    openocd -f interface/flyswatter.cfg -f board/robus_uc1754.cfg
  7. Connect gdbto the OpenOCD server.
    target remote localhost:3333
  8. Force the microcontroller into a halt state from which OpenOCD can wiggle the JTAG lines.
    monitor reset halt
  9. Force the microcontroller to run faster by triggering the code connected to the reset-init event.
    monitor reset init
  10. Force the new code to be downloaded from gdb to the microcontroller through the OpenOCD server.
    load
  11. Force the microcontroller to reset again. The clock is again slow because the reset-start event got triggered:
    monitor reset halt
  12. Plant a breakpoint on main:
    break main
  13. Let the microcontroller execute until it hits the breakpoint ad main:
    continue
  14. While the microcontroller has already executed code to increase the clock speed, the OpenOCD server does not know this. So force the debug adapter back up to a reasonable speed:
    monitor adapter_khz 6000
From here on out the code can be debugged using the usual breakpoints, step, next, continue, and Control-C to interrupt execution.

Just as a random comment, I found the article over at:

http://fun-tech.se/stm32/OpenOCD/gdb.php
to be useful.

Connectors

This section has been replaced by the next section called Connectors Revisited. This section is retained only because it contained the original research.

I will start this section with the following quote:

The wonderful thing about standards is that there are so many of them to choose from. -- Grace Hopper
Along those line, the URL below lists a bunch of different JTAG pin-outs:
http://www.jtagtest.com/pinouts/
When designing a printed circuit board, the PCB designer has to select a connector and assign the signals to the connector. My thoughts on selecting a JTAG connector follow.

While there are many possible JTAG connectors, I have selected three to focus the discussion:

The table below indicates which signals are present on which connectors:

Signal ARM-20 ARM-14 AVR JTAG Altera Byte Blaster
(GND) Ground 4,6,8,10,12,14,16,18,20 2,4,6,8,10,14 2,10 2,10
(VREF) Voltage Reference 1 1,13 4 4
(nTDST) Test Reset 3 3 6 -
(TDI) Test Data In 5 5 9 9
(TMS) Test Mode Select 7 7 3 3
(TCK) Test Clock 9 9 1 1
(TDO) Test Data Output 13 11 3 3
(nSRST) System Reset 15 12 6 -
(VSUPPLY) Voltage Supply 2 - - -
(RTCK) Return Test Clock 11 - - -
(DBGRQ) Debug Request 17 - - -
(DBGACK) Debug Acknowledge 19 - - -

When designing a printed circuit board, a connector choice is needed. These are my thoughts on the JTAG connector topic:

That more or less covers the JTAG connector discussion for now. There is some further discussion about ICSP (In-Circuit Serial Programming) that needs to occur.

I know that the NXP LPC13xx and LPC17xx microcontrollers have a serial boot loader in the ROM. When the RESET pin on the microcontroller is triggered, the code in the ROM is executed. This code checks one pin to see if it is low, and if so, enters a serial boot loader that allows the microcontroller to be programmed using one of the microcontroller UART's.

I suspect, but do not know, that other ARM embedded microcontrollers do the same thing. I have "standardized" on a common 5-pin connector for doing ISCP:

Pin Signal Description
1 GND Ground
2 TXD Transmit Data
3 nRESET System Reset
4 RXD Receive Data
5 nPGM Program (and LED)
I have a little board that takes the 6 pins from a 3.3V FTDI RS-232 cable, adds a reset and program button, provides 5 signals above. In order to program a microcontroller, I hold the [Program] button down followed by depressing the [Reset] button to force the microcontroller into the serial boot loader. I then run a program called nxpprog to download a .hex file into the microcontroller. I depress the [Reset] (but leave the program button unchanged.) Lastly, there is an LED connected to the nPROG signal. My blinky program can turn drive the nPROG signal on and off to cause the LED to blink. It means that I no longer feel obligated to put an LED on all of my boards.

So the quest arises, how should these microcontrollers be programmed. Obviously, they can be programmed via either the serial boot loader or the JTAG interface. Frankly, the serial boot loader seems to load programs in faster than the JTAG interface. I seem to be getting about 4K/second with the serial boot loader and 2.5K/second for the JTAG.

When I am debugging a PCB, I am perfectly happy to solder a JTAG connector to the edge of the board. For mass product, something faster is required. Currently, I am leaning towards the connector below:

http://tag-connect.com/
The TC2030-IDC-NL looks like it would be pretty reasonable for doing serial programming. What is nice is that no additional connector needs to be installed. The amount of board real estate require appears to be quite reasonable. Since there are 6 pins available, I am thinking that the sixth pin should be hooked up to a voltage supply so that both power and programming can be done using a single connector.

The question arises of whether I should have a connector that merges both JTAG programming/debugging and serial programming?

Many of the newer JTAG dongles out there are using the FT2232 chip that has two serial channels on one chip. One channel is put into MSSP (Master Synchronous Serial Port) mode for the JTAG and the other is a standard serial port. The serial port signals are typically exported on a DB9 with RS232 voltage levels.

The serial port can be used for both serial programming and ad hoc debugging. For ad hoc debugging, a little command line interpreter can be used to issue commands. In addition, trace information can be output to the to the serial port for subsequent logging and data visualization.

Given that the only connector that has RTCK is the ARM-20, some sort of rewire PCB is needed to get down to a smaller connector. I am leaning towards a 14-pin connector that can be soldered onto the edge of a board. This would include the "ARM-10" pin-outs and an additional 4 pins for serial download:

14-Pin AVR JTAG Connector
Pin Use Use Pin
1 (TCK) Test Clock (GND) Ground 2
3 (TDO) Test Data Output (VREF) Voltage Reference 4
5 (TMS) Test Mode Select (nSRST) System Reset (*) 6
7 (RTCK) Return Test Clock (nTRST) Test Reset (*) 8
9 (TDI) Test Data Input (GND) Ground 10
11 (TXD)Transmit Data (VSUPPLY) Voltage Supply 12
13 (RXD) Receive Data (nPROG) Program 14

In addition, there would be a chunk of board area set aside for TC2030 connector with the following pin-outs:

Pin Signal Description
1 GND Ground
2 TXD Transmit Data
3 nRESET System Reset
4 RXD Receive Data
5 nPGM Program (and LED)
6 VSUPPLY Voltage Supply

Connectors Revisited

I have been struggleing with the connector issue. Rather than delete my previous thoughts, I decided to just add this new section.

The requirements that must be met are:

If would be desirable if:

The ability to do in circuit serial programming without a connector is pushing me towards a "pogo" connector allows the board to be placed down and programmed. This requires that GND, TXD, RXD, VSUPPLY, nSRST, nPROG be on the bottom of the board and suitable for use with a "pogo" connector. An example is the Mil-Max 821-22-008-10-003101

Originally, the plan was that the JTAG/ICSP connector would look more like PCB edge connectors. The plan was to solder on a regular male header to the edge. The theory was that this would save some board real estate. In practice, not enough board real estate was save to make it worth the effort. Instead a standard 2 × 8 connector (2.54mm pitch) is used.

The first try at the connector looks as follows:

16-Pin JTAG Connector
Pin Use Use Pin
1 (GND1) Ground (RXD) Receive Data 2
3 (VREF) Voltage Reference (TXD) Transmit Data 4
5 (nTRST) Test Reset (GND2) Ground 6
7 (RTCK) Return Test Clock (nPROG) Program 8
9 (TCK) Test Clock (SWDCLK) (VSUPPLY) Voltage Supply 10
11 (TDO) Test Data Out (SWO) (nSRST) System Reset 12
13 (TDI) Test Data In (VPROG) Program Voltage 14
15 (TMS) Test Mode Select (SWDIO) (unused) 16
bold signals "wiggle" and it is desired that they be separated by a non "wiggle" signal line to lower cross talk issues:

The second try:

16-Pin JTAG Connector
Pin Use Use Pin
16 (unused) (TMS) Test Mode Select (SWDIO) 15
14 (nPROG) Program (TDI) Test Data In 13
12 (nSRST) System Reset (TDO) Test Data Out (SWO) 11
10 (VUNREG) Unregulated Voltage Supply (TCK) Test Clock (SWDCLK) 9
8 (VREF) Voltage Reference (RTCK) Return Test Clock 7
6 (GND2) Ground (GND1) Ground 5
4 (TXD) Transmit Data (nTRST) Test Reset 3
2 (RXD) Receive Data (unused) 1

The purpose of VUNREG (unregulated voltage supply) pin is to provide some flexibility in powering devices.

There are three objects in this discussion -- 1) a module with an embedded microcontroller on it, 2) a serial programmer board with the 8-pin "pogo" connector that touches the bottom 8 pins of the JTAG/ICSP pads, and 3) an JTAG device (i.e. something that can talk to OpenOCD.) I will call these MODULE, SERIAL, and JTAG, respectively. MODULE can be connected to either SERIAL or JTAG, but not both at the same time.

The goal is to support three scenerios:

VUNREG is required to be between 6V and 30V.

MODULE has an on board regulator that takes VUNREG and regulates it down to a useful regulated voltage for further use. The regulator is typically a low drop out (LDO) voltage regulator.

All possible power sources connected to VUNREG must go through a current direction protection diode. The current direction protection diode does the following.

The table below summarizes:
MODULE JTAG SERIAL Discussion
no no no No power on VUNREG
no no yes SERIAL supplies power
no yes no JTAG supplies power
no yes yes Simultaneous JTAG and SERIAL is not allowed
yes no no MODULE supplies power
yes no yes Higher voltage of MODULE or SERIAL supplies power
yes yes no Higher voltage of MODULE or JTAG supply power
yes yes yes Simultaneous JTAG and SERIAL is not allowed

The JTAG device needs to be able to get power from two or more sources. For the sake of discussion, we will assume that the JTAG device wants to be able to get power from:

A further assumption is that the JTAG device runs at 3.3 volts. This means that it is possible to derive 3.3 volts from the 5 volts available from USB5V.

The solution here is the same. VUNREG, USB5V and JACK all supply power to the JTAG voltage regulator through a protection diode. The source with the highest voltage will provide the power.

As a side note for Robus modules, it should be noted that VUNREG is tied to the LPWR pins of the bus connector. Each Robus module does not need a protection diode. However, the device that does connect to the LPWR wires does need to have the protection diode.

As a further side note for Robus modules, the shroud of the shrouded male header for the Robus connector is allowed to overlap the JTAG/ICSP connector holes. If it is necessary to access the JTAG/ICSP pins, the shroud can be pulled off and still be quite serviceable.

Cross Compiling OpenOCD

I found the following scripts for cross compiling OpenOCD from Linux to Windows using mingw:

https://github.com/caspencer/openocd-mingw32-build-scripts
Naturally I could not leave the scripts alone and munged them together to form my own script:
http://gramlich.net/projects/openocd/cross.sh
This script download libusb, libftdi, and openocd and compiles them all with an embedded ARM cross compiler. The resulting openocd appears to execute just fine on one my ARM based Linux boxes.

As a side note, ARM based Linux box (a rooted version of the Iomega iConnect) does not have enough power to run my flyswatter. I needed to add a power USB hub to make if work.

Wireless Access

I am starting to research wireless access points. It is important that I be able to connect to specific ports OpenOCD ports to support GDB and such. Some random links below:

http://www.dd-wrt.com/wiki/index.php/Wireless_Access_Point
http://wireless.wikia.com/wiki/Wi-Fi_How_To#Use_a_wireless_router_as_a_wireless_access_point

Debug Adapter PCB?

After reading the specification sheet for the FTDI FT2232H chip:

http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf
it looks like making a PCB for a JTAG dongle is quite easy. It looks like it takes the following parts:

In addition, there is a program provided by FTDI that is used to load up the serial EEPROM to configure it for MSSP mode, provide a serial number etc. The amount of code required to add a new debug adapter into OpenOCD looks quite nominal.

RTOS_Support

http://www.freertos.org/index.html?http://www.freertos.org/portLM3Sxxxx_Eclipse.html
http://stackoverflow.com/questions/3539970/configuring-gcc-with-freertos-and-openocd

Future Work and Issues

The following issues need to be worked on:

A random link.


Copyright © 2012 by Wayne C. Gramlich All rights reserved.