Driver for USB-JTAG, Altera USB-Blaster and compatibles
authorCatalin Patulea <cat@vv.carleton.ca>
Sat, 26 Dec 2009 23:05:06 +0000 (15:05 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 26 Dec 2009 23:05:06 +0000 (15:05 -0800)
The 10-pin JTAG layout used with these adapters is used by
a variety of platforms including AVR.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
NEWS
configure.in
doc/openocd.texi
src/Makefile.am
src/jtag/drivers/Makefile.am
src/jtag/drivers/usb_blaster.c [new file with mode: 0644]
src/jtag/interfaces.c
tcl/interface/altera-usb-blaster.cfg [new file with mode: 0644]
tcl/interface/usb-jtag.cfg [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 173d06af81e6dd8207d9aa3a98823196ad7a7c19..e3e813cbae5e9b3528f57d6fe9affec8e41ae856 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ and other issues not mentioned here.
 
 JTAG Layer:
        Support KT-Link JTAG adapter.
+       Support USB-JTAG, Altera USB-Blaster and compatibles.
 
 Boundary Scan:
 Target Layer:
index 7ce79559625f639c2557ce1d4113d21a6b46f911..21edba9203ecde1f3ea569268b32ac0e89f8ad02 100644 (file)
@@ -392,6 +392,14 @@ AC_ARG_ENABLE(ft2232_ftd2xx,
   AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 based devices using the FTD2XX driver from ftdichip.com]),
   [build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no])
 
+AC_ARG_ENABLE(usb_blaster_libftdi,
+  AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]),
+  [build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no])
+
+AC_ARG_ENABLE(usb_blaster_ftd2xx,
+  AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]),
+  [build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no])
+
 AC_ARG_ENABLE(amtjtagaccel,
   AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
   [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
@@ -651,6 +659,20 @@ else
   AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.])
 fi
 
+if test $build_usb_blaster_libftdi = yes; then
+  build_bitbang=yes
+  AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 1, [1 if you want libftdi usb_blaster.])
+else
+  AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 0, [0 if you don't want libftdi usb_blaster.])
+fi
+
+if test $build_usb_blaster_ftd2xx = yes; then
+  build_bitbang=yes
+  AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 1, [1 if you want ftd2xx usb_blaster.])
+else
+  AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 0, [0 if you don't want ftd2xx usb_blaster.])
+fi
+
 if test $build_amtjtagaccel = yes; then
   AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator driver.])
 else
@@ -727,7 +749,7 @@ then
   AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
 fi
 
-if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then
+if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then
   AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
 
   # if we are given a zipdir...
@@ -1001,6 +1023,8 @@ AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
 AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
 AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
 AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_LIBFTDI, test $build_usb_blaster_libftdi = yes)
+AM_CONDITIONAL(USB_BLASTER_DRIVER, test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes)
 AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes)
 AM_CONDITIONAL(GW16012, test $build_gw16012 = yes)
 AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
