Configuring openOCD with FTDI JTAG interface
The FTDI chips are not only good for transcoding USB/UART transmissions; higher versions extend the feature list to emulate JTAG interfaces. There are many versions of the chip available on the market, but when it comes to the JTAG interface, it all boils down to configuring the ports and setting up the GDB server hosted by software like OpenOCD.
The largest version of the chip is the FT4232H, which allows
emulation of up to two JTAG interfaces on the ADBUS and
BDBUS ports. We will use this chip as an example for
writing an OpenOCD configuration to utilize one of the JTAG
interfaces.
+-----+---------+-----------+--------+
| Pin | Name | JTAG Port | MSSE |
+-----+---------+-----------+--------+
| 16 | ADBUS0 | 0 | TCK |
| 17 | ADBUS1 | 0 | TDI |
| 18 | ADBUS2 | 0 | TDO |
| 19 | ADBUS3 | 0 | TMS |
+-----+---------+-----------+--------+
| 26 | BDBUS0 | 1 | TCK |
| 27 | BDBUS1 | 1 | TDI |
| 28 | BDBUS2 | 1 | TDO |
| 29 | BDBUS3 | 1 | TMS |
+-----+---------+-----------+--------+
Each port consist four (3 - mandatory, and 1 - optional ) JTAG connectors:
- TCK - Test clock
- TDI - Test data input
- TDO - Test data output
- TMS - Test mode select (optional)
The optional TRST (test reset) dedicated pin is
not supported by the JTAG emulation peripheral. OpenOCD requires to
specify the nTRST signal to operate correctly,
therefore we need to allocate one more GPIO.
The driver uses a signal abstraction to enable Tcl configuration files to define outputs for one or several FTDI GPIO. These outputs can then be controlled using the ftdi set_signal command. Special signal names are reserved for nTRST, nSRST and LED (for blink) so that they, if defined, will be used for their customary purpose. Inputs can be read using the ftdi get_signal command.
For this purpose we are going to use ADBUS4 as the
nTRST signal, and instruct OpenOCD about the reset
method by using reset_config trst_only.
Writing the openOCD configuration file
Defining the FTDI chip
First, OpenOCD needs to be informed that we will use an FTDI chip
as the driver for our communication. This is done by setting the
adapter driver to ftdi, resulting in the
command adapter driver ftdi. Next, we specify the
transport layer, which in this case is JTAG, using the command
transport select jtag. We also need to set the
operating speed in kHz with adapter speed 10000. If
there are issues with connection stability, such as when using long
wires, the speed should be decreased. Lastly, before we move on to
pin configuration, we need to specify the VID (Vendor ID) and PID
(Product ID) of the FTDI chip, which can be found in the datasheet
for the part. The documentation provides the following
statement:
If no EEPROM is connected (or the EEPROM is blank), the FT4232H uses its built-in default VID (0403), PID (6011) Product Description and Power Descriptor Value. In this case, the device will not have a serial number as part of the USB descriptor.
Basing on that we can specify the FTDI VID and PID with
ftdi_vid_pid <VID> <PID>.
Defining used JTAG peripheral
The configuration needs to be aware which JTAG peripheral
available on the FTDI chip supposed to be used by the session. In
FT4232H we have two possibilities, either port 0 or 1. We can select
the port with ftdi_channel <port>. In case FTDI
with only one JTAG is used this configuration is not necessary.
Configuring pins
To configure the GPIO pin direction, OpenOCD uses the
ftdi_layout_init and ftdi_layout_signal
functions.
First, we define the direction of the pins on the port using
ftdi_layout_init, where 1 means output and
0 means input. We also need to define the default state
as the second argument. All port pins will be set to low, except for
TMS, which will be set to high. This results in the
configuration line:
ftdi_layout_init 0xfb 0x08
It’s also important to define the nTRST signal,
which is used to trigger the device reset. To instruct OpenOCD where
to find the signal, we use ftdi_layout_signal. We need
to specify the name of the signal, mask for the data bit, and enable
open collector mode for the pin.
The nTRST signal will use ADBUS4, which
translates to the mask 0x0010 (the mask accounts for
all available ports). The open collector output type will be the
same as the data mask. This results in the following command:
ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010
To make this clearer, we can construct a diagram of used masks.
Pin name | ADBUS7 | ADBUS6 | ADBUS5 | ADBUS4 | ADBUS3 | ADBUS2 | ADBUS1 | ADBUS0 | Mask
Direction | OUT 1 | OUT 1 | OUT 1 | OUT 1 | IN 0 | OUT 1 | OUT 1 | OUT 1 | 0xfb
State | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0x08
Data | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0x0010
OC En. | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0x0010
Final configuration for FTDI
To conclude all necessary configuration that must be added to the openOCD config files we end up with example script:
adapter driver ftdi
transport select jtag
adapter speed 10000
ftdi_vid_pid 0x0403 0x6011
ftdi_channel 0
ftdi_layout_init 0xfb 0x08
ftdi_layout_signal nTRST -data 0x0010 -oe 0x0010
reset_config trst_only
Finally, you must add all configuration related to the MCU architecture that is going to be used.