From 84dbf8ab5a2e85c9d9c9d276fba152a45a441433 Mon Sep 17 00:00:00 2001 From: Catalin Patulea Date: Sat, 26 Dec 2009 15:05:06 -0800 Subject: [PATCH] Driver for USB-JTAG, Altera USB-Blaster and compatibles The 10-pin JTAG layout used with these adapters is used by a variety of platforms including AVR. Signed-off-by: David Brownell --- NEWS | 1 + configure.in | 26 +- doc/openocd.texi | 59 +++ src/Makefile.am | 4 + src/jtag/drivers/Makefile.am | 3 + src/jtag/drivers/usb_blaster.c | 589 +++++++++++++++++++++++++++ src/jtag/interfaces.c | 6 + tcl/interface/altera-usb-blaster.cfg | 11 + tcl/interface/usb-jtag.cfg | 11 + 9 files changed, 709 insertions(+), 1 deletion(-) create mode 100644 src/jtag/drivers/usb_blaster.c create mode 100644 tcl/interface/altera-usb-blaster.cfg create mode 100644 tcl/interface/usb-jtag.cfg diff --git a/NEWS b/NEWS index 173d06af8..e3e813cba 100644 --- 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: diff --git a/configure.in b/configure.in index 7ce795596..21edba920 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/doc/openocd.texi b/doc/openocd.texi index 013a31a8d..1c20716c9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -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: diff --git a/src/Makefile.am b/src/Makefile.am index f60feac31..a566b4d42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 8ee5ac592..d6113c601 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -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 index 000000000..3703323bf --- /dev/null +++ b/src/jtag/drivers/usb_blaster.c @@ -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 +#include +#include + +/* system includes */ +#include +#include +#include + +#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 +#elif BUILD_USB_BLASTER_LIBFTDI == 1 +#include +#endif + +#include +#include + +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 "); + + 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, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 643e11181..f6d82195d 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -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 index 000000000..ae2146526 --- /dev/null +++ b/tcl/interface/altera-usb-blaster.cfg @@ -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 index 000000000..b81028d61 --- /dev/null +++ b/tcl/interface/usb-jtag.cfg @@ -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 +