From: David B. <dbr...@us...> - 2009-12-27 00:05:38
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 84dbf8ab5a2e85c9d9c9d276fba152a45a441433 (commit) from 900d745567809d9f0163cfde5832b10ec0581a0e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 84dbf8ab5a2e85c9d9c9d276fba152a45a441433 Author: Catalin Patulea <ca...@vv...> Date: Sat Dec 26 15:05:06 2009 -0800 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 <dbr...@us...> diff --git a/NEWS b/NEWS index 173d06a..e3e813c 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 7ce7955..21edba9 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 013a31a..1c20716 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 f60feac..a566b4d 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 8ee5ac5..d6113c6 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 0000000..3703323 --- /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 * + * ca...@vv... * + * * + * Copyright (C) 2006 Kolja Waschk * + * us...@ix... * + * * + * 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, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 643e111..f6d8219 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 0000000..ae21465 --- /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 0000000..b81028d --- /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 + ----------------------------------------------------------------------- Summary of changes: 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 deletions(-) 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 hooks/post-receive -- Main OpenOCD repository |