index 013a31a8df9020271a7aa397d69680310c7571ad..1c20716c9d1e3b38e5da6b9e8addf47095da7a3b 100644 (file)
@@ -310,6 +310,25 @@ chips are starting to become available in JTAG adapters.
 @* Link @url{http://www.hitex.com/index.php?id=cortino}
 @end itemize
 
+@section USB-JTAG / Altera USB-Blaster compatibles
+
+These devices also show up as FTDI devices, but are not
+protocol-compatible with the FT2232 devices. They are, however,
+protocol-compatible among themselves.  USB-JTAG devices typically consist
+of a FT245 followed by a CPLD that understands a particular protocol,
+or emulate this protocol using some other hardware.
+
+They may appear under different USB VID/PID depending on the particular
+product.  The driver can be configured to search for any VID/PID pair
+(see the section on driver commands).
+
+@itemize
+@item @b{USB-JTAG} Kolja Waschk's USB Blaster-compatible adapter
+@* Link: @url{http://www.ixo.de/info/usb_jtag/}
+@item @b{Altera USB-Blaster}
+@* Link: @url{http://www.altera.com/literature/ug/ug_usb_blstr.pdf}
+@end itemize
+
 @section USB JLINK based
 There are several OEM versions of the Segger @b{JLINK} adapter. It is
 an example of a micro controller based JTAG adapter, it uses an
@@ -1989,6 +2008,46 @@ ft2232_vid_pid 0x0403 0xbdc8
 @end example
 @end deffn
 
+@deffn {Interface Driver} {usb_blaster}
+USB JTAG/USB-Blaster compatibles over one of the userspace libraries
+for FTDI chips.  These interfaces have several commands, used to
+configure the driver before initializing the JTAG scan chain:
+
+@deffn {Config Command} {usb_blaster_device_desc} description
+Provides the USB device description (the @emph{iProduct string})
+of the FTDI FT245 device. If not
+specified, the FTDI default value is used. This setting is only valid
+if compiled with FTD2XX support.
+@end deffn
+
+@deffn {Config Command} {usb_blaster_vid_pid} vid pid
+The vendor ID and product ID of the FTDI FT245 device. If not specified,
+default values are used.
+Currently, only one @var{vid}, @var{pid} pair may be given, e.g. for
+Altera USB-Blaster (default):
+@example
+ft2232_vid_pid 0x09FB 0x6001
+@end example
+The following VID/PID is for Kolja Waschk's USB JTAG:
+@example
+ft2232_vid_pid 0x16C0 0x06AD
+@end example
+@end deffn
+
+@deffn {Command} {usb_blaster} (@option{pin6}|@option{pin8}) (@option{0}|@option{1})
+Sets the state of the unused GPIO pins on USB-Blasters (pins 6 and 8 on the
+female JTAG header). These pins can be used as SRST and/or TRST provided the
+appropriate connections are made on the target board.
+
+For example, to use pin 6 as SRST (as with an AVR board):
+@example
+$_TARGETNAME configure -event reset-assert \
+      "usb_blaster pin6 1; wait 1; usb_blaster pin6 0"
+@end example
+@end deffn
+
+@end deffn
+
 @deffn {Interface Driver} {gw16012}
 Gateworks GW16012 JTAG programmer.
 This has one driver-specific command:
index f60feac313683119f911f257ba7a8b5b09787f7f..a566b4d422fdce4cfd98079a4e3fca3dd55de687 100644 (file)
@@ -60,12 +60,16 @@ endif
 if FT2232_LIBFTDI
 FTDI2232LIB = -lftdi -lusb
 else
+if USB_BLASTER_LIBFTDI
+FTDI2232LIB = -lftdi -lusb
+else
 if PRESTO_LIBFTDI
 FTDI2232LIB = -lftdi -lusb
 else
 FTDI2232LIB =
 endif
 endif
+endif
 
 if USBPROG
 LIBUSB = -lusb
index 8ee5ac592b83e27ea267bf4bb8346ffcc0188117..d6113c6012b2841f6221c01c55643686ed34d0c3 100644 (file)
@@ -28,6 +28,9 @@ endif
 if FT2232_DRIVER
 DRIVERFILES += ft2232.c
 endif
+if USB_BLASTER_DRIVER
+DRIVERFILES += usb_blaster.c
+endif
 if AMTJTAGACCEL
 DRIVERFILES += amt_jtagaccel.c
 endif
diff --git a/src/jtag/drivers/usb_blaster.c b/src/jtag/drivers/usb_blaster.c
new file mode 100644 (file)
index 0000000..3703323
--- /dev/null
@@ -0,0 +1,589 @@
+/***************************************************************************
+ *   Driver for USB-JTAG, Altera USB-Blaster and compatibles               *
+ *   Original code from Kolja Waschk's USB-JTAG project                    *
+ *     (http://www.ixo.de/info/usb_jtag/).                                 *
+ *   Some updates by Anthony Liu (2006).                                   *
+ *   Minor updates and cleanup by Catalin Patulea (2009).                  *
+ *                                                                         *
+ *   Copyright (C) 2009 Catalin Patulea                                    *
+ *   cat@vv.carleton.ca                                                    *
+ *                                                                         *
+ *   Copyright (C) 2006 Kolja Waschk                                       *
+ *   usbjtag@ixo.de                                                        *
+ *                                                                         *
+ *   Based on ft2232.c and bitbang.c,                                      *
+ *   Copyright (C) 2004,2006 by Dominic Rath                               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/*
+ * The following information is originally from Kolja Waschk's USB-JTAG,
+ * where it was obtained by reverse engineering an Altera USB-Blaster.
+ * See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
+ * usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol.
+ *
+ * The same information is also on the UrJTAG mediawiki, with some additional
+ * notes on bits marked as "unknown" by usb_jtag.
+ * (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
+ *    title=Cable_Altera_USB-Blaster)
+ *
+ * USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
+ * an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
+ *
+ *            _________
+ *           |         |
+ *           | AT93C46 |
+ *           |_________|
+ *            __|__________    _________
+ *           |             |  |         |
+ *      USB__| FTDI 245BM  |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
+ *           |_____________|  |_________|
+ *            __|__________    _|___________
+ *           |             |  |             |
+ *           | 6 MHz XTAL  |  | 24 MHz Osc. |
+ *           |_____________|  |_____________|
+ *
+ * Protocol details are given in the code below.
+ *
+ * It is also possible to emulate this configuration using a single-chip USB
+ * controller like the Cypress FX2 (again, see usb_jtag for details).
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef LOG_ERROR
+#endif
+
+/* project specific includes */
+#include <jtag/interface.h>
+#include <jtag/commands.h>
+#include <helper/time_support.h>
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bitbang.h"
+
+#if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
+#error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
+          "are mutually exclusive"
+#elif (BUILD_USB_BLASTER_FTD2XX != 1 && BUILD_USB_BLASTER_LIBFTDI != 1)
+#error "BUILD_USB_BLASTER_FTD2XX || BUILD_USB_BLASTER_LIBFTDI must be chosen"
+#endif
+
+/* USB_BLASTER access library includes */
+#if BUILD_USB_BLASTER_FTD2XX == 1
+#include <ftd2xx.h>
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+#include <ftdi.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+
+static char *usb_blaster_device_desc;
+static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
+static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
+
+/* last output byte in simple bit banging mode */
+static uint8_t out_value;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+static FT_HANDLE ftdih;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+static struct ftdi_context ftdic;
+#endif
+
+static int usb_blaster_buf_write(
+       uint8_t *buf, int size, uint32_t *bytes_written)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+       DWORD dw_bytes_written;
+
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       status = FT_Write(ftdih, buf, size, &dw_bytes_written);
+       if (status != FT_OK)
+       {
+               *bytes_written = dw_bytes_written;
+               LOG_ERROR("FT_Write returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_written = dw_bytes_written;
+       return ERROR_OK;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       retval = ftdi_write_data(&ftdic, buf, size);
+       if (retval < 0)
+       {
+               *bytes_written = 0;
+               LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_written = retval;
+       return ERROR_OK;
+#endif
+}
+
+static int
+usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       DWORD dw_bytes_read;
+       FT_STATUS status;
+
+       status = FT_Read(ftdih, buf, size, &dw_bytes_read);
+       if (status != FT_OK)
+       {
+               *bytes_read = dw_bytes_read;
+               LOG_ERROR("FT_Read returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
+#endif
+       *bytes_read = dw_bytes_read;
+       return ERROR_OK;
+
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+       int timeout = 100;
+
+       *bytes_read = 0;
+       while ((*bytes_read < size) && timeout--)
+       {
+               retval = ftdi_read_data(&ftdic, buf + *bytes_read,
+                               size - *bytes_read);
+               if (retval < 0)
+               {
+                       *bytes_read = 0;
+                       LOG_ERROR("ftdi_read_data: %s",
+                                       ftdi_get_error_string(&ftdic));
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += retval;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
+#endif
+       return ERROR_OK;
+#endif
+}
+
+/* The following code doesn't fully utilize the possibilities of the
+ * USB-Blaster. It writes one byte per JTAG pin state change at a time; it
+ * doesn't even try to buffer data up to the maximum packet size of 64 bytes.
+ *
+ * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data
+ * bits (bidirectional) in a single USB packet. A header byte has to be sent as
+ * the first byte in a packet with the following meaning:
+ *
+ *   Bit 7 (0x80): Must be set to indicate byte-shift mode.
+ *   Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
+ *   Bit 5..0:     Define the number N of following bytes
+ *
+ * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
+ * set, it will afterwards return N bytes with TDO data read while clocking out
+ * the TDI data. LSB of the first byte after the header byte will appear first
+ * on TDI.
+ */
+
+/* Simple bit banging mode:
+ *
+ *   Bit 7 (0x80): Must be zero (see byte-shift mode above)
+ *   Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
+ *                 in return.
+ *   Bit 5 (0x20): Output Enable/LED.
+ *   Bit 4 (0x10): TDI Output.
+ *   Bit 3 (0x08): nCS Output (not used in JTAG mode).
+ *   Bit 2 (0x04): nCE Output (not used in JTAG mode).
+ *   Bit 1 (0x02): TMS Output.
+ *   Bit 0 (0x01): TCK Output.
+ *
+ * For transmitting a single data bit, you need to write two bytes. Up to 64
+ * bytes can be combined in a single USB packet (but this is not done in the
+ * code below). It isn't possible to read a data without transmitting data.
+ */
+
+#define TCK                    (1 << 0)
+#define TMS                    (1 << 1)
+#define NCE                    (1 << 2)
+#define NCS                    (1 << 3)
+#define TDI                    (1 << 4)
+#define LED                    (1 << 5)
+#define READ           (1 << 6)
+#define SHMODE         (1 << 7)
+#define OTHERS         ((1 << 2) | (1 << 3) | (1 << 5))
+
+#define READ_TDO       (1 << 0)
+
+static void usb_blaster_write_data(void)
+{
+       uint32_t bytes_written;
+       usb_blaster_buf_write(&out_value, 1, &bytes_written);
+}
+
+static int usb_blaster_read_data(void)
+{
+       int status;
+       uint8_t buf[1];
+       uint32_t bytes_read;
+
+       out_value |= READ;
+       usb_blaster_write_data();
+       out_value &= ~READ;
+
+       status = usb_blaster_buf_read(buf, 1, &bytes_read);
+       if (status < 0)
+               return 0;
+
+       return !!(buf[0] & READ_TDO);
+}
+
+static void usb_blaster_write(int tck, int tms, int tdi)
+{
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi);
+#endif
+       out_value &= ~(TCK | TMS | TDI);
+       if (tck)
+               out_value |= TCK;
+       if (tms)
+               out_value |= TMS;
+       if (tdi)
+               out_value |= TDI;
+
+       usb_blaster_write_data();
+}
+
+static int usb_blaster_speed(int speed)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       LOG_DEBUG("TODO: usb_blaster_speed() isn't implemented for libftd2xx!");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       LOG_DEBUG("TODO: usb_blaster_speed() isn't optimally implemented!");
+
+       /* TODO: libftdi's ftdi_set_baudrate chokes on high rates, use lowlevel
+        * usb function instead! And additionally allow user to throttle.
+        */
+       if (ftdi_set_baudrate(&ftdic, 3000000 / 4) < 0)
+       {
+               LOG_ERROR("Can't set baud rate to max: %s",
+                       ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       };
+#endif
+
+       return ERROR_OK;
+}
+
+static void usb_blaster_reset(int trst, int srst)
+{
+       LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
+                       trst, srst);
+}
+
+static struct bitbang_interface usb_blaster_bitbang = {
+       .read = usb_blaster_read_data,
+       .write = usb_blaster_write,
+       .reset = usb_blaster_reset,
+};
+
+static int usb_blaster_init(void)
+{
+       uint8_t latency_timer;
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       LOG_DEBUG("'usb_blaster' interface using FTD2XX");
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       LOG_DEBUG("'usb_blaster' interface using libftdi");
+#endif
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       /* Open by device description */
+       if (usb_blaster_device_desc == NULL)
+       {
+               LOG_WARNING("no usb_blaster device description specified, "
+                                       "using default 'USB-Blaster'");
+               usb_blaster_device_desc = "USB-Blaster";
+       }
+
+#if IS_WIN32 == 0
+       /* Add non-standard Vid/Pid to the linux driver */
+       status = FT_SetVIDPID(usb_blaster_vid, usb_blaster_pid);
+       if (status != FT_OK)
+       {
+               LOG_WARNING("couldn't add %4.4x:%4.4x",
+                       usb_blaster_vid, usb_blaster_pid);
+       }
+#endif
+
+       status = FT_OpenEx(usb_blaster_device_desc, FT_OPEN_BY_DESCRIPTION,
+                       &ftdih);
+       if (status != FT_OK)
+       {
+               DWORD num_devices;
+
+               LOG_ERROR("unable to open ftdi device: %lu", status);
+               status = FT_ListDevices(&num_devices, NULL,
+                               FT_LIST_NUMBER_ONLY);
+               if (status == FT_OK)
+               {
+                       char **desc_array = malloc(sizeof(char *)
+                                               * (num_devices + 1));
+                       unsigned int i;
+
+                       for (i = 0; i < num_devices; i++)
+                               desc_array[i] = malloc(64);
+                       desc_array[num_devices] = NULL;
+
+                       status = FT_ListDevices(desc_array, &num_devices,
+                               FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
+
+                       if (status == FT_OK)
+                       {
+                               LOG_ERROR("ListDevices: %lu\n", num_devices);
+                               for (i = 0; i < num_devices; i++)
+                                       LOG_ERROR("%i: %s", i, desc_array[i]);
+                       }
+
+                       for (i = 0; i < num_devices; i++)
+                               free(desc_array[i]);
+                       free(desc_array);
+               }
+               else
+               {
+                       printf("ListDevices: NONE\n");
+               }
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       status = FT_SetLatencyTimer(ftdih, 2);
+       if (status != FT_OK)
+       {
+               LOG_ERROR("unable to set latency timer: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       status = FT_GetLatencyTimer(ftdih, &latency_timer);
+       if (status != FT_OK)
+       {
+               LOG_ERROR("unable to get latency timer: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       LOG_DEBUG("current latency timer: %i", latency_timer);
+
+       status = FT_SetBitMode(ftdih, 0x00, 0);
+       if (status != FT_OK)
+       {
+               LOG_ERROR("unable to disable bit i/o mode: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       if (ftdi_init(&ftdic) < 0)
+               return ERROR_JTAG_INIT_FAILED;
+
+       /* context, vendor id, product id */
+       if (ftdi_usb_open(&ftdic, usb_blaster_vid, usb_blaster_pid) < 0)
+       {
+               LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_usb_reset(&ftdic) < 0)
+       {
+               LOG_ERROR("unable to reset ftdi device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_set_latency_timer(&ftdic, 2) < 0)
+       {
+               LOG_ERROR("unable to set latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
+       {
+               LOG_ERROR("unable to get latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       LOG_DEBUG("current latency timer: %u", latency_timer);
+
+       ftdi_disable_bitbang(&ftdic);
+#endif
+
+       bitbang_interface = &usb_blaster_bitbang;
+
+       usb_blaster_speed(jtag_get_speed());
+
+#if 0
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+       {
+               LOG_ERROR("error purging ftd2xx device: %i", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       if (ftdi_usb_purge_buffers(&ftdic) < 0)
+       {
+               LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#endif
+#endif
+
+       return ERROR_OK;
+}
+
+static int usb_blaster_quit(void)
+{
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+
+       status = FT_Close(ftdih);
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       ftdi_usb_close(&ftdic);
+       ftdi_deinit(&ftdic);
+#endif
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
+{
+       if (CMD_ARGC == 1)
+               usb_blaster_device_desc = strdup(CMD_ARGV[0]);
+       else
+               LOG_ERROR("require exactly one argument to "
+                                 "usb_blaster_device_desc <description>");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_vid_pid_command)
+{
+       if (CMD_ARGC > 2)
+       {
+               LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
+                                       "(maximum is 1 pair)");
+               CMD_ARGC = 2;
+       }
+       if (CMD_ARGC == 2)
+       {
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], usb_blaster_vid);
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], usb_blaster_pid);
+       }
+       else
+               LOG_WARNING("incomplete usb_blaster_vid_pid configuration");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(usb_blaster_handle_pin_command)
+{
+       if (CMD_ARGC == 2)
+       {
+               const char * const pin_name = CMD_ARGV[0];
+               uint8_t mask;
+               unsigned int state;
+
+               if (!strcmp(pin_name, "pin6"))
+                       mask = NCE;
+               else if (!strcmp(pin_name, "pin8"))
+                       mask = NCS;
+               else
+               {
+                       LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
+                                       CMD_NAME);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+
+               COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state);
+               if (state == 0)
+               {
+                       out_value &= ~mask;
+                       usb_blaster_write_data();
+               }
+               else if (state == 1)
+               {
+                       out_value |= mask;
+                       usb_blaster_write_data();
+               }
+               else
+               {
+                       LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+
+               return ERROR_OK;
+       }
+       else
+       {
+               LOG_ERROR("%s takes exactly two arguments", CMD_NAME);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+}
+
+static const struct command_registration usb_blaster_command_handlers[] = {
+       {
+               .name = "usb_blaster_device_desc",
+               .handler = usb_blaster_handle_device_desc_command,
+               .mode = COMMAND_CONFIG,
+               .help = "set the USB device description of the USB-Blaster",
+               .usage = "description-string",
+       },
+       {
+               .name = "usb_blaster_vid_pid",
+               .handler = usb_blaster_handle_vid_pid_command,
+               .mode = COMMAND_CONFIG,
+               .help = "the vendor ID and product ID of the USB-Blaster",
+               .usage = "vid pid",
+       },
+       {
+               .name = "usb_blaster",
+               .handler = usb_blaster_handle_pin_command,
+               .mode = COMMAND_ANY,
+               .help = "set pin state for the unused GPIO pins",
+               .usage = "(pin6|pin8) (0|1)",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface usb_blaster_interface = {
+       .name = "usb_blaster",
+       .commands = usb_blaster_command_handlers,
+
+       .execute_queue = bitbang_execute_queue,
+
+       .speed = usb_blaster_speed,
+       .init = usb_blaster_init,
+       .quit = usb_blaster_quit,
+};
index 643e1118114a0706c9047fdeacd43eea71d50233..f6d82195d8167e85aee58728c24e15343e9bb9a7 100644 (file)
@@ -58,6 +58,9 @@ extern struct jtag_interface ft2232_interface;
 #if BUILD_FT2232_LIBFTDI == 1
 extern struct jtag_interface ft2232_interface;
 #endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
+extern struct jtag_interface usb_blaster_interface;
+#endif
 #if BUILD_AMTJTAGACCEL == 1
 extern struct jtag_interface amt_jtagaccel_interface;
 #endif
@@ -115,6 +118,9 @@ struct jtag_interface *jtag_interfaces[] = {
 #if BUILD_FT2232_LIBFTDI == 1
                &ft2232_interface,
 #endif
+#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
+               &usb_blaster_interface,
+#endif
 #if BUILD_AMTJTAGACCEL == 1
                &amt_jtagaccel_interface,
 #endif
diff --git a/tcl/interface/altera-usb-blaster.cfg b/tcl/interface/altera-usb-blaster.cfg
new file mode 100644 (file)
index 0000000..ae21465
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Altera USB-Blaster
+#
+# http://www.altera.com/literature/ug/ug_usb_blstr.pdf
+#
+
+interface usb_blaster
+# These are already the defaults.
+# usb_blaster_vid_pid 0x09FB 0x6001
+# usb_blaster_device_desc "USB-Blaster"
+jtag_khz 3000
diff --git a/tcl/interface/usb-jtag.cfg b/tcl/interface/usb-jtag.cfg
new file mode 100644 (file)
index 0000000..b81028d
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Kolja Waschk's USB-JTAG
+#
+# http://www.ixo.de/info/usb_jtag/
+#
+
+interface usb_blaster
+usb_blaster_vid_pid 0x16C0 0x06AD
+usb_blaster_device_desc "USB-JTAG-IF"
+jtag_khz 3000
+

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)