diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 32d58272..f3492e7f 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,25 @@ +2009-01-19 Kolja Waschk + + * doc/UrJTAG.txt, + include/cable.h, include/chain.h, include/pod.h, include/Makefile.am, + src/cmd/cmd.c, src/cmd/pod.c, src/cmd/Makefile.am, src/tap/cable.c, + src/tap/chain.c, src/tap/cable/wiggler.c, src/tap/cable/arcom.c, + src/tap/cable/mpcbdm.c, src/tap/cable/ts7800.c, + src/tap/cable/usbblaster.c, src/tap/cable/jlink.c, + src/tap/cable/generic.c, src/tap/cable/vision_ep9307.c, + src/tap/cable/ea253.c, src/tap/cable/triton.c, src/tap/cable/ei012.c, + src/tap/cable/byteblaster.c, src/tap/cable/generic.h, + src/tap/cable/ft2232.c, src/tap/cable/wiggler2.c, + src/tap/cable/keithkoep.c, src/tap/cable/lattice.c, + src/tap/cable/dlc5.c, src/tap/cable/xpc.c, src/svf/svf.c: + [ 2187351 ] Direct JTAG signal access, get/set_trst extension; + Integrated changes from getset_pod branch, substituting the + get/set_trst cable functions with more mighty get/set_signal + functions. Finally, this gives low level access to cable signals + as Sebastian Hesselbarth suggested and implemented first (thanks). + Arnim implemented it for the FTDI cable drivers, while I worked + on the parport cable drivers and new "pod" command. + 2009-01-16 Arnim Laeuger * src/cmd/parse.c: flush_chain() between commands read from file diff --git a/jtag/doc/UrJTAG.txt b/jtag/doc/UrJTAG.txt index 0653b70b..094aa2d4 100644 --- a/jtag/doc/UrJTAG.txt +++ b/jtag/doc/UrJTAG.txt @@ -816,6 +816,7 @@ of the TAP controller(s) and registers in the chain: *dr*:: display or set active data register for a part *instruction*:: change active instruction for a part or declare new instruction *get*:: get external signal value +*pod*:: low level direct access to POD signals like TRST; use with care *scan*:: detect changes on input pins of current part *set*:: set external signal value *shift*:: shift data/instruction registers through JTAG chain diff --git a/jtag/include/Makefile.am b/jtag/include/Makefile.am index 1e111b09..6164309a 100644 --- a/jtag/include/Makefile.am +++ b/jtag/include/Makefile.am @@ -50,6 +50,7 @@ noinst_HEADERS = \ fclock.h \ jim.h \ jim/some_cpu.h \ + pod.h \ svf.h \ usbconn.h \ usbconn/libftdx.h \ diff --git a/jtag/include/cable.h b/jtag/include/cable.h index 29c66d8e..02a2a6f6 100644 --- a/jtag/include/cable.h +++ b/jtag/include/cable.h @@ -33,6 +33,7 @@ typedef struct cable_t cable_t; #include "usbconn.h" #include "parport.h" #include "chain.h" +#include "pod.h" typedef struct cable_driver_t cable_driver_t; @@ -56,8 +57,8 @@ struct cable_driver_t { 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 ); - int (*get_trst)( cable_t * ); + int (*set_signal)( cable_t *, int, int ); + int (*get_signal)( cable_t *, pod_sigsel_t ); void (*flush)( cable_t *, cable_flush_amount_t ); void (*help)( const char * ); }; @@ -69,8 +70,8 @@ struct cable_queue_t { CABLE_CLOCK, CABLE_GET_TDO, CABLE_TRANSFER, - CABLE_SET_TRST, - CABLE_GET_TRST + CABLE_SET_SIGNAL, + CABLE_GET_SIGNAL } action; union { struct { @@ -79,8 +80,8 @@ struct cable_queue_t { int n; } clock; struct { - int tdo; - int trst; + pod_sigsel_t sig; + int mask; int val; } value; struct { @@ -129,11 +130,11 @@ void cable_clock( cable_t *cable, int tms, int tdi, int n ); int cable_get_tdo( cable_t *cable ); int cable_get_tdo_late( cable_t *cable ); int cable_defer_get_tdo( cable_t *cable ); -int cable_set_trst( cable_t *cable, int trst ); - int cable_defer_set_trst( cable_t *cable, int trst ); -int cable_get_trst( cable_t *cable ); - int cable_get_trst_late( cable_t *cable ); - int cable_defer_get_trst( cable_t *cable ); +int cable_set_signal( cable_t *cable, int mask, int val ); + int cable_defer_set_signal( cable_t *cable, int mask, int val ); +int cable_get_signal( cable_t *cable, pod_sigsel_t sig ); + int cable_get_signal_late( cable_t *cable, pod_sigsel_t sig ); + int cable_defer_get_signal( cable_t *cable, pod_sigsel_t sig ); int cable_transfer( cable_t *cable, int len, char *in, char *out ); int cable_transfer_late( cable_t *cable, char *out ); int cable_defer_transfer( cable_t *cable, int len, char *in, char *out ); diff --git a/jtag/include/chain.h b/jtag/include/chain.h index 3ffa5d5b..d2cbce2c 100644 --- a/jtag/include/chain.h +++ b/jtag/include/chain.h @@ -26,6 +26,7 @@ #define CHAIN_H #include "part.h" +#include "pod.h" typedef struct chain_t chain_t; @@ -58,6 +59,8 @@ void chain_shift_instructions_mode( chain_t *chain, int capture_output, int capt void chain_shift_data_registers( chain_t *chain, int capture_output ); void chain_shift_data_registers_mode( chain_t *chain, int capture_output, int capture, int exit ); void chain_flush( chain_t *chain ); +int chain_set_pod_signal( chain_t *chain, int mask, int val ); +int chain_get_pod_signal( chain_t *chain, pod_sigsel_t sig ); typedef struct { chain_t **chains; diff --git a/jtag/include/pod.h b/jtag/include/pod.h new file mode 100644 index 00000000..723f1751 --- /dev/null +++ b/jtag/include/pod.h @@ -0,0 +1,41 @@ +/* + * $Id$ + * + * Pod signal names + * Copyright (C) 2008 K. Waschk + * + * 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. + * + */ + +#ifndef POD_H +#define POD_H + +typedef enum +{ + CS_NONE = 0, // no/invalid signal + CS_TDI = (1<<0), // out: JTAG/SPI data in + CS_TCK = (1<<1), // out: JTAG/SPI clock + CS_TMS = (1<<2), // out: JTAG test mode select/SPI slave select + CS_TRST = (1<<3), // out: JTAG TAP reset + CS_RESET = (1<<4), // out: system reset + CS_SCK = (1<<5), // out: I2C clock (not yet used) + CS_SDA = (1<<6), // inout: I2C data (not yet used) + CS_SS = (1<<7), // out: SPI slave select (not yet used) +} +pod_sigsel_t; + +#endif /* POD_H */ diff --git a/jtag/src/cmd/Makefile.am b/jtag/src/cmd/Makefile.am index 99a36ea6..bd19bc59 100644 --- a/jtag/src/cmd/Makefile.am +++ b/jtag/src/cmd/Makefile.am @@ -55,6 +55,7 @@ libcmd_a_SOURCES = \ endian.c \ parse.c \ peekpoke.c \ + pod.c \ readmem.c \ writemem.c \ flashmem.c \ diff --git a/jtag/src/cmd/cmd.c b/jtag/src/cmd/cmd.c index 5da3a9eb..b8b26d0d 100644 --- a/jtag/src/cmd/cmd.c +++ b/jtag/src/cmd/cmd.c @@ -61,6 +61,7 @@ extern cmd_t cmd_set; extern cmd_t cmd_endian; extern cmd_t cmd_peek; extern cmd_t cmd_poke; +extern cmd_t cmd_pod; extern cmd_t cmd_readmem; extern cmd_t cmd_writemem; extern cmd_t cmd_detectflash; @@ -106,6 +107,7 @@ const cmd_t *cmds[] = { &cmd_endian, &cmd_peek, &cmd_poke, + &cmd_pod, &cmd_readmem, &cmd_writemem, &cmd_detectflash, diff --git a/jtag/src/cmd/pod.c b/jtag/src/cmd/pod.c new file mode 100644 index 00000000..ed4ff7ba --- /dev/null +++ b/jtag/src/cmd/pod.c @@ -0,0 +1,91 @@ +/* + * $Id$ + * + * Copyright (C) 2008 K. Waschk + * + * 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 Kolja Waschk, 2008 + * based on idea and code by Sebastian Hesselbarth, 2008 + * and code by Marcel Telka , 2003. + * + */ + +#include "sysdep.h" + +#include +#include +#include + +#include "jtag.h" +#include + +#include "cmd.h" + +static int +cmd_pod_run( chain_t *chain, char *params[] ) +{ + int i,j; + int mask = 0; + int val = 0; + + if ((i = cmd_params( params )) < 2) + return -1; + + if (!cmd_test_cable( chain )) + return -1; + + for (j=1; jcable, trst_cable); + cable_set_signal(chain->cable, CS_TRST, trst_cable ? CS_TRST : 0); return(1); } diff --git a/jtag/src/tap/cable.c b/jtag/src/tap/cable.c index 0dd590c6..9baffbbb 100644 --- a/jtag/src/tap/cable.c +++ b/jtag/src/tap/cable.c @@ -406,7 +406,7 @@ cable_get_tdo_late( cable_t *cable ) } else { - return cable->done.data[i].arg.value.tdo; + return cable->done.data[i].arg.value.val; } }; return cable->driver->get_tdo( cable ); @@ -423,58 +423,66 @@ cable_defer_get_tdo( cable_t *cable ) } int -cable_set_trst( cable_t *cable, int trst ) +cable_set_signal( cable_t *cable, int mask, int val ) { cable_flush( cable, COMPLETELY ); - return cable->driver->set_trst( cable, trst ); + return cable->driver->set_signal( cable, mask, val ); } int -cable_defer_set_trst( cable_t *cable, int trst ) +cable_defer_set_signal( cable_t *cable, int mask, int val ) { int i = cable_add_queue_item( cable, &(cable->todo) ); if( i < 0 ) return 1; /* report failure */ - cable->todo.data[i].action = CABLE_SET_TRST; - cable->todo.data[i].arg.value.trst = trst; + cable->todo.data[i].action = CABLE_SET_SIGNAL; + cable->todo.data[i].arg.value.mask = mask; + cable->todo.data[i].arg.value.val = val; cable_flush( cable, OPTIONALLY ); return 0; /* success */ } int -cable_get_trst( cable_t *cable ) +cable_get_signal( cable_t *cable, pod_sigsel_t sig ) { cable_flush( cable, COMPLETELY ); - return cable->driver->get_trst( cable ); + return cable->driver->get_signal( cable, sig ); } int -cable_get_trst_late( cable_t *cable ) +cable_get_signal_late( cable_t *cable, pod_sigsel_t sig ) { int i; cable_flush( cable, TO_OUTPUT ); i = cable_get_queue_item( cable, &(cable->done) ); if( i >= 0 ) { - if(cable->done.data[i].action != CABLE_GET_TRST) + if(cable->done.data[i].action != CABLE_GET_SIGNAL) { printf(_("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"), cable->done.data[i].action, &(cable->done), i); cable_purge_queue( &(cable->done), 1 ); } + else if(cable->done.data[i].arg.value.sig != sig) + { + printf(_("Internal error: Got wrong signal's value from queue (%d? %p.%d)\n"), + cable->done.data[i].action, &(cable->done), i); + cable_purge_queue( &(cable->done), 1 ); + } else { - return cable->done.data[i].arg.value.trst; + return cable->done.data[i].arg.value.val; } }; - return cable->driver->get_trst( cable ); + return cable->driver->get_signal( cable, sig ); } int -cable_defer_get_trst( cable_t *cable ) +cable_defer_get_signal( cable_t *cable, pod_sigsel_t sig ) { int i = cable_add_queue_item( cable, &(cable->todo) ); if( i < 0 ) return 1; /* report failure */ - cable->todo.data[i].action = CABLE_GET_TRST; + cable->todo.data[i].action = CABLE_GET_SIGNAL; + cable->todo.data[i].arg.value.sig = sig; cable_flush( cable, OPTIONALLY ); return 0; /* success */ } diff --git a/jtag/src/tap/cable/arcom.c b/jtag/src/tap/cable/arcom.c index e7e174fe..7a96f35a 100644 --- a/jtag/src/tap/cable/arcom.c +++ b/jtag/src/tap/cable/arcom.c @@ -60,9 +60,9 @@ arcom_init( cable_t *cable ) if ((data = parport_get_data( cable->link.port )) < 0) { if (parport_set_data( cable->link.port, 1 << TRST )) return -1; - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; } else - PARAM_TRST(cable) = (data >> TRST) & 1; + PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0; return 0; } @@ -71,33 +71,57 @@ static void arcom_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int arcom_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -arcom_set_trst( cable_t *cable, int trst ) +arcom_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t arcom_cable_driver = { @@ -112,8 +136,8 @@ cable_driver_t arcom_cable_driver = { arcom_clock, arcom_get_tdo, generic_transfer, - arcom_set_trst, - generic_get_trst, + arcom_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/byteblaster.c b/jtag/src/tap/cable/byteblaster.c index 2254204f..f4461874 100644 --- a/jtag/src/tap/cable/byteblaster.c +++ b/jtag/src/tap/cable/byteblaster.c @@ -75,8 +75,8 @@ byteblaster_init( cable_t *cable ) if (parport_open( cable->link.port )) return -1; - PARAM_TRST(cable) = 1; - + PARAM_SIGNALS(cable) = CS_TRST; + /* check if a ByteBlaster or ByteBlasterMV is connected */ parport_set_data( cable->link.port, 1 << BB_CHECK); if ( !( ( parport_get_status( cable->link.port ) >> BB_PRESENT ) & 1 ) ) @@ -110,20 +110,43 @@ byteblaster_clock( cable_t *cable, int tms, int tdi, int n ) parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int byteblaster_get_tdo( cable_t *cable ) { parport_set_data( cable->link.port, 0 << TCK ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -byteblaster_set_trst( cable_t *cable, int trst ) +byteblaster_set_signal( cable_t *cable, int mask, int val ) { - return 1; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } + + return prev_sigs; } cable_driver_t byteblaster_cable_driver = { @@ -138,8 +161,8 @@ cable_driver_t byteblaster_cable_driver = { byteblaster_clock, byteblaster_get_tdo, generic_transfer, - byteblaster_set_trst, - generic_get_trst, + byteblaster_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/dlc5.c b/jtag/src/tap/cable/dlc5.c index de7469cd..46d4c527 100644 --- a/jtag/src/tap/cable/dlc5.c +++ b/jtag/src/tap/cable/dlc5.c @@ -62,7 +62,7 @@ dlc5_init( cable_t *cable ) if (parport_open( cable->link.port )) return -1; - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; return 0; } @@ -81,20 +81,43 @@ dlc5_clock( cable_t *cable, int tms, int tdi, int n ) parport_set_data( cable->link.port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int dlc5_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (1 << PROG) | (0 << TCK) ); + parport_set_data( cable->link.port, (1 << PROG) | ( 0 << TCK ) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -dlc5_set_trst( cable_t *cable, int trst ) +dlc5_set_signal( cable_t *cable, int mask, int val ) { - return 1; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + parport_set_data( cable->link.port, ( 1 << PROG ) | data ); + PARAM_SIGNALS(cable) = sigs; + } + + return prev_sigs; } cable_driver_t dlc5_cable_driver = { @@ -109,8 +132,8 @@ cable_driver_t dlc5_cable_driver = { dlc5_clock, dlc5_get_tdo, generic_transfer, - dlc5_set_trst, - generic_get_trst, + dlc5_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/ea253.c b/jtag/src/tap/cable/ea253.c index 9ac34167..f26b936d 100644 --- a/jtag/src/tap/cable/ea253.c +++ b/jtag/src/tap/cable/ea253.c @@ -60,9 +60,9 @@ ea253_init( cable_t *cable ) if ((data = parport_get_data( cable->link.port )) < 0) { if (parport_set_data( cable->link.port, 1 << TRST )) return -1; - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; } else - PARAM_TRST(cable) = (data >> TRST) & 1; + PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0; return 0; } @@ -71,33 +71,57 @@ static void ea253_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int ea253_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -ea253_set_trst( cable_t *cable, int trst ) +ea253_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t ea253_cable_driver = { @@ -112,8 +136,8 @@ cable_driver_t ea253_cable_driver = { ea253_clock, ea253_get_tdo, generic_transfer, - ea253_set_trst, - generic_get_trst, + ea253_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/ei012.c b/jtag/src/tap/cable/ei012.c index 2d8e63f6..d306d330 100644 --- a/jtag/src/tap/cable/ei012.c +++ b/jtag/src/tap/cable/ei012.c @@ -62,9 +62,9 @@ ei012_init( cable_t *cable ) if ((data = parport_get_data( cable->link.port )) < 0) { if (parport_set_data( cable->link.port, 1 << TRST )) return -1; - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; } else - PARAM_TRST(cable) = (data >> TRST) & 1; + PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0; return 0; } @@ -73,33 +73,57 @@ static void ei012_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int ei012_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -ei012_set_trst( cable_t *cable, int trst ) +ei012_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t ei012_cable_driver = { @@ -114,8 +138,8 @@ cable_driver_t ei012_cable_driver = { ei012_clock, ei012_get_tdo, generic_transfer, - ei012_set_trst, - generic_get_trst, + ei012_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/ft2232.c b/jtag/src/tap/cable/ft2232.c index 9fb26ade..d67e9128 100644 --- a/jtag/src/tap/cable/ft2232.c +++ b/jtag/src/tap/cable/ft2232.c @@ -53,8 +53,8 @@ /* repeat the definitions for MPSSE command processor here - since we cannot rely on the existence of ftdih. even though - they're defined there */ + since we cannot rely on the existence of ftdi.h even though + they're defined there */ /* Shifting commands IN MPSSE Mode*/ #define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/ @@ -109,7 +109,7 @@ #define BIT_ARMUSBOCD_RED_LED 3 #define BITMASK_ARMUSBOCD_nOE (1 << BIT_ARMUSBOCD_nOE) #define BITMASK_ARMUSBOCD_nTRST (1 << BIT_ARMUSBOCD_nTRST) -#define BITMASK_ARMUSBOCD_nTSRST (1 << BIT_ARMUSBOCD_nTRST) +#define BITMASK_ARMUSBOCD_nTSRST (1 << BIT_ARMUSBOCD_nTSRST) #define BITMASK_ARMUSBOCD_nTRST_nOE (1 << BIT_ARMUSBOCD_nTRST_nOE) #define BITMASK_ARMUSBOCD_RED_LED (1 << BIT_ARMUSBOCD_RED_LED) /* bit and bitmask definitions for Blackfin gnICE */ @@ -173,18 +173,27 @@ typedef struct { uint8_t low_byte_value; uint8_t low_byte_dir; - /* this driver supports TRST control on high byte only - set the variables below with value/direction for active and inactive TRST line - static settings for other high byte signals must be entered here as well */ - uint8_t high_byte_value_trst_active; - uint8_t high_byte_value_trst_inactive; + /* this driver issues several "Set Data Bits High Byte" commands + here is the place where cable specific values can be stored + that are used each time this command is issued */ + uint8_t high_byte_value; uint8_t high_byte_dir; + /* the following variables store the bit position of TRST and RESET (SRST) + for XOR'ing with the default values of low_byte_value and high_byte_value + allowed values: + < 0 : feature not used + < 8 : applies to low byte + < 12 : applies to high byte */ + int bit_trst; + int bit_reset; + /* 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 */ unsigned int last_tdo_valid; unsigned int last_tdo; + int signals; cx_cmd_root_t cmd_root; } params_t; @@ -253,16 +262,20 @@ ft2232_generic_init( cable_t *cable ) cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = 0; + params->high_byte_value = 0; + params->high_byte_value = 0; + params->high_byte_dir = 0; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = -1; /* not used */ + params->bit_reset = -1; /* not used */ + params->last_tdo_valid = 0; + params->signals = 0; return 0; } @@ -293,22 +306,25 @@ ft2232_jtagkey_init( cable_t *cable ) TRST_N_OE_N = 0 SRST_N_OUT = 1 SRST_N_OE_N = 0 */ - params->high_byte_value_trst_active = BITMASK_JTAGKEY_SRST_N_OUT; - params->high_byte_value_trst_inactive = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OUT; - params->high_byte_dir = BITMASK_JTAGKEY_TRST_N_OUT + params->high_byte_value = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OUT; + params->high_byte_dir = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_JTAGKEY_TRST_N_OUT + 8; /* member of HIGH byte */ + params->bit_reset = BIT_JTAGKEY_SRST_N_OUT + 8; /* member of HIGH byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -340,25 +356,27 @@ ft2232_armusbocd_init( cable_t *cable ) TRST buffer enable = 0 TSRST = 1 RED LED on */ - params->high_byte_value_trst_active = BITMASK_ARMUSBOCD_nTSRST - | BITMASK_ARMUSBOCD_RED_LED; - params->high_byte_value_trst_inactive = BITMASK_ARMUSBOCD_nTRST + params->high_byte_value = BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTSRST | BITMASK_ARMUSBOCD_RED_LED; - params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST + params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | BITMASK_ARMUSBOCD_nTSRST | BITMASK_ARMUSBOCD_RED_LED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_ARMUSBOCD_nTRST + 8; /* member of HIGH byte */ + params->bit_reset = BIT_ARMUSBOCD_nTSRST + 8; /* member of HIGH byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -384,19 +402,22 @@ ft2232_gnice_init( cable_t *cable ) cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = BITMASK_GNICE_nLED; - params->high_byte_value_trst_inactive = BITMASK_GNICE_nTRST; - params->high_byte_dir = BITMASK_GNICE_nTRST | BITMASK_GNICE_nLED; + params->high_byte_value = BITMASK_GNICE_nTRST; + params->high_byte_dir = BITMASK_GNICE_nTRST | BITMASK_GNICE_nLED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_GNICE_nTRST + 8; /* member of HIGH byte */ + params->bit_reset = -1; /* not used */ + params->last_tdo_valid = 0; + params->signals = CS_TRST; return 0; } @@ -427,23 +448,26 @@ ft2232_oocdlinks_init( cable_t *cable ) TRST buffer enable = 0 SRST = 1 SRST buffer enable = 0 */ - params->high_byte_value_trst_active = BITMASK_OOCDLINKS_nSRST; - params->high_byte_value_trst_inactive = BITMASK_OOCDLINKS_nTRST + params->high_byte_value = BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nSRST; - params->high_byte_dir = BITMASK_OOCDLINKS_nTRST + params->high_byte_dir = BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nTRST_nOE | BITMASK_OOCDLINKS_nSRST | BITMASK_OOCDLINKS_nSRST_nOE; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_OOCDLINKS_nTRST + 8; /* member of HIGH byte */ + params->bit_reset = BIT_OOCDLINKS_nSRST + 8; /* member of HIGH byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -474,16 +498,19 @@ ft2232_turtelizer2_init( cable_t *cable ) default: TX1LED on RX1LED on */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED; + params->high_byte_value = 0; + params->high_byte_dir = BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = -1; /* not used */ + params->bit_reset = BIT_TURTELIZER2_RST; /* member of LOW byte */ + params->last_tdo_valid = 0; + params->signals = CS_RESET; return 0; } @@ -513,18 +540,22 @@ ft2232_usbtojtagif_init( cable_t *cable ) default: RxLED on TxLED on */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED; + params->high_byte_value = 0; + params->high_byte_value = 0; + params->high_byte_dir = BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); /* I-couplers can only work up to 3 MHz ref. http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html */ ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ/2 ); + params->bit_trst = BIT_USBTOJTAGIF_nTRST; /* member of LOW byte */ + params->bit_reset = BIT_USBTOJTAGIF_RST; /* member of LOW byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -539,7 +570,7 @@ ft2232_signalyzer_init( cable_t *cable ) if (usbconn_open( cable->link.usb )) return -1; /* static low byte value and direction: - nTRST = 1, RST = 1, DBGRQ = 0 */ + nTRST = 1, nSRST = 1 */ params->low_byte_value = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; params->low_byte_dir = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; @@ -551,16 +582,19 @@ ft2232_signalyzer_init( cable_t *cable ) cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = 0; + params->high_byte_value = 0; + params->high_byte_dir = 0; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_SIGNALYZER_nTRST; /* member of LOW byte */ + params->bit_reset = BIT_SIGNALYZER_nSRST; /* member of LOW byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -575,8 +609,8 @@ ft2232_flyswatter_init( cable_t *cable ) if (usbconn_open( cable->link.usb )) return -1; /* static low byte value and direction: - nTRST = 1, set nOE1 and nOE2 to '0' -> activate output enables */ - params->low_byte_value = BITMASK_FLYSWATTER_nTRST; + nTRST = 1, nSRST = 1, set nOE1 and nOE2 to '0' -> activate output enables */ + params->low_byte_value = BITMASK_FLYSWATTER_nTRST | BIT_FLYSWATTER_nSRST; params->low_byte_dir = BITMASK_FLYSWATTER_nOE1 | BITMASK_FLYSWATTER_nOE2 | BITMASK_FLYSWATTER_nTRST | BITMASK_FLYSWATTER_nSRST; @@ -589,16 +623,19 @@ ft2232_flyswatter_init( cable_t *cable ) /* Set Data Bits High Byte */ /* Turn LED2 on */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = BITMASK_FLYSWATTER_nLED2; + params->high_byte_value = 0; + params->high_byte_dir = BITMASK_FLYSWATTER_nLED2; cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_value ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + params->bit_trst = BIT_FLYSWATTER_nTRST; /* member of LOW byte */ + params->bit_reset = BIT_FLYSWATTER_nSRST; /* member of LOW byte */ + params->last_tdo_valid = 0; + params->signals = CS_TRST | CS_RESET; return 0; } @@ -954,6 +991,11 @@ ft2232_clock_schedule( cable_t *cable, int tms, int tdi, int n ) } cx_cmd_push( cmd_root, tdi | tms ); } + + params->signals &= ~(CS_TMS | CS_TDI | CS_TCK); + if (tms) params->signals |= CS_TMS; + if (tdi) params->signals |= CS_TDI; + // if (tck) params->signals |= CS_TCK; } @@ -1007,27 +1049,84 @@ ft2232_get_tdo( cable_t *cable ) static void -ft2232_set_trst_schedule( params_t *params, int trst ) +ft2232_set_signal_schedule( params_t *params, int mask, int val, + int set_low, int set_high ) { cx_cmd_root_t *cmd_root = &(params->cmd_root); - cx_cmd_queue( cmd_root, 0 ); - cx_cmd_push( cmd_root, SET_BITS_HIGH ); - cx_cmd_push( cmd_root, - trst == 0 ? params->high_byte_value_trst_active : params->high_byte_value_trst_inactive ); - cx_cmd_push( cmd_root, params->high_byte_dir ); + /* filter for supported signals */ + mask &= CS_TCK | CS_TDI | CS_TMS | CS_TRST | CS_RESET; + if (mask != 0) + { + int sigs = (params->signals & ~mask) | (val & mask); + uint8_t low_or = 0; + uint8_t low_xor = 0; + uint8_t high_xor = 0; + + /* prepare low and high byte */ + if (sigs & CS_TCK) low_or |= BITMASK_TCK; + if (sigs & CS_TDI) low_or |= BITMASK_TDI; + if (sigs & CS_TMS) low_or |= BITMASK_TMS; + /* TRST and RESET (SRST) are XOR'ed to the default value since + the right value depends on the external circuitry (inverter or not) */ + if ((sigs & CS_TRST) == 0) + if (params->bit_trst >= 0) + { + if (params->bit_trst < 8) + { + low_xor |= 1 << params->bit_trst; + } + else + { + high_xor |= 1 << (params->bit_trst - 8); + } + } + if ((sigs & CS_RESET) == 0) + if (params->bit_reset >= 0) + { + if (params->bit_reset < 8) + { + low_xor |= 1 << params->bit_reset; + } + else + { + high_xor |= 1 << (params->bit_reset - 8); + } + } + + if (set_low) + { + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, (params->low_byte_value | low_or) ^ low_xor ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + } + + if (set_high) + { + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value ^ high_xor ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + } + + params->signals = sigs; + } } + static int -ft2232_set_trst( cable_t *cable, int trst ) +ft2232_set_signal( cable_t *cable, int mask, int val ) { params_t *params = (params_t *)cable->params; - ft2232_set_trst_schedule( params, trst ); + int prev_sigs = params->signals; + + ft2232_set_signal_schedule( params, mask, val, 1, 1 ); cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY ); params->last_tdo_valid = 0; - return trst; + return prev_sigs; } @@ -1040,13 +1139,9 @@ ft2232_transfer_schedule( cable_t *cable, int len, char *in, char *out ) int bitwise_len; int chunkbytes; - /* Set Data Bits Low Byte to lower TMS for transfer - TCK = 0, TMS = 0, TDI = 0, nOE = 0 */ - cx_cmd_queue( cmd_root, 0 ); - cx_cmd_push( cmd_root, SET_BITS_LOW ); - cx_cmd_push( cmd_root, params->low_byte_value | 0 ); - cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - + /* lower TMS for transfer + also lower TCK to ensure correct clocking */ + ft2232_set_signal_schedule( params, CS_TCK | CS_TMS, 0, 1, 0 ); chunkbytes = len >> 3; while (chunkbytes > 0) @@ -1247,6 +1342,7 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) while (cable->todo.num_items > 0) { int i, j, n; + int post_signals = params->signals; int last_tdo_valid_schedule = params->last_tdo_valid; int last_tdo_valid_finish = params->last_tdo_valid; @@ -1271,8 +1367,10 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) } break; - case CABLE_SET_TRST: - ft2232_set_trst_schedule( params, cable->todo.data[i].arg.value.trst ); + case CABLE_SET_SIGNAL: + ft2232_set_signal_schedule( params, + cable->todo.data[i].arg.value.mask, + cable->todo.data[i].arg.value.val, 1, 1 ); last_tdo_valid_schedule = 0; break; @@ -1300,8 +1398,13 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) switch (cable->todo.data[j].action) { case CABLE_CLOCK: - params->last_tdo_valid = last_tdo_valid_finish = 0; - break; + { + post_signals &= ~(CS_TCK | CS_TDI | CS_TMS); + post_signals |= (cable->todo.data[j].arg.clock.tms ? CS_TMS : 0); + post_signals |= (cable->todo.data[j].arg.clock.tdi ? CS_TDI : 0); + params->last_tdo_valid = last_tdo_valid_finish = 0; + break; + } case CABLE_GET_TDO: { int tdo; @@ -1313,21 +1416,24 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) last_tdo_valid_finish = params->last_tdo_valid; m = cable_add_queue_item( cable, &(cable->done) ); cable->done.data[m].action = CABLE_GET_TDO; - cable->done.data[m].arg.value.tdo = tdo; + cable->done.data[m].arg.value.val = tdo; break; } - case CABLE_SET_TRST: + case CABLE_SET_SIGNAL: { int m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_SET_TRST; - cable->done.data[m].arg.value.trst = cable->done.data[j].arg.value.trst; - params->last_tdo_valid = last_tdo_valid_finish = 0; + cable->done.data[m].action = CABLE_SET_SIGNAL; + cable->done.data[m].arg.value.mask = cable->todo.data[j].arg.value.mask; + cable->done.data[m].arg.value.val = post_signals; + int mask = cable->todo.data[j].arg.value.mask & ~(CS_TCK | CS_TDI | CS_TMS | CS_TRST | CS_RESET); + post_signals = (post_signals & ~mask) | (cable->todo.data[j].arg.value.val & mask); } - case CABLE_GET_TRST: + case CABLE_GET_SIGNAL: { int m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_GET_TRST; - cable->done.data[m].arg.value.trst = 1; + cable->done.data[m].action = CABLE_GET_SIGNAL; + cable->done.data[m].arg.value.sig = cable->todo.data[j].arg.value.sig; + cable->done.data[m].arg.value.val = (post_signals & cable->todo.data[j].arg.value.sig) ? 1 : 0; break; } case CABLE_TRANSFER: @@ -1480,8 +1586,8 @@ cable_driver_t ft2232_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1512,8 +1618,8 @@ cable_driver_t ft2232_armusbocd_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1558,8 +1664,8 @@ cable_driver_t ft2232_gnice_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1590,8 +1696,8 @@ cable_driver_t ft2232_jtagkey_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1622,8 +1728,8 @@ cable_driver_t ft2232_oocdlinks_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1654,8 +1760,8 @@ cable_driver_t ft2232_turtelizer2_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1686,8 +1792,8 @@ cable_driver_t ft2232_usbtojtagif_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1718,8 +1824,8 @@ cable_driver_t ft2232_signalyzer_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; @@ -1750,8 +1856,8 @@ cable_driver_t ft2232_flyswatter_cable_driver = { ft2232_clock, ft2232_get_tdo, ft2232_transfer, - ft2232_set_trst, - generic_get_trst, + ft2232_set_signal, + generic_get_signal, ft2232_flush, ft2232_usbcable_help }; diff --git a/jtag/src/tap/cable/generic.c b/jtag/src/tap/cable/generic.c index 595bc295..fa80aacb 100644 --- a/jtag/src/tap/cable/generic.c +++ b/jtag/src/tap/cable/generic.c @@ -83,9 +83,9 @@ generic_transfer( cable_t *cable, int len, char *in, char *out ) } int -generic_get_trst( cable_t *cable ) +generic_get_signal( cable_t *cable, pod_sigsel_t sig ) { - return PARAM_TRST(cable); + return (((PARAM_SIGNALS(cable)) & sig) != 0) ? 1:0; } int @@ -104,7 +104,7 @@ do_one_queued_action( cable_t *cable ) if( cable->done.num_items >= cable->done.max_items ) { if( cable->todo.data[i].action == CABLE_GET_TDO - || cable->todo.data[i].action == CABLE_GET_TRST + || cable->todo.data[i].action == CABLE_GET_SIGNAL || cable->todo.data[i].action == CABLE_TRANSFER ) { printf(_("No space in cable activity results queue.\n")); @@ -120,9 +120,10 @@ do_one_queued_action( cable_t *cable ) cable->todo.data[i].arg.clock.tdi, cable->todo.data[i].arg.clock.n ); break; - case CABLE_SET_TRST: - cable_set_trst( cable, - cable->todo.data[i].arg.value.trst ); + case CABLE_SET_SIGNAL: + cable_set_signal( cable, + cable->todo.data[i].arg.value.sig, + cable->todo.data[i].arg.value.val ); break; case CABLE_TRANSFER: { @@ -151,17 +152,20 @@ do_one_queued_action( cable_t *cable ) printf("add result from get_tdo to %p.%d\n", &(cable->done), j); #endif cable->done.data[j].action = CABLE_GET_TDO; - cable->done.data[j].arg.value.tdo = + cable->done.data[j].arg.value.val = cable->driver->get_tdo( cable ); break; - case CABLE_GET_TRST: + case CABLE_GET_SIGNAL: j = cable_add_queue_item( cable, &(cable->done) ); #ifdef VERBOSE - printf("add result from get_trst to %p.%d\n", &(cable->done), j); + printf("add result from get_signal to %p.%d\n", &(cable->done), j); #endif - cable->done.data[j].action = CABLE_GET_TRST; - cable->done.data[j].arg.value.trst = - cable->driver->get_trst( cable ); + cable->done.data[j].action = CABLE_GET_SIGNAL; + cable->done.data[j].arg.value.sig = + cable->todo.data[i].arg.value.sig; + cable->done.data[j].arg.value.val = + cable->driver->get_signal( cable, + cable->todo.data[i].arg.value.sig ); break; }; #ifdef VERBOSE @@ -316,7 +320,7 @@ generic_flush_using_transfer( cable_t *cable, cable_flush_amount_t how_much ) printf("add result from transfer to %p.%d\n", &(cable->done), c); #endif cable->done.data[c].action = CABLE_GET_TDO; - cable->done.data[c].arg.value.tdo = tdo; + cable->done.data[c].arg.value.val = tdo; } else if(cable->todo.data[i].action == CABLE_TRANSFER) { diff --git a/jtag/src/tap/cable/generic.h b/jtag/src/tap/cable/generic.h index b56811cf..3fbb75de 100644 --- a/jtag/src/tap/cable/generic.h +++ b/jtag/src/tap/cable/generic.h @@ -29,17 +29,15 @@ #include "parport.h" typedef struct { - int trst; - int sreset; + int signals; } generic_params_t; -#define PARAM_TRST(cable) ((generic_params_t *) cable->params)->trst -#define PARAM_SRESET(cable) ((generic_params_t *) cable->params)->sreset +#define PARAM_SIGNALS(cable) ((generic_params_t *) cable->params)->signals void generic_disconnect( cable_t *cable ); void generic_set_frequency( cable_t *cable, uint32_t new_freq ); int generic_transfer( cable_t *cable, int len, char *in, char *out ); -int generic_get_trst( cable_t *cable ); +int generic_get_signal( cable_t *cable, pod_sigsel_t sig ); void generic_flush_one_by_one( cable_t *cable, cable_flush_amount_t hm ); void generic_flush_using_transfer( cable_t *cable, cable_flush_amount_t hm ); diff --git a/jtag/src/tap/cable/jlink.c b/jtag/src/tap/cable/jlink.c index 33947a22..13950c93 100644 --- a/jtag/src/tap/cable/jlink.c +++ b/jtag/src/tap/cable/jlink.c @@ -562,7 +562,7 @@ jlink_transfer( cable_t *cable, int len, char *in, char *out ) /* ---------------------------------------------------------------------- */ static int -jlink_set_trst( cable_t *cable, int trst ) +jlink_set_signal( cable_t *cable, int mask, int val ) { return 1; } @@ -579,8 +579,8 @@ cable_driver_t jlink_cable_driver = { jlink_clock, jlink_get_tdo, jlink_transfer, - jlink_set_trst, - generic_get_trst, + jlink_set_signal, + generic_get_signal, generic_flush_using_transfer, generic_usbconn_help }; diff --git a/jtag/src/tap/cable/keithkoep.c b/jtag/src/tap/cable/keithkoep.c index b8528e6c..a3e50fa1 100644 --- a/jtag/src/tap/cable/keithkoep.c +++ b/jtag/src/tap/cable/keithkoep.c @@ -70,7 +70,7 @@ keithkoep_init( cable_t *cable ) return -1; parport_set_control( cable->link.port, 1 << TRST ); - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; return 0; } @@ -89,23 +89,51 @@ keithkoep_clock( cable_t *cable, int tms, int tdi, int n ) parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int keithkoep_get_tdo( cable_t *cable ) { parport_set_data( cable->link.port, 0 << TCK ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -keithkoep_set_trst( cable_t *cable, int trst ) +keithkoep_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int sigs = (prev_sigs & ~mask) | (val & mask); + + if ((mask & ~CS_TRST) != 0) + { + int data = 0; + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + parport_set_data( cable->link.port, data ); + } + if ((mask & CS_TRST) != 0) + { + parport_set_control( cable->link.port, (sigs & CS_TRST) ? (1 << TRST) : 0 ); + } + PARAM_SIGNALS(cable) = sigs; + } - parport_set_control( cable->link.port, PARAM_TRST(cable) << TRST ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t keithkoep_cable_driver = { @@ -120,8 +148,8 @@ cable_driver_t keithkoep_cable_driver = { keithkoep_clock, keithkoep_get_tdo, generic_transfer, - keithkoep_set_trst, - generic_get_trst, + keithkoep_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/lattice.c b/jtag/src/tap/cable/lattice.c index ddcff4b0..ef47dd42 100644 --- a/jtag/src/tap/cable/lattice.c +++ b/jtag/src/tap/cable/lattice.c @@ -54,11 +54,18 @@ static int lattice_init( cable_t *cable ) { + int data; + if (parport_open( cable->link.port )) return -1; - PARAM_TRST(cable) = 1; - + if ((data = parport_get_data( cable->link.port )) < 0) { + if (parport_set_data( cable->link.port, 1 << TRST )) + return -1; + PARAM_SIGNALS(cable) = CS_TRST; + } else + PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0; + return 0; } @@ -66,30 +73,57 @@ static void lattice_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (0 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); - parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) ); + parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int lattice_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (0 << TCK) | (1 << TRST) ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -lattice_set_trst( cable_t *cable, int trst ) +lattice_set_signal( cable_t *cable, int mask, int val ) { - return parport_set_data( cable->link.port, trst << TRST ); + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } + + return prev_sigs; } cable_driver_t lattice_cable_driver = { @@ -104,8 +138,8 @@ cable_driver_t lattice_cable_driver = { lattice_clock, lattice_get_tdo, generic_transfer, - lattice_set_trst, - generic_get_trst, + lattice_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/mpcbdm.c b/jtag/src/tap/cable/mpcbdm.c index 574e197c..fac84c57 100644 --- a/jtag/src/tap/cable/mpcbdm.c +++ b/jtag/src/tap/cable/mpcbdm.c @@ -67,8 +67,8 @@ mpcbdm_init( cable_t *cable ) if (parport_open( cable->link.port )) return -1; - parport_set_control( cable->link.port, 0 << TRST ); - PARAM_TRST(cable) = 1; + parport_set_control( cable->link.port, 0 ); + PARAM_SIGNALS(cable) = ( CS_TRST | CS_RESET ); return 0; } @@ -87,23 +87,54 @@ mpcbdm_clock( cable_t *cable, int tms, int tdi, int n ) parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= (CS_TRST | CS_RESET); + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int mpcbdm_get_tdo( cable_t *cable ) { parport_set_data( cable->link.port, 0 << TCK ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -mpcbdm_set_trst( cable_t *cable, int trst ) +mpcbdm_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST | CS_RESET); // only these can be modified + + if (mask) + { + int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask); + + if ((mask & ~(CS_TRST | CS_RESET)) != 0) + { + int data = 0; + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + parport_set_data( cable->link.port, data ); + } + if ((mask & (CS_TRST | CS_RESET)) != 0) + { + int data = 0; + data |= (sigs & CS_TRST) ? 0 : (1 << TRST); + // data |= (sigs & CS_RESET) ? 0 : (1 << SRESET); // use SRESET or HRESET? which polarity? + parport_set_control( cable->link.port, data ); + } + PARAM_SIGNALS(cable) = sigs; + } - parport_set_control( cable->link.port, (PARAM_TRST(cable) ^ 1) << TRST ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t mpcbdm_cable_driver = { @@ -118,8 +149,8 @@ cable_driver_t mpcbdm_cable_driver = { mpcbdm_clock, mpcbdm_get_tdo, generic_transfer, - mpcbdm_set_trst, - generic_get_trst, + mpcbdm_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/triton.c b/jtag/src/tap/cable/triton.c index 6a9f2e3f..5ad8ddeb 100644 --- a/jtag/src/tap/cable/triton.c +++ b/jtag/src/tap/cable/triton.c @@ -72,8 +72,8 @@ triton_init( cable_t *cable ) if (parport_open( cable->link.port )) return -1; - PARAM_TRST(cable) = 1; - PARAM_SRESET(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST | CS_RESET; + parport_set_data( cable->link.port, (1 << TRST) | (1 << SRESET) ); return 0; } @@ -82,33 +82,60 @@ static void triton_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + int sreset = (PARAM_SIGNALS(cable) & CS_RESET) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= (CS_TRST | CS_RESET); + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int triton_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + int sreset = (PARAM_SIGNALS(cable) & CS_RESET) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (0 << TCK) ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -triton_set_trst( cable_t *cable, int trst ) +triton_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST | CS_RESET); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + data |= (sigs & CS_RESET) ? (1 << SRESET) : 0; + parport_set_data( cable->link.port, data ); + PARAM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t triton_cable_driver = { @@ -123,8 +150,8 @@ cable_driver_t triton_cable_driver = { triton_clock, triton_get_tdo, generic_transfer, - triton_set_trst, - generic_get_trst, + triton_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/ts7800.c b/jtag/src/tap/cable/ts7800.c index 090f2dd7..d3448f4d 100644 --- a/jtag/src/tap/cable/ts7800.c +++ b/jtag/src/tap/cable/ts7800.c @@ -71,7 +71,7 @@ typedef struct { void *map_base; size_t map_size; uint32_t *gpio_base; - int trst; + int signals; uint32_t lastout; } ts7800_params_t; @@ -126,6 +126,7 @@ ts7800_gpio_close( cable_t *cable ) static int ts7800_gpio_write( cable_t *cable, uint8_t data ) { + int sigs; ts7800_params_t *p = cable->params; p->gpio_base[GPIO_OUT] = p->lastout = (p->lastout & GPIO_BITMASK) | data; @@ -190,7 +191,7 @@ ts7800_init( cable_t *cable ) if (ts7800_gpio_open( cable )) return -1; - p->trst = 1; + p->signals = CS_TRST; return 0; } @@ -225,24 +226,52 @@ ts7800_clock( cable_t *cable, int tms, int tdi, int n ) static int ts7800_get_tdo( cable_t *cable ) { - ts7800_gpio_write( cable, ((ts7800_params_t *)cable->params)->lastout & ~(0 << TCK) ); + ts7800_params_t *p = cable->params; + ts7800_gpio_write( cable, p->lastout & ~(0 << TCK) ); + return (ts7800_gpio_read( cable ) >> TDO) & 1; } static int -ts7800_set_trst( cable_t *cable, int trst ) +ts7800_current_signals( cable_t *cable ) +{ + ts7800_params_t *p = cable->params; + + int sigs = p->signals & ~(CS_TMS | CS_TDI | CS_TCK); + if (p->lastout & (1 << TCK)) sigs |= CS_TCK; + if (p->lastout & (1 << TDI)) sigs |= CS_TDI; + if (p->lastout & (1 << TMS)) sigs |= CS_TMS; + + return sigs; +} + +static int +ts7800_set_signal( cable_t *cable, int mask, int val ) { ts7800_params_t *p = cable->params; - p->trst = trst ? 1 : 0; + int prev_sigs = current_signals( cable ); - return p->trst; + mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified + + if (mask != 0) + { + sigs = (prev_sigs & ~mask) | (val & mask); + tms = (sigs & CS_TMS) ? (1 << TMS) : 0; + tdi = (sigs & CS_TDI) ? (1 << TDI) : 0; + tck = (sigs & CS_TCK) ? (1 << TCK) : 0; + ts7800_gpio_write( cable, tms | tdi | tck ); + } + + return prev_sigs; } static int -ts7800_get_trst( cable_t *cable ) +ts7800_get_signal( cable_t *cable, pod_sigsel_t sig ) { - return ((ts7800_params_t *)cable->params)->trst; + ts7800_params_t *p = cable->params; + + return (current_signals( cable ) & sig) ? 1 : 0; } static void @@ -266,8 +295,8 @@ cable_driver_t ts7800_cable_driver = { ts7800_clock, ts7800_get_tdo, generic_transfer, - ts7800_set_trst, - ts7800_get_trst, + ts7800_set_signal, + ts7800_get_signal, generic_flush_one_by_one, ts7800_help }; diff --git a/jtag/src/tap/cable/usbblaster.c b/jtag/src/tap/cable/usbblaster.c index ebea3bec..8afc9515 100644 --- a/jtag/src/tap/cable/usbblaster.c +++ b/jtag/src/tap/cable/usbblaster.c @@ -230,7 +230,7 @@ usbblaster_get_tdo( cable_t *cable ) } static int -usbblaster_set_trst( cable_t *cable, int trst ) +usbblaster_set_signal( cable_t *cable, int mask, int val ) { return 1; } @@ -404,16 +404,20 @@ usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) int m; m = cable_add_queue_item( cable, &(cable->done) ); cable->done.data[m].action = CABLE_GET_TDO; - cable->done.data[m].arg.value.tdo = usbblaster_get_tdo_finish( cable ); + cable->done.data[m].arg.value.val = usbblaster_get_tdo_finish( cable ); break; } - case CABLE_GET_TRST: + case CABLE_GET_SIGNAL: { int m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_GET_TRST; - cable->done.data[m].arg.value.trst = 1; + cable->done.data[m].action = CABLE_GET_SIGNAL; + cable->done.data[m].arg.value.sig = cable->todo.data[j].arg.value.sig; + if (cable->todo.data[j].arg.value.sig == CS_TRST) + cable->done.data[m].arg.value.val = 1; + else + cable->done.data[m].arg.value.val = -1; // not supported yet break; - } + } case CABLE_TRANSFER: { int r = usbblaster_transfer_finish( cable, @@ -475,8 +479,8 @@ cable_driver_t usbblaster_cable_driver = { usbblaster_clock, usbblaster_get_tdo, usbblaster_transfer, - usbblaster_set_trst, - generic_get_trst, + usbblaster_set_signal, + generic_get_signal, // generic_flush_one_by_one, // generic_flush_using_transfer, usbblaster_flush, diff --git a/jtag/src/tap/cable/vision_ep9307.c b/jtag/src/tap/cable/vision_ep9307.c index d28800f2..9aa223f8 100644 --- a/jtag/src/tap/cable/vision_ep9307.c +++ b/jtag/src/tap/cable/vision_ep9307.c @@ -73,7 +73,8 @@ typedef struct { void *map_base; size_t map_size; uint32_t *gpio_PHDR; - int trst; + uint32_t lastout; + int signals; } ep9307_params_t; static int @@ -167,6 +168,7 @@ ep9307_gpio_write( cable_t *cable, uint8_t data ) tmp &= ~GPIO_OUTPUT_MASK; tmp |= data; *((uint32_t*)p->gpio_PHDR) = tmp; + p->lastout = tmp; return 0; } @@ -224,7 +226,7 @@ ep9307_init( cable_t *cable ) ep9307_gpio_write( cable, 1 << TRST ); cable_wait( cable ); - p->trst = 1; + p->signals = CS_TRST; return 0; } @@ -265,28 +267,50 @@ ep9307_get_tdo( cable_t *cable ) ep9307_gpio_write( cable, (0 << TCK) | (p->trst << TRST) ); cable_wait( cable ); + return (ep9307_gpio_read( cable ) >> TDO) & 1; } -/** - * NOTE: This also lowers the TCK, TDI, and TMS lines; is this intended? - */ static int -ep9307_set_trst( cable_t *cable, int trst ) +ep9307_current_signals( cable_t *cable ) { ep9307_params_t *p = cable->params; - p->trst = trst ? 1 : 0; + int sigs = p->signals & ~(CS_TMS | CS_TDI | CS_TCK | CS_TRST); + if (p->lastout & (1 << TCK)) sigs |= CS_TCK; + if (p->lastout & (1 << TDI)) sigs |= CS_TDI; + if (p->lastout & (1 << TMS)) sigs |= CS_TMS; + if (p->lastout & (1 << TRST)) sigs |= CS_TRST; - ep9307_gpio_write( cable, p->trst << TRST ); - cable_wait( cable ); - return p->trst; + return sigs; +} + +static int +ep9307_set_signal( cable_t *cable, int mask, int val ) +{ + ep9307_params_t *p = cable->params; + + int prev_sigs = ep9307_current_signals (cable); + + int mask &= (CS_TMS | CS_TDI | CS_TCK | CS_TRST); // only these can be modified + + if (mask != 0) + { + int sigs = (prev_sigs & ~mask) | (val & mask); + int tms = (sigs & CS_TMS) ? (1 << TMS) : 0; + int tdi = (sigs & CS_TDI) ? (1 << TDI) : 0; + int tck = (sigs & CS_TCK) ? (1 << TCK) : 0; + int trst = (sigs & CS_TRST) ? (1 << TRST) : 0; + ep9307_gpio_write( cable, tms | tdi | tck | trst ); + } + + return prev_sigs; } static int -ep9307_get_trst( cable_t *cable ) +ep9307_get_signal( cable_t *cable, pod_sigsel_t sig ) { - return (ep9307_gpio_read( cable ) >> TRST) & 1; + return (ep9307_current_signals( cable ) & sig) ? 1 : 0; } static void diff --git a/jtag/src/tap/cable/wiggler.c b/jtag/src/tap/cable/wiggler.c index 9f720658..a173ff55 100644 --- a/jtag/src/tap/cable/wiggler.c +++ b/jtag/src/tap/cable/wiggler.c @@ -78,6 +78,7 @@ char *std_wgl_map = xstr(TDO) "," /* private parameters of this cable driver */ typedef struct { + int signals; int trst_lvl; int srst_act, srst_inact; int tms_act, tms_inact; @@ -90,6 +91,7 @@ typedef struct { /* access macros for the parameters */ +#define PRM_SIGNALS(cable) ((wiggler_params_t *) cable->params)->signals #define PRM_TRST_LVL(cable) ((wiggler_params_t *) cable->params)->trst_lvl #define PRM_SRST_ACT(cable) ((wiggler_params_t *) cable->params)->srst_act #define PRM_SRST_INACT(cable) ((wiggler_params_t *) cable->params)->srst_inact @@ -245,6 +247,8 @@ wiggler_init( cable_t *cable ) } else PRM_TRST_LVL(cable) = data & (PRM_TRST_ACT(cable) | PRM_TRST_INACT(cable)); + PRM_SIGNALS (cable) = (PRM_TRST_LVL(cable) == PRM_TRST_ACT(cable)) ? CS_TRST : 0; + return 0; } @@ -270,6 +274,10 @@ wiggler_clock( cable_t *cable, int tms, int tdi, int n ) PRM_UNUSED_BITS(cable) ); cable_wait( cable ); } + + PRM_SIGNALS (cable) &= ~(CS_TDI | CS_TMS); + if (tms) PRM_SIGNALS(cable) |= CS_TMS; + if (tdi) PRM_SIGNALS(cable) |= CS_TDI; } static int @@ -279,24 +287,37 @@ wiggler_get_tdo( cable_t *cable ) PRM_TCK_INACT(cable) | PRM_UNUSED_BITS(cable) ); cable_wait( cable ); + return (parport_get_status( cable->link.port ) & (PRM_TDO_ACT(cable) | PRM_TDO_INACT(cable))) ^ - PRM_TDO_ACT(cable) ? 0 : 1; + PRM_TDO_ACT(cable) ? 0 : 1; } static int -wiggler_set_trst( cable_t *cable, int trst ) +wiggler_set_signal( cable_t *cable, int mask, int val ) { - PRM_TRST_LVL(cable) = trst ? PRM_TRST_ACT(cable) : PRM_TRST_INACT(cable); + int prev_sigs = PRM_SIGNALS(cable); + + mask &= (CS_TMS | CS_TDI | CS_TCK | CS_TRST); // Only these can be modified + + if (mask != 0) + { + int sigs = (prev_sigs & ~mask) | (val & mask); + PRM_TRST_LVL(cable) = ((sigs & CS_TRST) ? PRM_TRST_ACT(cable) : PRM_TRST_INACT(cable)); + int data = PRM_UNUSED_BITS(cable) | PRM_TRST_LVL(cable); + data |= ((sigs & CS_TCK) ? PRM_TCK_ACT(cable) : PRM_TCK_INACT(cable)); + data |= ((sigs & CS_TMS) ? PRM_TMS_ACT(cable) : PRM_TMS_INACT(cable)); + data |= ((sigs & CS_TDI) ? PRM_TDI_ACT(cable) : PRM_TDI_INACT(cable)); + parport_set_data( cable->link.port, data ); + PRM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, PRM_TRST_LVL(cable) | - PRM_UNUSED_BITS(cable) ); - return PRM_TRST_LVL(cable) ^ PRM_TRST_ACT(cable) ? 0 : 1; + return prev_sigs; } static int -wiggler_get_trst( cable_t *cable ) +wiggler_get_signal( cable_t *cable, pod_sigsel_t sig ) { - return PRM_TRST_LVL(cable) ^ PRM_TRST_ACT(cable) ? 0 : 1; + return (PRM_SIGNALS(cable) & sig) ? 1 : 0; } static void @@ -345,8 +366,8 @@ cable_driver_t wiggler_cable_driver = { wiggler_clock, wiggler_get_tdo, generic_transfer, - wiggler_set_trst, - wiggler_get_trst, + wiggler_set_signal, + wiggler_get_signal, generic_flush_one_by_one, wiggler_help }; @@ -363,8 +384,8 @@ cable_driver_t igloo_cable_driver = { wiggler_clock, wiggler_get_tdo, generic_transfer, - wiggler_set_trst, - wiggler_get_trst, + wiggler_set_signal, + wiggler_get_signal, generic_flush_one_by_one, wiggler_help }; diff --git a/jtag/src/tap/cable/wiggler2.c b/jtag/src/tap/cable/wiggler2.c index c7bd06dc..e0a2b330 100644 --- a/jtag/src/tap/cable/wiggler2.c +++ b/jtag/src/tap/cable/wiggler2.c @@ -73,12 +73,15 @@ wiggler2_init( cable_t *cable ) if (parport_open( cable->link.port )) return -1; + // TODO: CPU_RESET bit is set to zero here and can't be changed afterwards + // If CPU_RESET=0 doesn't harm, it means it is an active high signal? - kawk + if ((data = parport_get_data( cable->link.port )) < 0) { - if (parport_set_data( cable->link.port, (0 << TRST) | UNUSED_BITS )) + if (parport_set_data( cable->link.port, (1 << TRST) | UNUSED_BITS )) return -1; - PARAM_TRST(cable) = 1; + PARAM_SIGNALS(cable) = CS_TRST; } else - PARAM_TRST(cable) = (data >> TRST) & 1; + PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0; return 0; } @@ -87,33 +90,57 @@ static void wiggler2_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; for (i = 0; i < n; i++) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); cable_wait( cable ); - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); + parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS ); cable_wait( cable ); } + + PARAM_SIGNALS(cable) &= CS_TRST; + PARAM_SIGNALS(cable) |= CS_TCK; + PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0; + PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0; } static int wiggler2_get_tdo( cable_t *cable ) { - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | UNUSED_BITS ); + int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0; + + parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | UNUSED_BITS ); + PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS); + cable_wait( cable ); + return (parport_get_status( cable->link.port ) >> TDO) & 1; } static int -wiggler2_set_trst( cable_t *cable, int trst ) +wiggler2_set_signal( cable_t *cable, int mask, int val ) { - PARAM_TRST(cable) = trst ? 1 : 0; + int prev_sigs = PARAM_SIGNALS(cable); + + mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified + + if (mask != 0) + { + int data = 0; + int sigs = (prev_sigs & ~mask) | (val & mask); + data |= (sigs & CS_TDI) ? (1 << TDI) : 0; + data |= (sigs & CS_TCK) ? (1 << TCK) : 0; + data |= (sigs & CS_TMS) ? (1 << TMS) : 0; + data |= (sigs & CS_TRST) ? (1 << TRST) : 0; + parport_set_data( cable->link.port, data | UNUSED_BITS ); + PARAM_SIGNALS(cable) = sigs; + } - parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | UNUSED_BITS ); - return PARAM_TRST(cable); + return prev_sigs; } cable_driver_t wiggler2_cable_driver = { @@ -128,8 +155,8 @@ cable_driver_t wiggler2_cable_driver = { wiggler2_clock, wiggler2_get_tdo, generic_transfer, - wiggler2_set_trst, - generic_get_trst, + wiggler2_set_signal, + generic_get_signal, generic_flush_one_by_one, generic_parport_help }; diff --git a/jtag/src/tap/cable/xpc.c b/jtag/src/tap/cable/xpc.c index 1b830098..d0ab8897 100644 --- a/jtag/src/tap/cable/xpc.c +++ b/jtag/src/tap/cable/xpc.c @@ -437,7 +437,7 @@ xpc_get_tdo( cable_t *cable ) /* ---------------------------------------------------------------------- */ static int -xpc_set_trst( cable_t *cable, int trst ) +xpc_set_signal( cable_t *cable, int mask, int val ) { return 1; } @@ -641,8 +641,8 @@ cable_driver_t xpc_int_cable_driver = { xpc_clock, xpc_get_tdo, generic_transfer, - xpc_set_trst, - generic_get_trst, + xpc_set_signal, + generic_get_signal, generic_flush_using_transfer, generic_usbconn_help }; @@ -667,8 +667,8 @@ cable_driver_t xpc_ext_cable_driver = { xpc_ext_clock, xpc_ext_get_tdo, xpc_ext_transfer, - xpc_set_trst, - generic_get_trst, + xpc_set_signal, + generic_get_signal, generic_flush_using_transfer, generic_usbconn_help }; diff --git a/jtag/src/tap/chain.c b/jtag/src/tap/chain.c index ff61b278..268550aa 100644 --- a/jtag/src/tap/chain.c +++ b/jtag/src/tap/chain.c @@ -105,8 +105,8 @@ chain_defer_clock( chain_t *chain, int tms, int tdi, int n ) int chain_set_trst( chain_t *chain, int trst ) { - int old_trst = cable_get_trst( chain->cable ); - trst = cable_set_trst( chain->cable, trst ); + int old_trst = cable_set_signal( chain->cable, CS_TRST, trst ? CS_TRST : 0 ); + old_trst = (old_trst & CS_TRST) ? 1 : 0; tap_state_set_trst( chain, old_trst, trst ); return trst; } @@ -114,7 +114,23 @@ chain_set_trst( chain_t *chain, int trst ) int chain_get_trst( chain_t *chain ) { - return cable_get_trst( chain->cable ); + return (cable_get_signal( chain->cable, CS_TRST )); +} + +int +chain_set_pod_signal( chain_t *chain, int mask, int val ) +{ + int old_val = cable_set_signal( chain->cable, mask, val ); + int old_trst = (old_trst & CS_TRST) ? 1 : 0; + int new_trst = (val & mask & CS_TRST) ? 1 : 0; + tap_state_set_trst( chain, old_trst, new_trst ); + return old_val; +} + +int +chain_get_pod_signal( chain_t *chain, pod_sigsel_t sig ) +{ + return (cable_get_signal( chain->cable, sig )); } void