diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 448ae9a2..a59987ad 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -3,7 +3,11 @@ * acinclude.m4, configure.ac: Use local copy of AC_PROG_SED macro (renamed to ACI_PROG_SED) maintain compatibility with older autoconf; fixes [1890192] - autogen.sh fails on AC_PROG_SED - + * include/cable.h, src/tap/cable/usbblaster.c, src/tap/cable/generic.c, + src/tap/cable/generic.h, src/tap/cable/ft2232.c, src/tap/cable.c, + doc/UrJTAG.txt: Extended cable_flush() to take one extra argument + regarding the amount of items to flush (see UrJTAG.txt for doc) + 2008-02-09 Arnim Laeuger * src/tap/cable/ft2232.c (ft2232_transfer_schedule): ensure max number of bytes for diff --git a/jtag/doc/UrJTAG.txt b/jtag/doc/UrJTAG.txt index 466a4e1c..7d90e55e 100644 --- a/jtag/doc/UrJTAG.txt +++ b/jtag/doc/UrJTAG.txt @@ -254,11 +254,11 @@ least the following are supported: NOTE: Not all chips are supported in every possible configuration, there may be untested combinations of chip type, bus width, ... - * Intel 28FxxxJ3A (28F320J3A, 28F640J3A, 28F128J3A) - * Intel 28FxxxK3 (28F640K3, 28F128K3, 28F256K3) - * Intel 28FxxxK18 (28F640K18, 28F128K18, 28F256K18) - * AMD Am29LV64xD (Am29LV640D, Am29LV641D, Am29LV642D) - * AMD Am29xx040B (Am29F040B, Am29LV040B) + * Intel 28FxxxJ3A (28F320J3A, 28F640J3A, 28F128J3A) + * Intel 28FxxxK3 (28F640K3, 28F128K3, 28F256K3) + * Intel 28FxxxK18 (28F640K18, 28F128K18, 28F256K18) + * AMD Am29LV64xD (Am29LV640D, Am29LV641D, Am29LV642D) + * AMD Am29xx040B (Am29F040B, Am29LV040B) //------------------------------------------------------------------------ @@ -905,9 +905,9 @@ Currently the API provides five different functions for performing operations at the JTAG interface on the low level signal level (using the four signals TMS, TCK, TDI, and TDO). - * clock() takes values for TMS and TDI output as its parameters, ensures that actual cable signals are set accordingly, and does a 0-1 transition on TCK. + * clock(tms,tdi,n) takes values for TMS and TDI output as its parameters, ensures that actual cable signals are set accordingly, and does a 0-1 transition on TCK (n times) * get_tdo() returns the current value at the TDO input. - * set_trst() sets the TRST signal and returns the current value. + * set_trst(x) sets the TRST signal and returns the current value. * get_trst() returns the current value of the TRST signal. For many JTAG adapters, there's almost no delay when doing alternating clock() @@ -924,6 +924,8 @@ which would limit the transfer rate to 1 kHz. One way to workaround this is to transmit bits compacted into bytes and chunks of bytes, which is possible with the transfer() function. + * transfer(in, out) + The transfer() function does a series of TCK pulses, with data for TDI read as bytes from memory. The bytes are automatically serialized. TMS is set to zero during transfer()s. Optionally, prior to each bit shifted out to the interface, @@ -969,7 +971,30 @@ second clock(), the sequence can be optimized into the following sequence (if 4. get_tdo_late() 5. get_tdo_late() -The next section explains the queueing mechanism and its limits in detail. +The next sections explain the queueing mechanism and its limits in detail. + +===== When flushing occurs ====== + +The cable_flush() function is used to flush the queue towards the cable. It +takes one additional argument, "how_much", which may be one of + + * OPTIONALLY: The cable driver may flush if it's reasonable (e.g. if the + queue has been filled so that some buffer limit for the cable interface + is reached). It would be wise to flush early to keep the queue small, if + there is no point in queueing up more items because the transfer to the + cable would have to be split into smaller chunks anyway. This is used by + UrJTAG immediately after adding items to the queue. + + * TO_OUTPUT: The cable driver should at least flush as much so that one + output becomes available in the output queue. If there's already something + in the output queue, this should be interpreted similar to OPTIONALLY. This + is used by UrJTAG immediately before it wants to use that output. + + * COMPLETELY: The cable driver has to flush the queue completely. This is + used by UrJTAG immediately before actions that circumvent the queueing + such as calls to the legacy clock/get_tdo functions. It could also be + used by application code to ensure that some action is actually done in + time. ===== JTAG activity queueing ===== diff --git a/jtag/include/cable.h b/jtag/include/cable.h index 32fc8594..f6251444 100644 --- a/jtag/include/cable.h +++ b/jtag/include/cable.h @@ -35,6 +35,14 @@ typedef struct cable_t cable_t; typedef struct cable_driver_t cable_driver_t; +typedef enum +{ + OPTIONALLY, + TO_OUTPUT, + COMPLETELY +} +cable_flush_amount_t; + struct cable_driver_t { const char *name; const char *description; @@ -48,7 +56,7 @@ struct cable_driver_t { int (*transfer)( cable_t *, int, char *, char * ); int (*set_trst)( cable_t *, int ); int (*get_trst)( cable_t * ); - void (*flush)( cable_t * ); + void (*flush)( cable_t *, cable_flush_amount_t ); void (*help)( const char * ); }; @@ -110,7 +118,7 @@ struct cable_t { void cable_free( cable_t *cable ); int cable_init( cable_t *cable ); void cable_done( cable_t *cable ); -void cable_flush( cable_t *cable ); +void cable_flush( cable_t *cable, cable_flush_amount_t ); void cable_clock( cable_t *cable, int tms, int tdi, int n ); int cable_defer_clock( cable_t *cable, int tms, int tdi, int n ); int cable_get_tdo( cable_t *cable ); diff --git a/jtag/src/tap/cable.c b/jtag/src/tap/cable.c index d13d92a0..e26804cc 100644 --- a/jtag/src/tap/cable.c +++ b/jtag/src/tap/cable.c @@ -138,15 +138,15 @@ cable_init( cable_t *cable ) } void -cable_flush ( cable_t *cable ) +cable_flush ( cable_t *cable, cable_flush_amount_t how_much ) { - cable->driver->flush( cable ); + cable->driver->flush( cable, how_much ); } void cable_done( cable_t *cable ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); if( cable->todo.data != NULL) { free( cable->todo.data ); @@ -296,7 +296,7 @@ cable_purge_queue( cable_queue_info_t *q, int io ) void cable_clock( cable_t *cable, int tms, int tdi, int n ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); cable->driver->clock( cable, tms, tdi, n ); } @@ -309,13 +309,14 @@ cable_defer_clock ( cable_t *cable, int tms, int tdi, int n ) cable->todo.data[i].arg.clock.tms = tms; cable->todo.data[i].arg.clock.tdi = tdi; cable->todo.data[i].arg.clock.n = n; + cable_flush( cable, OPTIONALLY ); return 0; /* success */ } int cable_get_tdo( cable_t *cable ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); return cable->driver->get_tdo( cable ); } @@ -323,7 +324,7 @@ int cable_get_tdo_late( cable_t *cable ) { int i; - cable_flush( cable ); + cable_flush( cable, TO_OUTPUT ); i = cable_get_queue_item( cable, &(cable->done) ); if( i >= 0 ) { @@ -347,13 +348,14 @@ cable_defer_get_tdo( cable_t *cable ) int i = cable_add_queue_item( cable, &(cable->todo) ); if( i < 0 ) return 1; /* report failure */ cable->todo.data[i].action = CABLE_GET_TDO; + cable_flush( cable, OPTIONALLY ); return 0; /* success */ } int cable_set_trst( cable_t *cable, int trst ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); return cable->driver->set_trst( cable, trst ); } @@ -364,13 +366,14 @@ cable_defer_set_trst( cable_t *cable, int trst ) if( i < 0 ) return 1; /* report failure */ cable->todo.data[i].action = CABLE_SET_TRST; cable->todo.data[i].arg.value.trst = trst; + cable_flush( cable, OPTIONALLY ); return 0; /* success */ } int cable_get_trst( cable_t *cable ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); return cable->driver->get_trst( cable ); } @@ -378,7 +381,7 @@ int cable_get_trst_late( cable_t *cable ) { int i; - cable_flush( cable ); + cable_flush( cable, TO_OUTPUT ); i = cable_get_queue_item( cable, &(cable->done) ); if( i >= 0 ) { @@ -402,13 +405,14 @@ cable_defer_get_trst( cable_t *cable ) 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_flush( cable, OPTIONALLY ); return 0; /* success */ } int cable_transfer( cable_t *cable, int len, char *in, char *out ) { - cable_flush( cable ); + cable_flush( cable, COMPLETELY ); return cable->driver->transfer( cable, len, in, out ); } @@ -416,7 +420,7 @@ int cable_transfer_late( cable_t *cable, char *out ) { int i; - cable_flush( cable ); + cable_flush( cable, TO_OUTPUT ); i = cable_get_queue_item( cable, &(cable->done) ); if( i >= 0 && cable->done.data[i].action == CABLE_TRANSFER) @@ -479,6 +483,7 @@ cable_defer_transfer( cable_t *cable, int len, char *in, char *out ) if(in) memcpy(ibuf, in, len); cable->todo.data[i].arg.transfer.in = ibuf; cable->todo.data[i].arg.transfer.out = obuf; + cable_flush( cable, OPTIONALLY ); return 0; /* success */ } diff --git a/jtag/src/tap/cable/ft2232.c b/jtag/src/tap/cable/ft2232.c index f9a3f625..0ddb4bca 100644 --- a/jtag/src/tap/cable/ft2232.c +++ b/jtag/src/tap/cable/ft2232.c @@ -676,7 +676,7 @@ ft2232_transfer( cable_t *cable, int len, char *in, char *out ) static void -ft2232_flush( cable_t *cable ) +ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) { params_t *params = (params_t *)cable->params; diff --git a/jtag/src/tap/cable/generic.c b/jtag/src/tap/cable/generic.c index ca5427f9..ef70e54c 100644 --- a/jtag/src/tap/cable/generic.c +++ b/jtag/src/tap/cable/generic.c @@ -225,13 +225,13 @@ do_one_queued_action( cable_t *cable ) } void -generic_flush_one_by_one( cable_t *cable ) +generic_flush_one_by_one( cable_t *cable, cable_flush_amount_t how_much ) { while( do_one_queued_action( cable ) ); } void -generic_flush_using_transfer( cable_t *cable ) +generic_flush_using_transfer( cable_t *cable, cable_flush_amount_t how_much ) { int i, j, n; char *in, *out; @@ -308,7 +308,7 @@ generic_flush_using_transfer( cable_t *cable ) { if(in != NULL) free(in); if(out != NULL) free(out); - generic_flush_one_by_one( cable ); + generic_flush_one_by_one( cable, how_much ); break; }; diff --git a/jtag/src/tap/cable/generic.h b/jtag/src/tap/cable/generic.h index 44e4d227..55935299 100644 --- a/jtag/src/tap/cable/generic.h +++ b/jtag/src/tap/cable/generic.h @@ -42,8 +42,8 @@ void generic_cable_free( cable_t *cable ); void generic_done( cable_t *cable ); int generic_transfer( cable_t *cable, int len, char *in, char *out ); int generic_get_trst( cable_t *cable ); -void generic_flush_one_by_one( cable_t *cable ); -void generic_flush_using_transfer( cable_t *cable ); +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 ); void generic_lptcable_help( const char *name ); #endif /* GENERIC_H */ diff --git a/jtag/src/tap/cable/usbblaster.c b/jtag/src/tap/cable/usbblaster.c index d865d7ee..e23c18ce 100644 --- a/jtag/src/tap/cable/usbblaster.c +++ b/jtag/src/tap/cable/usbblaster.c @@ -187,7 +187,7 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out ) } static void -usbblaster_flush( cable_t *cable ) +usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) { while (cable->todo.num_items > 0) {