From 4912ec2f2ecfb960c9a718fc92dd5b7bcc4876f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnim=20L=C3=A4uger?= Date: Fri, 16 Nov 2007 17:50:20 +0000 Subject: [PATCH] merged changes from /branches/ft2232_eval@770 this is the initial stable version of the ft2232 cable driver git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@771 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- jtag/include/cable.h | 4 +- jtag/include/chain.h | 2 +- jtag/src/cmd/cable.c | 3 +- jtag/src/svf/svf.c | 53 ++-- jtag/src/tap/Makefile.am | 3 +- jtag/src/tap/cable.c | 10 +- jtag/src/tap/cable/arcom.c | 14 +- jtag/src/tap/cable/byteblaster.c | 14 +- jtag/src/tap/cable/dlc5.c | 14 +- jtag/src/tap/cable/ea253.c | 14 +- jtag/src/tap/cable/ei012.c | 14 +- jtag/src/tap/cable/ft2232.c | 480 +++++++++++++++++++++++++++++++ jtag/src/tap/cable/generic.c | 4 +- jtag/src/tap/cable/keithkoep.c | 14 +- jtag/src/tap/cable/lattice.c | 14 +- jtag/src/tap/cable/mpcbdm.c | 14 +- jtag/src/tap/cable/triton.c | 14 +- jtag/src/tap/cable/usbblaster.c | 14 +- jtag/src/tap/cable/wiggler.c | 15 +- jtag/src/tap/cable/wiggler2.c | 14 +- jtag/src/tap/cable/xpc.c | 14 +- jtag/src/tap/chain.c | 10 +- jtag/src/tap/parport.c | 2 + jtag/src/tap/parport/ftdi.c | 185 ++++++++++-- jtag/src/tap/tap.c | 25 +- 25 files changed, 829 insertions(+), 135 deletions(-) create mode 100644 jtag/src/tap/cable/ft2232.c diff --git a/jtag/include/cable.h b/jtag/include/cable.h index 467f7091..fba16524 100644 --- a/jtag/include/cable.h +++ b/jtag/include/cable.h @@ -43,7 +43,7 @@ struct cable_driver_t { void (*cable_free)( cable_t *cable ); int (*init)( cable_t * ); void (*done)( cable_t * ); - void (*clock)( cable_t *, int, int ); + void (*clock)( cable_t *, int, int, int ); int (*get_tdo)( cable_t * ); int (*transfer)( cable_t *, int, char *, char * ); int (*set_trst)( cable_t *, int ); @@ -60,7 +60,7 @@ struct cable_t { void cable_free( cable_t *cable ); int cable_init( cable_t *cable ); void cable_done( cable_t *cable ); -void cable_clock( cable_t *cable, int tms, int tdi ); +void cable_clock( cable_t *cable, int tms, int tdi, int n ); int cable_get_tdo( cable_t *cable ); int cable_set_trst( cable_t *cable, int trst ); int cable_get_trst( cable_t *cable ); diff --git a/jtag/include/chain.h b/jtag/include/chain.h index 4acb0d57..a835b7a1 100644 --- a/jtag/include/chain.h +++ b/jtag/include/chain.h @@ -45,7 +45,7 @@ struct chain_t { chain_t *chain_alloc( void ); void chain_free( chain_t *chain ); void chain_disconnect( chain_t *chain ); -void chain_clock( chain_t *chain, int tms, int tdi ); +void chain_clock( chain_t *chain, int tms, int tdi, int n ); int chain_set_trst( chain_t *chain, int trst ); int chain_get_trst( chain_t *chain ); void chain_shift_instructions( chain_t *chain ); diff --git a/jtag/src/cmd/cable.c b/jtag/src/cmd/cable.c index 8b1f9be8..42644233 100644 --- a/jtag/src/cmd/cable.c +++ b/jtag/src/cmd/cable.c @@ -87,6 +87,7 @@ cmd_cable_help( void ) "Usage: %s DEV CABLE\n" "Usage: %s VID:PID:S/N CABLE\n" "Usage: %s VID:PID:S/N CABLE\n" + "Usage: %s VID:PID:S/N CABLE\n" "Select JTAG cable connected to parallel port.\n" "\n" "PORTADDR parallel port address (e.g. 0x378)\n" @@ -98,7 +99,7 @@ cmd_cable_help( void ) "\n" "List of supported cables:\n" "%-13s No cable connected\n" - ), "cable parallel", "cable ppdev", "cable ftdi", "cable xpcu", "none" ); + ), "cable parallel", "cable ppdev", "cable ftdi", "cable ftdi-mpsse", "cable xpcu", "none" ); for (i = 0; cable_drivers[i]; i++) printf( _("%-13s %s\n"), cable_drivers[i]->name, _(cable_drivers[i]->description) ); diff --git a/jtag/src/svf/svf.c b/jtag/src/svf/svf.c index c21c36c6..8849d7a7 100644 --- a/jtag/src/svf/svf.c +++ b/jtag/src/svf/svf.c @@ -92,9 +92,7 @@ static int issued_runtest_maxtime; static void svf_force_reset_state(void) { - int i; - for (i = 1; i <= 5; i++) - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 5); tap_state_reset(chain); } @@ -128,11 +126,11 @@ svf_goto_state(int new_state) switch (current_state) { case Test_Logic_Reset: - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); break; case Run_Test_Idle: - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Select_DR_Scan: @@ -142,86 +140,86 @@ svf_goto_state(int new_state) (current_state & TAPSTAT_DR && new_state & TAPSTAT_IR) || (current_state & TAPSTAT_IR && new_state & TAPSTAT_DR)) /* progress in select-idle/reset loop */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); else /* enter DR/IR branch */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); break; case Capture_DR: if (new_state == Shift_DR) /* enter Shift_DR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* bypass Shift_DR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Capture_IR: if (new_state == Shift_IR) /* enter Shift_IR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* bypass Shift_IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Shift_DR: case Shift_IR: /* progress to Exit1_DR/IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Exit1_DR: if (new_state == Pause_DR) /* enter Pause_DR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* bypass Pause_DR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Exit1_IR: if (new_state == Pause_IR) /* enter Pause_IR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* bypass Pause_IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Pause_DR: case Pause_IR: /* progress to Exit2_DR/IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Exit2_DR: if (new_state == Shift_DR) /* enter Shift_DR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* progress to Update_DR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Exit2_IR: if (new_state == Shift_IR) /* enter Shift_IR state */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* progress to Update_IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; case Update_DR: case Update_IR: if (new_state == Run_Test_Idle) /* enter Run_Test_Idle */ - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); else /* progress to Select_DR/IR */ - chain_clock(chain, 1, 0); + chain_clock(chain, 1, 0, 1); break; default: @@ -706,9 +704,12 @@ svf_runtest(struct runtest *params) ualarm(max_time, 0); } - while (run_count-- > 0 && !max_time_reached) { - chain_clock(chain, 0, 0); - } + if (params->max_time > 0.0) + while (run_count-- > 0 && !max_time_reached) { + chain_clock(chain, 0, 0, 1); + } + else + chain_clock(chain, 0, 0, run_count); svf_goto_state(runtest_end_state); diff --git a/jtag/src/tap/Makefile.am b/jtag/src/tap/Makefile.am index 6445564f..704e8c76 100644 --- a/jtag/src/tap/Makefile.am +++ b/jtag/src/tap/Makefile.am @@ -58,6 +58,7 @@ endif if HAVE_LIBFTDI libtap_a_SOURCES += \ parport/ftdi.c \ - cable/usbblaster.c + cable/usbblaster.c \ + cable/ft2232.c endif diff --git a/jtag/src/tap/cable.c b/jtag/src/tap/cable.c index 6ce644a7..c3015748 100644 --- a/jtag/src/tap/cable.c +++ b/jtag/src/tap/cable.c @@ -39,6 +39,8 @@ extern cable_driver_t arcom_cable_driver; extern cable_driver_t byteblaster_cable_driver; #ifdef HAVE_LIBFTDI extern cable_driver_t usbblaster_cable_driver; +extern cable_driver_t ft2232_cable_driver; +extern cable_driver_t ft2232_armusbocd_cable_driver; #endif extern cable_driver_t dlc5_cable_driver; extern cable_driver_t ea253_cable_driver; @@ -61,6 +63,8 @@ cable_driver_t *cable_drivers[] = { &byteblaster_cable_driver, #ifdef HAVE_LIBFTDI &usbblaster_cable_driver, + &ft2232_cable_driver, + &ft2232_armusbocd_cable_driver, #endif &dlc5_cable_driver, &ea253_cable_driver, @@ -98,9 +102,9 @@ cable_done( cable_t *cable ) } void -cable_clock( cable_t *cable, int tms, int tdi ) +cable_clock( cable_t *cable, int tms, int tdi, int n ) { - cable->driver->clock( cable, tms, tdi ); + cable->driver->clock( cable, tms, tdi, n ); } int @@ -149,7 +153,7 @@ cable_set_frequency( cable_t *cable, uint32_t new_frequency ) start = frealtime(); for (i = 0; i < loops; ++i) { - chain_clock(chain, 0, 0); + chain_clock(chain, 0, 0, 1); } end = frealtime(); diff --git a/jtag/src/tap/cable/arcom.c b/jtag/src/tap/cable/arcom.c index d406da0e..2dce386f 100644 --- a/jtag/src/tap/cable/arcom.c +++ b/jtag/src/tap/cable/arcom.c @@ -67,15 +67,19 @@ arcom_init( cable_t *cable ) } static void -arcom_clock( cable_t *cable, int tms, int tdi ) +arcom_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/byteblaster.c b/jtag/src/tap/cable/byteblaster.c index 3fb67d3e..9e3e9194 100644 --- a/jtag/src/tap/cable/byteblaster.c +++ b/jtag/src/tap/cable/byteblaster.c @@ -96,15 +96,19 @@ byteblaster_init( cable_t *cable ) } static void -byteblaster_clock( cable_t *cable, int tms, int tdi ) +byteblaster_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/dlc5.c b/jtag/src/tap/cable/dlc5.c index 1db1c78c..8b54b0c6 100644 --- a/jtag/src/tap/cable/dlc5.c +++ b/jtag/src/tap/cable/dlc5.c @@ -67,15 +67,19 @@ dlc5_init( cable_t *cable ) } static void -dlc5_clock( cable_t *cable, int tms, int tdi ) +dlc5_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/ea253.c b/jtag/src/tap/cable/ea253.c index 8c2b68eb..89a7c417 100644 --- a/jtag/src/tap/cable/ea253.c +++ b/jtag/src/tap/cable/ea253.c @@ -67,15 +67,19 @@ ea253_init( cable_t *cable ) } static void -ea253_clock( cable_t *cable, int tms, int tdi ) +ea253_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/ei012.c b/jtag/src/tap/cable/ei012.c index b4ba3f33..ebed907e 100644 --- a/jtag/src/tap/cable/ei012.c +++ b/jtag/src/tap/cable/ei012.c @@ -69,15 +69,19 @@ ei012_init( cable_t *cable ) } static void -ei012_clock( cable_t *cable, int tms, int tdi ) +ei012_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/ft2232.c b/jtag/src/tap/cable/ft2232.c new file mode 100644 index 00000000..52e8601f --- /dev/null +++ b/jtag/src/tap/cable/ft2232.c @@ -0,0 +1,480 @@ +/* + * $Id$ + * + * Generic cable driver for FTDI's FT2232C chip in MPSSE mode. + * Copyright (C) 2007 A. Laeuger + * + * 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. + * + * Written by Arnim Laeuger, 2007. + * + */ + +#include + +#include "sysdep.h" + +#include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" + + +/* Define MULTI_BYTE to activate block read transfer from parport + no benefit over single byte read observed. */ +#undef MULTI_BYTE + +/* Maximum chunk to write to parport driver. + Larger values might speed up comm, but there's an upper limit + when too many bytes are sent and libftdi doesn't fetch the + returned data in time -> deadlock */ +#define MAXCHUNK (4 * 64) + +/* Enable caching of last TDO to speed up things a bit. + Should be left define'd unless comm/sync problems occur. */ +#define LAST_TDO_CACHE + +/* Maximum TCK frequency of FT2232 */ +#define FT2232_MAX_TCK_FREQ 6000000 + + +#define BIT_TCK 0 +#define BIT_TDI 1 +#define BIT_TDO 2 +#define BIT_TMS 3 +#define BIT_ARMUSBOCD_nOE 4 +#define BITMASK_TDO (1 << BIT_TDO) +#define BITMASK_TDI (1 << BIT_TDI) +#define BITMASK_TCK (1 << BIT_TCK) +#define BITMASK_TMS (1 << BIT_TMS) +#define BITMASK_ARMUSBOCD_nOE (1 << BIT_ARMUSBOCD_nOE) + + +/* global variables to save last TDO value + this acts as a cache to prevent multiple "Read Data Bits Low" transfer + over USB for ft2232_get_tdo */ +static unsigned int last_tdo_valid; +static unsigned int last_tdo; + +static uint32_t mpsse_frequency; + +#ifdef MULTIBYTE +static uint8_t local_buffer[MAXCHUNK+16]; +#endif + + +static void +update_frequency( cable_t *cable ) +{ + parport_t *p = cable->port; + uint32_t new_frequency = cable_get_frequency( cable ); + + if (!new_frequency || new_frequency > FT2232_MAX_TCK_FREQ) + new_frequency = FT2232_MAX_TCK_FREQ; + + /* update ft2232 frequency if cable setting changed */ + if (new_frequency != mpsse_frequency) { + uint32_t div; + + div = FT2232_MAX_TCK_FREQ / new_frequency; + if (FT2232_MAX_TCK_FREQ % new_frequency) + div++; + + if (div >= (1 << 16)) { + div = (1 << 16) - 1; + printf( _("Warning: Setting lowest supported frequency for FT2232: %d\n"), FT2232_MAX_TCK_FREQ/div ); + } + + /* send new divisor to device */ + div -= 1; + parport_set_data( p, TCK_DIVISOR ); + parport_set_data( p, div & 0xff ); + parport_set_data( p, (div >> 8) & 0xff ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + mpsse_frequency = FT2232_MAX_TCK_FREQ / (div + 1); + } +} + + +static int +ft2232_generic_init( cable_t *cable ) +{ + parport_t *p = cable->port; + + if (parport_open( p )) + return -1; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + parport_set_data( p, SET_BITS_LOW ); + parport_set_data( p, BITMASK_TMS ); + parport_set_data( p, BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + /* Set TCK/SK Divisor */ + parport_set_data( p, TCK_DIVISOR ); + parport_set_data( p, 0 ); + parport_set_data( p, 0 ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + mpsse_frequency = FT2232_MAX_TCK_FREQ; + + last_tdo_valid = 0; + + return 0; +} + +static int +ft2232_armusbocd_init( cable_t *cable ) +{ + parport_t *p = cable->port; + + if (parport_open( p )) + return -1; + + /* set loopback off */ + parport_set_data( p, LOOPBACK_END ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ + parport_set_data( p, SET_BITS_LOW ); + parport_set_data( p, BITMASK_TMS ); + parport_set_data( p, BITMASK_TCK | BITMASK_TDI | BITMASK_TMS | BITMASK_ARMUSBOCD_nOE ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + /* Set TCK/SK Divisor */ + parport_set_data( p, TCK_DIVISOR ); + parport_set_data( p, 0 ); + parport_set_data( p, 0 ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + mpsse_frequency = FT2232_MAX_TCK_FREQ; + + last_tdo_valid = 0; + + return 0; +} + +static void +ft2232_generic_done( cable_t *cable ) +{ + parport_t *p = cable->port; + + /* Set Data Bits Low Byte + set all to input */ + parport_set_data( p, SET_BITS_LOW ); + parport_set_data( p, 0 ); + parport_set_data( p, 0 ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + parport_close( p ); +} + +static void +ft2232_armusbocd_done( cable_t *cable ) +{ + parport_t *p = cable->port; + + /* Set Data Bits Low Byte + disable output drivers */ + parport_set_data( p, SET_BITS_LOW ); + parport_set_data( p, BITMASK_ARMUSBOCD_nOE ); + parport_set_data( p, BITMASK_ARMUSBOCD_nOE ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + /* Set Data Bits Low Byte + set all to input */ + parport_set_data( p, SET_BITS_LOW ); + parport_set_data( p, BITMASK_ARMUSBOCD_nOE ); + parport_set_data( p, 0 ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + parport_close( p ); +} + +static void +ft2232_clock( cable_t *cable, int tms, int tdi, int n ) +{ + parport_t *p = cable->port; + + tms = tms ? 0x7f : 0; + tdi = tdi ? 1 << 7 : 0; + + /* check for new frequency setting */ + update_frequency( cable ); + + while (n > 0) { + /* Clock Data to TMS/CS Pin (no Read) */ + parport_set_data( p, MPSSE_WRITE_TMS | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + if (n <= 7) { + parport_set_data( p, n-1 ); + n = 0; + } else { + parport_set_data( p, 7-1 ); + n -= 7; + } + parport_set_data( p, tdi | tms ); + } + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + last_tdo_valid = 0; +} + +static int +ft2232_get_tdo( cable_t *cable ) +{ + parport_t *p = cable->port; + + if (!last_tdo_valid) { + /* Read Data Bits Low Byte */ + parport_set_data( p, GET_BITS_LOW ); + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + last_tdo = ( parport_get_data( p ) & BITMASK_TDO) ? 1 : 0; + +#ifdef LAST_TDO_CACHE + last_tdo_valid = 1; +#endif + } + return last_tdo; +} + +static int +ft2232_set_trst( cable_t *cable, int trst ) +{ + return 1; +} + +static int +ft2232_transfer( cable_t *cable, int len, char *in, char *out ) +{ + parport_t *p = cable->port; + int in_offset = 0; + int out_offset = 0; + int bitwise_len; + + /* check for new frequency setting */ + update_frequency( cable ); + +#ifdef LAST_TDO_CACHE + /* invalidate TDO cache */ + last_tdo_valid = 0; +#endif + + while (len - in_offset > 0) { + int byte_idx; + int chunkbytes = (len - in_offset) >> 3; + + if (chunkbytes > MAXCHUNK) + chunkbytes = MAXCHUNK; + + if ((chunkbytes < MAXCHUNK) && + ((len - in_offset) % 8 > 0)) + bitwise_len = (len - in_offset) % 8; + else + bitwise_len = 0; + + + if (chunkbytes > 0) { + /*********************************************************************** + * Step 1: + * Determine data shifting command (bytewise). + * Either with or without read + ***********************************************************************/ + if (out) + /* Clock Data Bytes In and Out LSB First + out on negative edge, in on positive edge */ + parport_set_data( p, MPSSE_DO_READ | MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_WRITE_NEG ); + else + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + parport_set_data( p, MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_WRITE_NEG ); + /* set byte count */ + parport_set_data( p, (chunkbytes - 1) & 0xff ); + parport_set_data( p, ((chunkbytes - 1) >> 8) & 0xff ); + + + /********************************************************************* + * Step 2: + * Write TDI data in bundles of 8 bits. + *********************************************************************/ + for (byte_idx = 0; byte_idx < chunkbytes; byte_idx++) { + int bit_idx; + unsigned char b = 0; + + for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) + if (in[in_offset++]) + b |= bit_idx; + parport_set_data( p, b ); + } + } + + if (bitwise_len > 0) { + /*********************************************************************** + * Step 3: + * Determine data shifting command (bitwise). + * Either with or without read + ***********************************************************************/ + if (out) + /* Clock Data Bytes In and Out LSB First + out on negative edge, in on positive edge */ + parport_set_data( p, MPSSE_DO_READ | MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + else + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + parport_set_data( p, MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + /* determine bit count */ + parport_set_data( p, bitwise_len - 1 ); + + /*********************************************************************** + * Step 4: + * Write TDI data bitwise + ***********************************************************************/ + { + int bit_idx; + unsigned char b = 0; + for (bit_idx = 1; bit_idx <= 1 << bitwise_len; bit_idx <<= 1) { + if (in[in_offset++]) + b |= bit_idx; + } + parport_set_data( p, b ); + } + } + +#ifdef LAST_TDO_CACHE + if (out) { + /* Read Data Bits Low Byte to get current TDO, + Do this only if we'll read out data nonetheless */ + parport_set_data( p, GET_BITS_LOW ); + } +#endif + + parport_set_control( p, 1 ); // flush + parport_set_control( p, 0 ); // noflush + + if (out) { + if (chunkbytes > 0) { +#ifdef MULTI_BYTE + int buf_idx; +#endif + uint32_t xferred; + + /********************************************************************* + * Step 5: + * Read TDO data in bundles of 8 bits if read is requested. + *********************************************************************/ +#ifdef MULTI_BYTE + parport_get_block( p, local_buffer, chunkbytes, &xferred ); + if (chunkbytes != xferred) + printf("Bummer\n"); + buf_idx = 0; +#else + xferred = chunkbytes; +#endif + for (; xferred > 0; xferred--) { + int bit_idx; + unsigned char b; + +#ifdef MULTI_BYTE + b = local_buffer[buf_idx++]; +#else + b = parport_get_data( p ); +#endif + for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) + out[out_offset++] = (b & bit_idx) ? 1 : 0; + } + } + + if (bitwise_len > 0) { + /*********************************************************************** + * Step 6: + * Read TDO data bitwise if read is requested. + ***********************************************************************/ + int bit_idx; + unsigned char b; + + b = parport_get_data( p ); + + for (bit_idx = (1 << (8 - bitwise_len)); bit_idx < 256; bit_idx <<= 1) + out[out_offset++] = (b & bit_idx) ? 1 : 0; + } + } + +#ifdef LAST_TDO_CACHE + if (out) { + /* gather current TDO */ + last_tdo = ( parport_get_data( p ) & BITMASK_TDO) ? 1 : 0; + last_tdo_valid = 1; + } +#endif + } + + return 0; +} + +cable_driver_t ft2232_cable_driver = { + "FT2232", + N_("Generic FTDI FT2232 Cable"), + generic_connect, + generic_disconnect, + generic_cable_free, + ft2232_generic_init, + ft2232_generic_done, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst +}; + +cable_driver_t ft2232_armusbocd_cable_driver = { + "ARM-USB-OCD", + N_("Olimex ARM-USB-OCD (FT2232) Cable"), + generic_connect, + generic_disconnect, + generic_cable_free, + ft2232_armusbocd_init, + ft2232_armusbocd_done, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst +}; + + +/* + Local Variables: + mode:C + tab-width:2 + indent-tabs-mode:t + End: +*/ diff --git a/jtag/src/tap/cable/generic.c b/jtag/src/tap/cable/generic.c index 7495acd9..6ba1bb9b 100644 --- a/jtag/src/tap/cable/generic.c +++ b/jtag/src/tap/cable/generic.c @@ -78,11 +78,11 @@ generic_transfer( cable_t *cable, int len, char *in, char *out ) if(out) for(i=0; iport, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/lattice.c b/jtag/src/tap/cable/lattice.c index c8edac60..c86c29bd 100644 --- a/jtag/src/tap/cable/lattice.c +++ b/jtag/src/tap/cable/lattice.c @@ -62,15 +62,19 @@ lattice_init( cable_t *cable ) } static void -lattice_clock( cable_t *cable, int tms, int tdi ) +lattice_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); - cable_wait(); - parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); + cable_wait(); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/mpcbdm.c b/jtag/src/tap/cable/mpcbdm.c index 13071876..068efa6e 100644 --- a/jtag/src/tap/cable/mpcbdm.c +++ b/jtag/src/tap/cable/mpcbdm.c @@ -73,15 +73,19 @@ mpcbdm_init( cable_t *cable ) } static void -mpcbdm_clock( cable_t *cable, int tms, int tdi ) +mpcbdm_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/triton.c b/jtag/src/tap/cable/triton.c index 7b62fb46..17e253b5 100644 --- a/jtag/src/tap/cable/triton.c +++ b/jtag/src/tap/cable/triton.c @@ -78,15 +78,19 @@ triton_init( cable_t *cable ) } static void -triton_clock( cable_t *cable, int tms, int tdi ) +triton_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/usbblaster.c b/jtag/src/tap/cable/usbblaster.c index dcfd3ac1..99008eb6 100644 --- a/jtag/src/tap/cable/usbblaster.c +++ b/jtag/src/tap/cable/usbblaster.c @@ -58,15 +58,19 @@ usbblaster_init( cable_t *cable ) } static void -usbblaster_clock( cable_t *cable, int tms, int tdi ) +usbblaster_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, OTHERS | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - parport_set_data( cable->port, OTHERS | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - parport_set_control( cable->port, 1 ); // flush - parport_set_control( cable->port, 0 ); // noflush + for (i = 0; i < n; i++) { + parport_set_data( cable->port, OTHERS | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->port, OTHERS | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_control( cable->port, 1 ); // flush + parport_set_control( cable->port, 0 ); // noflush + } } static int diff --git a/jtag/src/tap/cable/wiggler.c b/jtag/src/tap/cable/wiggler.c index 8e1aaa98..31731625 100644 --- a/jtag/src/tap/cable/wiggler.c +++ b/jtag/src/tap/cable/wiggler.c @@ -76,14 +76,19 @@ wiggler_init( cable_t *cable ) } static void -wiggler_clock( cable_t *cable, int tms, int tdi ) +wiggler_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << nTRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); - cable_wait(); - parport_set_data( cable->port, 0xe0 | (PARAM_TRST(cable) << nTRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); - cable_wait(); + + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << nTRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + cable_wait(); + parport_set_data( cable->port, 0xe0 | (PARAM_TRST(cable) << nTRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/wiggler2.c b/jtag/src/tap/cable/wiggler2.c index 4001b466..5d786e2e 100644 --- a/jtag/src/tap/cable/wiggler2.c +++ b/jtag/src/tap/cable/wiggler2.c @@ -83,15 +83,19 @@ wiggler2_init( cable_t *cable ) } static void -wiggler2_clock( cable_t *cable, int tms, int tdi ) +wiggler2_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); - cable_wait(); - parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + cable_wait(); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/cable/xpc.c b/jtag/src/tap/cable/xpc.c index 398d9b02..80c5cc29 100644 --- a/jtag/src/tap/cable/xpc.c +++ b/jtag/src/tap/cable/xpc.c @@ -65,17 +65,21 @@ xpc_ext_init( cable_t *cable ) #define TDO 0 static void -xpc_clock( cable_t *cable, int tms, int tdi ) +xpc_clock( cable_t *cable, int tms, int tdi, int n ) { + int i; + tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); - parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); - cable_wait(); + for (i = 0; i < n; i++) { + parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + cable_wait(); + } } static int diff --git a/jtag/src/tap/chain.c b/jtag/src/tap/chain.c index 74391d7d..c54371e3 100644 --- a/jtag/src/tap/chain.c +++ b/jtag/src/tap/chain.c @@ -70,13 +70,17 @@ chain_disconnect( chain_t *chain ) } void -chain_clock( chain_t *chain, int tms, int tdi ) +chain_clock( chain_t *chain, int tms, int tdi, int n ) { + int i; + if (!chain || !chain->cable) return; - cable_clock( chain->cable, tms, tdi ); - tap_state_clock( chain, tms ); + cable_clock( chain->cable, tms, tdi, n ); + + for (i = 0; i < n; i++) + tap_state_clock( chain, tms ); } int diff --git a/jtag/src/tap/parport.c b/jtag/src/tap/parport.c index 28d26d2e..d8f3bb1e 100644 --- a/jtag/src/tap/parport.c +++ b/jtag/src/tap/parport.c @@ -34,6 +34,7 @@ extern parport_driver_t ppdev_parport_driver; #endif /* HAVE_LINUX_PPDEV_H */ #ifdef HAVE_LIBFTDI extern parport_driver_t ftdi_parport_driver; +extern parport_driver_t ftdi_mpsse_parport_driver; #endif /* HAVE_LIBFTDI */ #ifdef HAVE_LIBUSB extern parport_driver_t xpcu_pp_driver; @@ -48,6 +49,7 @@ parport_driver_t *parport_drivers[] = { #endif /* HAVE_LINUX_PPDEV_H */ #ifdef HAVE_LIBFTDI &ftdi_parport_driver, + &ftdi_mpsse_parport_driver, #endif /* HAVE_LIBFTDI */ #ifdef HAVE_LIBUSB &xpcu_pp_driver, diff --git a/jtag/src/tap/parport/ftdi.c b/jtag/src/tap/parport/ftdi.c index e2263b0d..a4b1d89a 100644 --- a/jtag/src/tap/parport/ftdi.c +++ b/jtag/src/tap/parport/ftdi.c @@ -42,6 +42,7 @@ #include "cable.h" parport_driver_t ftdi_parport_driver; +parport_driver_t ftdi_mpsse_parport_driver; typedef struct port_node_t port_node_t; @@ -52,7 +53,8 @@ struct port_node_t { static port_node_t *ports = NULL; /* devices */ -#define OUTBUF_LEN 64 +#define OUTBUF_LEN_STD 64 +#define OUTBUF_LEN_MPSSE 4096 typedef struct { char *serial; @@ -60,20 +62,21 @@ typedef struct { unsigned int product_id; char autoflush; struct ftdi_context *fc; - unsigned char outcount; + int outcount; unsigned char *outbuf; + int outbuf_len; } ftdi_params_t; static int ftdi_flush_output ( ftdi_params_t *p ); static parport_t * -ftdi_parport_alloc( const char *vidpid ) +ftdi_parport_alloc( const char *vidpid, parport_driver_t * parport_driver, size_t outbuf_len ) { ftdi_params_t *params = malloc( sizeof *params ); parport_t *parport = malloc( sizeof *parport ); port_node_t *node = malloc( sizeof *node ); struct ftdi_context *fc = malloc( sizeof(struct ftdi_context) ); - unsigned char *outbuf = malloc( OUTBUF_LEN ); + unsigned char *outbuf = malloc( outbuf_len ); if (!node || !parport || !params || !fc || !outbuf) { free( node ); @@ -85,6 +88,7 @@ ftdi_parport_alloc( const char *vidpid ) ftdi_init(fc); params->outbuf = outbuf; + params->outbuf_len = outbuf_len; params->outcount = 0; params->autoflush = 0; params->product_id = 0; @@ -104,7 +108,7 @@ ftdi_parport_alloc( const char *vidpid ) }; parport->params = params; - parport->driver = &ftdi_parport_driver; + parport->driver = parport_driver; parport->cable = NULL; node->port = parport; @@ -137,13 +141,12 @@ ftdi_parport_free( parport_t *port ) free( port ); } -static cable_t * -ftdi_connect( const char **par, int parnum ) + +static cable_driver_t * +ftdi_pre_connect( const char **par, int parnum ) { int i; port_node_t *pn; - parport_t *parport; - cable_t *cable; if (parnum != 2) { printf( _("Syntax error!\n") ); @@ -173,21 +176,62 @@ ftdi_connect( const char **par, int parnum ) printf( _("Initializing %s on FTDI device %s\n"), _(cable_drivers[i]->description), par[0] ); - parport = ftdi_parport_alloc( par[0] ); + return cable_drivers[i]; +} + + +static cable_t * +ftdi_std_connect( const char **par, int parnum ) +{ + parport_t *parport; + cable_driver_t *cable_driver; + cable_t *cable; + + cable_driver = ftdi_pre_connect(par, parnum); + if (!cable_driver) + return NULL; + + parport = ftdi_parport_alloc( par[0], &ftdi_parport_driver, OUTBUF_LEN_STD ); if (!parport) { printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); return NULL; } - cable = cable_drivers[i]->connect( cable_drivers[i], parport ); + cable = cable_driver->connect( cable_driver, parport ); if (!cable) ftdi_parport_free( parport ); return cable; } + +static cable_t * +ftdi_mpsse_connect( const char **par, int parnum ) +{ + parport_t *parport; + cable_driver_t *cable_driver; + cable_t *cable; + + cable_driver = ftdi_pre_connect(par, parnum); + if (!cable_driver) + return NULL; + + parport = ftdi_parport_alloc( par[0], &ftdi_mpsse_parport_driver, OUTBUF_LEN_MPSSE ); + if (!parport) { + printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); + return NULL; + } + + cable = cable_driver->connect( cable_driver, parport ); + if (!cable) + ftdi_parport_free( parport ); + + return cable; +} + + static int -ftdi_open( parport_t *parport ) +ftdi_generic_open( parport_t *parport ) { int r; ftdi_params_t *p = parport->params; @@ -203,16 +247,32 @@ ftdi_open( parport_t *parport ) if(r<0) r = ftdi_usb_open_desc(fc, 0x09FB, 0x6002, NULL, p->serial); /* Cubic Cyclonium */ if(r<0) r = ftdi_usb_open_desc(fc, 0x09FB, 0x6003, NULL, p->serial); /* NIOS II Evaluation board */ if(r<0) r = ftdi_usb_open_desc(fc, 0x16C0, 0x06AD, NULL, p->serial); /* http://www.ixo.de/info/usb_jtag/ */ + if(r<0) r = ftdi_usb_open_desc(fc, 0x15BA, 0x0003, NULL, p->serial); /* Olimex ARM-USB-OCD */ }; if(r<0) { fprintf (stderr, "Can't open ftdi device: %s\n", - ftdi_get_error_string (fc)); + ftdi_get_error_string (fc)); ftdi_deinit(fc); return -1; }; + return 0; +} + + +static int +ftdi_std_open( parport_t *parport ) +{ + int r; + ftdi_params_t *p = parport->params; + struct ftdi_context *fc = p->fc; + + r = ftdi_generic_open(parport); + if (r < 0) + return r; + (void)ftdi_disable_bitbang(fc); if(ftdi_set_latency_timer(fc, 2)<0) @@ -249,6 +309,86 @@ ftdi_open( parport_t *parport ) return 0; } + +static int +ftdi_mpsse_open( parport_t *parport ) +{ + int r; + ftdi_params_t *p = parport->params; + struct ftdi_context *fc = p->fc; + + r = ftdi_generic_open(parport); + if (r < 0) + return r; + + /* This sequence might seem weird and containing superfluous stuff. + However, it's built after the description of JTAG_InitDevice + Ref. FTCJTAGPG10.pdf + Intermittent problems will occur when certain steps are skipped. */ + if (ftdi_usb_reset(fc) < 0) + { + fprintf (stderr, "Can't reset USB: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + } + if (ftdi_usb_purge_buffers(fc) < 0) + { + fprintf (stderr, "Can't purge USB buffers: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + } + + if (ftdi_set_bitmode(fc, 0x0b, BITMODE_RESET) < 0) + { + fprintf (stderr, "Can't reset bitmode: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + }; + if (ftdi_set_bitmode(fc, 0x0b, BITMODE_MPSSE) < 0) + { + fprintf (stderr, "Can't set mpsse mode: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + }; + + if (ftdi_usb_reset(fc) < 0) + { + fprintf (stderr, "Can't reset USB: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + } + if (ftdi_usb_purge_buffers(fc) < 0) + { + fprintf (stderr, "Can't purge USB buffers: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + } + + if(ftdi_set_latency_timer(fc, 2) < 0) + { + fprintf (stderr, "Can't set minimum latency: %s\n", + ftdi_get_error_string (fc)); + ftdi_usb_close(fc); + ftdi_deinit(fc); + return -1; + }; + + return 0; +} + + static int ftdi_flush_output ( ftdi_params_t *p ) { @@ -289,6 +429,7 @@ ftdi_close( parport_t *parport ) if(p->outcount > 0) ftdi_flush_output( p ); p->outcount = 0; + ftdi_disable_bitbang(p->fc); ftdi_usb_close(p->fc); ftdi_deinit(p->fc); @@ -308,7 +449,7 @@ ftdi_set_data( parport_t *parport, uint8_t data ) { p->outbuf[p->outcount++] = data; - if(p->outcount >= OUTBUF_LEN) + if(p->outcount >= p->outbuf_len) return ftdi_flush_output( p ); }; @@ -344,9 +485,21 @@ ftdi_set_control( parport_t *parport, uint8_t data ) parport_driver_t ftdi_parport_driver = { "ftdi", - ftdi_connect, + ftdi_std_connect, + ftdi_parport_free, + ftdi_std_open, + ftdi_close, + ftdi_set_data, + ftdi_get_data, + ftdi_get_status, + ftdi_set_control +}; + +parport_driver_t ftdi_mpsse_parport_driver = { + "ftdi-mpsse", + ftdi_mpsse_connect, ftdi_parport_free, - ftdi_open, + ftdi_mpsse_open, ftdi_close, ftdi_set_data, ftdi_get_data, diff --git a/jtag/src/tap/tap.c b/jtag/src/tap/tap.c index 5da6e269..885c1398 100644 --- a/jtag/src/tap/tap.c +++ b/jtag/src/tap/tap.c @@ -36,13 +36,9 @@ tap_reset( chain_t *chain ) { tap_state_reset( chain ); - chain_clock( chain, 1, 0 ); - chain_clock( chain, 1, 0 ); - chain_clock( chain, 1, 0 ); - chain_clock( chain, 1, 0 ); - chain_clock( chain, 1, 0 ); /* Test-Logic-Reset */ + chain_clock( chain, 1, 0, 5 ); /* Test-Logic-Reset */ - chain_clock( chain, 0, 0 ); /* Run-Test/Idle */ + chain_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */ } void @@ -55,7 +51,7 @@ tap_shift_register( chain_t *chain, const tap_register *in, tap_register *out, i /* Capture-DR, Capture-IR, Shift-DR, Shift-IR, Exit2-DR or Exit2-IR state */ if (tap_state( chain ) & TAPSTAT_CAPTURE) - chain_clock( chain, 0, 0 ); /* save last TDO bit :-) */ + chain_clock( chain, 0, 0, 1 ); /* save last TDO bit :-) */ i = in->len; if(exit) i--; @@ -69,12 +65,12 @@ tap_shift_register( chain_t *chain, const tap_register *in, tap_register *out, i for (; i < in->len; i++) { if (out && (i < out->len)) out->data[i] = cable_get_tdo( chain->cable ); - chain_clock( chain, (exit != EXITMODE_SHIFT && ((i + 1) == in->len)) ? 1 : 0, in->data[i] ); /* Shift (& Exit1) */ + chain_clock( chain, (exit != EXITMODE_SHIFT && ((i + 1) == in->len)) ? 1 : 0, in->data[i], 1 ); /* Shift (& Exit1) */ } /* Shift-DR, Shift-IR, Exit1-DR or Exit1-IR state */ if (exit == EXITMODE_IDLE) { - chain_clock( chain, 1, 0 ); /* Update-DR or Update-IR */ - chain_clock( chain, 0, 0 ); /* Run-Test/Idle */ + chain_clock( chain, 1, 0, 1 ); /* Update-DR or Update-IR */ + chain_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */ } } @@ -85,8 +81,8 @@ tap_capture_dr( chain_t *chain ) printf( _("%s: Invalid state: %2X\n"), "tap_capture_dr", tap_state( chain ) ); /* Run-Test/Idle or Update-DR or Update-IR state */ - chain_clock( chain, 1, 0 ); /* Select-DR-Scan */ - chain_clock( chain, 0, 0 ); /* Capture-DR */ + chain_clock( chain, 1, 0, 1 ); /* Select-DR-Scan */ + chain_clock( chain, 0, 0, 1 ); /* Capture-DR */ } void @@ -96,7 +92,6 @@ tap_capture_ir( chain_t *chain ) printf( _("%s: Invalid state: %2X\n"), "tap_capture_ir", tap_state( chain ) ); /* Run-Test/Idle or Update-DR or Update-IR state */ - chain_clock( chain, 1, 0 ); /* Select-DR-Scan */ - chain_clock( chain, 1, 0 ); /* Select-IR-Scan */ - chain_clock( chain, 0, 0 ); /* Capture-IR */ + chain_clock( chain, 1, 0, 2 ); /* Select-DR-Scan, then Select-IR-Scan */ + chain_clock( chain, 0, 0, 1 ); /* Capture-IR */ }