diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 16f1a756..480c0027 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,15 @@ +2003-01-05 Marcel Telka + + * include/register.h (register_inc, register_dec, register_shift_rigth, + register_shift_left): Added new functions. + * src/tap/register.c (register_inc, register_dec, register_shift_rigth, + register_shift_left): Ditto. + * src/Makefile.am: Added discovery.c file. + * src/discovery.c: Added new file with discovery() implementation. + * src/help.c (help): Added help for 'discovery' command. + * src/jtag.c (main): Added 'discovery' command. + * src/tap/tap.c (write_command): Removed unused function. + 2002-12-16 Marcel Telka * data/Makefile.am: Renamed intel/pxa250/pxa260 to intel/pxa250/pxa250c0. diff --git a/jtag/NEWS b/jtag/NEWS index ff2f3d6c..47951560 100644 --- a/jtag/NEWS +++ b/jtag/NEWS @@ -2,6 +2,7 @@ Changes since 0.1: * Completed JTAG declarations for Xilinx XCR3128XL-CS144. * Fixed crash if flash memory is not detected. + * Added new 'discovery' command for discovery unknown JTAG chains. jtag-0.1 (2002-11-25): diff --git a/jtag/include/register.h b/jtag/include/register.h index 11d3a0b9..8594c117 100644 --- a/jtag/include/register.h +++ b/jtag/include/register.h @@ -1,7 +1,7 @@ /* * $Id$ * - * Copyright (C) 2002 ETC s.r.o. + * Copyright (C) 2002, 2003 ETC s.r.o. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * - * Written by Marcel Telka , 2002. + * Written by Marcel Telka , 2002, 2003. * */ @@ -39,5 +39,9 @@ const char *register_get_string( const tap_register *tr ); tap_register *register_init( tap_register *tr, const char *value ); int register_compare( const tap_register *tr, const tap_register *tr2 ); int register_match( const tap_register *tr, const char *expr ); +tap_register *register_inc( tap_register *tr ); +tap_register *register_dec( tap_register *tr ); +tap_register *register_shift_right( tap_register *tr, int shift ); +tap_register *register_shift_left( tap_register *tr, int shift ); #endif /* REGISTER_H */ diff --git a/jtag/src/Makefile.am b/jtag/src/Makefile.am index 8e8901da..8977e39c 100644 --- a/jtag/src/Makefile.am +++ b/jtag/src/Makefile.am @@ -27,7 +27,18 @@ SUBDIRS = \ bin_PROGRAMS = jtag -jtag_SOURCES = jtag.c detect.c readmem.c detect.h bus.h pxa250.c sa1110.c cfi.c flash.c help.c +jtag_SOURCES = \ + jtag.c \ + detect.c \ + discovery.c \ + readmem.c \ + detect.h \ + bus.h \ + pxa250.c \ + sa1110.c \ + cfi.c \ + flash.c \ + help.c jtag_DEPENDENCIES = tap/libtap.a part/libpart.a diff --git a/jtag/src/discovery.c b/jtag/src/discovery.c new file mode 100644 index 00000000..aeaa5022 --- /dev/null +++ b/jtag/src/discovery.c @@ -0,0 +1,207 @@ +/* + * $Id$ + * + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "ctrl.h" +#include "tap.h" + +#define DETECT_PATTERN_SIZE 8 +#define MAX_REGISTER_LENGTH 1024 +#define TEST_COUNT 5 +#define TEST_THRESHOLD 100 /* in % */ + +static int +detect_register_size( FILE *f ) +{ + int len; + tap_register *rz; + tap_register *rout; + tap_register *rpat; + + for (len = 1; len < MAX_REGISTER_LENGTH; len++) { + int p; + int ok = 0; + + fprintf( f, "\tTesting register length: %d\n", len ); + + rz = register_fill( register_alloc( len ), 0 ); + rout = register_alloc( DETECT_PATTERN_SIZE + len ); + rpat = register_inc( register_fill( register_alloc( DETECT_PATTERN_SIZE + len ), 0 ) ); + + for (p = 1; p < (1 << DETECT_PATTERN_SIZE); p++) { + int i; + const char *s; + ok = 0; + + s = register_get_string( rpat ); + while (*s) + s++; + fprintf( f, "\t\tPattern: %s, ", s - DETECT_PATTERN_SIZE ); + + for (i = 0; i < TEST_COUNT; i++) { + tap_shift_register( rz, NULL, 0 ); + tap_shift_register( rpat, rout, 0 ); + + register_shift_right( rout, len ); + + if (register_compare( rpat, rout ) == 0) + ok++; + } + fprintf( f, "%d %%\n", 100 * ok / TEST_COUNT ); + if (100 * ok / TEST_COUNT < TEST_THRESHOLD) { + ok = 0; + break; + } + + register_inc( rpat ); + } + + register_free( rz ); + register_free( rout ); + register_free( rpat ); + + if (ok) + return len; + } + + return -1; +} + +static void +jtag_reset( void ) +{ + tap_set_trst( 0 ); + sleep( 1 ); + tap_set_trst( 1 ); + sleep( 1 ); + + tap_reset(); +} + +#define MAX_CHAIN_LENGTH 128 + +void +discovery( const char *filename ) +{ + int i; + int irlen; + tap_register *ir; + tap_register *irz; + FILE *f = NULL; + + tap_register *id = register_alloc( 32 ); + tap_register *zeros = register_fill( register_alloc( 32 ), 0 ); + tap_register *ones = register_fill( register_alloc( 32 ), 1 ); + + if (id && zeros && ones) { + f = fopen( filename, "w" ); + if (!f) + printf( "Error: Unable to create file '%s'.\n", filename ); + } else + printf( "Error: Out of memory!\n" ); + + if (!id || !zeros || !ones || !f) { + register_free( id ); + register_free( zeros ); + register_free( ones ); + return; + } + + printf( "Detecting JTAG chain length:\n" ); + fprintf( f, "Detecting JTAG chain length:\n" ); + + jtag_reset(); + + tap_capture_dr(); + for (i = 0; i < MAX_CHAIN_LENGTH; i++) { + tap_shift_register( zeros, id, 0 ); + if (!register_compare( id, zeros )) + break; /* end of chain */ + + if (!register_compare( ones, id )) { + printf( "bad JTAG connection (TDO is 1)\n" ); + fprintf( f, "bad JTAG connection (TDO is 1)\n" ); + return; /* FIXME: memory leak */ + } + + printf( "ID[%d]: %s\n", i, register_get_string( id ) ); + fprintf( f, "ID[%d]: %s\n", i, register_get_string( id ) ); + } + + if (i == MAX_CHAIN_LENGTH) { + printf( "Warning: Maximum internal JTAG chain length exceeded!\n" ); + fprintf( f, "Warning: Maximum internal JTAG chain length exceeded!\n" ); + } else { + printf( "JTAG chain length is %d\n", i ); + fprintf( f, "JTAG chain length is %d\n", i ); + } + + /* detecting IR size */ + jtag_reset(); + + printf( "Detecting IR size...\n" ); + fprintf( f, "Detecting IR size:\n" ); + + tap_capture_ir(); + irlen = detect_register_size( f ); + + printf( "IR length is %d\n\n", irlen ); + fprintf( f, "IR length is %d\n\n", irlen ); + + ir = register_fill( register_alloc( irlen ), 0 ); + irz = register_duplicate( ir ); + /* TODO: test for out of memory */ + for (;;) { + int rs; + + jtag_reset(); + + tap_capture_ir(); + tap_shift_register( ir, NULL, 1 ); + + printf( "Detecting DR size for IR %s ...\n", register_get_string( ir ) ); + fprintf( f, "Detecting DR size for IR %s:\n", register_get_string( ir ) ); + + tap_capture_dr(); + rs = detect_register_size( f ); + + printf( "DR length for IR %s is %d\n\n", register_get_string( ir ), rs ); + fprintf( f, "DR length for IR %s is %d\n\n", register_get_string( ir ), rs ); + + register_inc( ir ); + if (register_compare( ir, irz ) == 0) + break; + } + register_free( ir ); + register_free( irz ); + + fclose( f ); +} diff --git a/jtag/src/help.c b/jtag/src/help.c index f39dedff..3a102190 100644 --- a/jtag/src/help.c +++ b/jtag/src/help.c @@ -1,7 +1,7 @@ /* * $Id$ * - * Copyright (C) 2002 ETC s.r.o. + * Copyright (C) 2002, 2003 ETC s.r.o. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * - * Written by Marcel Telka , 2002. + * Written by Marcel Telka , 2002, 2003. * */ @@ -39,6 +39,7 @@ help( const char *cmd ) "quit exit from %s\n" "help display this help\n" "detect detect parts on the JTAG chain\n" + "discovery discovery unknown parts in the JTAG chain\n" "print display JTAG chain list/status\n" "instruction change active instruction for a part\n" "shift shift data/instruction register through JTAG chain\n" @@ -68,6 +69,21 @@ help( const char *cmd ) "Output from this command is a list of the detected parts.\n" "If no parts are detected other commands may not work properly.\n" ); + else if (strcmp( cmd, "discovery" ) == 0) + printf( + "Usage: discovery FILENAME\n" + "Discovery unknown parts in the JTAG chain.\n" + "\n" + "Detail output (report) is directed to the FILENAME.\n" + "'discovery' attempt to detect these parameters of an unknown JTAG\n" + "chain:\n" + " 1. JTAG chain size (number of parts in the chain)\n" + " 2. IR (instruction register) length\n" + " 3. DR (data register) length for all possible instructions\n" + "\n" + "Warning: This may be dangerous for some parts (especially, if the\n" + "part doesn't have TRST signal).\n" + ); else if (strcmp( cmd, "print" ) == 0) printf( "Usage: print\n" diff --git a/jtag/src/jtag.c b/jtag/src/jtag.c index e5c8be66..fb65dc8b 100644 --- a/jtag/src/jtag.c +++ b/jtag/src/jtag.c @@ -1,7 +1,7 @@ /* * $Id$ * - * Copyright (C) 2002 ETC s.r.o. + * Copyright (C) 2002, 2003 ETC s.r.o. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * - * Written by Marcel Telka , 2002. + * Written by Marcel Telka , 2002, 2003. * */ @@ -53,6 +53,8 @@ void flashmsbin( parts *ps, FILE *f ); void help( const char *cmd ); +void discovery( const char *filename ); + int main( void ) { @@ -104,6 +106,20 @@ main( void ) continue; } + if (strcmp( t, "discovery" ) == 0) { + t = get_token( NULL ); + if (!t) { + printf( "discovery: missing filename\n" ); + continue; + } + if (get_token( NULL )) { + printf( "syntax error!\n" ); + continue; + } + discovery( t ); + continue; + } + if (strcmp( t, "detect" ) == 0) { t = get_token( NULL ); if (ps) diff --git a/jtag/src/tap/register.c b/jtag/src/tap/register.c index 3ea0bd00..28c1db97 100644 --- a/jtag/src/tap/register.c +++ b/jtag/src/tap/register.c @@ -1,7 +1,7 @@ /* * $Id$ * - * Copyright (C) 2002 ETC s.r.o. + * Copyright (C) 2002, 2003 ETC s.r.o. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * - * Written by Marcel Telka , 2002. + * Written by Marcel Telka , 2002, 2003. * */ @@ -162,3 +162,81 @@ register_match( const tap_register *tr, const char *expr ) return 1; } + +tap_register * +register_inc( tap_register *tr ) +{ + int i; + + if (!tr) + return NULL; + + for (i = 0; i < tr->len; i++) { + tr->data[i] ^= 1; + + if (tr->data[i] == 1) + break; + } + + return tr; +} + +tap_register * +register_dec( tap_register *tr ) +{ + int i; + + if (!tr) + return NULL; + + for (i = 0; i < tr->len; i++) { + tr->data[i] ^= 1; + + if (tr->data[i] == 0) + break; + } + + return tr; +} + +tap_register * +register_shift_right( tap_register *tr, int shift ) +{ + int i; + + if (!tr) + return NULL; + + if (shift < 1) + return tr; + + for (i = 0; i < tr->len; i++) { + if (i + shift < tr->len) + tr->data[i] = tr->data[i + shift]; + else + tr->data[i] = 0; + } + + return tr; +} + +tap_register * +register_shift_left( tap_register *tr, int shift ) +{ + int i; + + if (!tr) + return NULL; + + if (shift < 1) + return tr; + + for (i = tr->len - 1; i >= 0; i--) { + if (i - shift >= 0) + tr->data[i] = tr->data[i - shift]; + else + tr->data[i] = 0; + } + + return tr; +} diff --git a/jtag/src/tap/tap.c b/jtag/src/tap/tap.c index 20074636..df60dc57 100644 --- a/jtag/src/tap/tap.c +++ b/jtag/src/tap/tap.c @@ -84,10 +84,3 @@ tap_capture_ir( void ) tap_clock( 1, 0 ); /* Select-IR-Scan */ tap_clock( 0, 0 ); /* Capture-IR */ } - -void -write_command( const tap_register *c, tap_register *cout, int len ) -{ - tap_capture_ir(); - tap_shift_register( c, cout, 1 ); -}