Move the JTAG cable interface API implementation
- Cloned the src/jtag/jtag.c file to src/jtag/interface.c. - For each for of those files, deleted the contents of the other. - Add new source file to automake input. git-svn-id: svn://svn.berlios.de/openocd/trunk@2012 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
parent
f7d011a955
commit
4ecf2c7dd8
|
@ -117,6 +117,7 @@ endif
|
||||||
|
|
||||||
libjtag_la_SOURCES = \
|
libjtag_la_SOURCES = \
|
||||||
jtag.c \
|
jtag.c \
|
||||||
|
interface.c \
|
||||||
$(DRIVERFILES) \
|
$(DRIVERFILES) \
|
||||||
$(BITBANGFILES) \
|
$(BITBANGFILES) \
|
||||||
$(PARPORTFILES) \
|
$(PARPORTFILES) \
|
||||||
|
|
|
@ -0,0 +1,465 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2005 by Dominic Rath *
|
||||||
|
* Dominic.Rath@gmx.de *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||||
|
* oyvind.harboe@zylin.com *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2009 SoftPLC Corporation *
|
||||||
|
* http://softplc.com *
|
||||||
|
* dick@softplc.com *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2009 Zachary T Welch *
|
||||||
|
* zw@superlucidity.net *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "jtag.h"
|
||||||
|
#include "interface.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see tap_set_state() and tap_get_state() accessors.
|
||||||
|
* Actual name is not important since accessors hide it.
|
||||||
|
*/
|
||||||
|
static tap_state_t state_follower = TAP_RESET;
|
||||||
|
|
||||||
|
void tap_set_state_impl( tap_state_t new_state )
|
||||||
|
{
|
||||||
|
/* this is the state we think the TAPs are in now, was cur_state */
|
||||||
|
state_follower = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_state_t tap_get_state()
|
||||||
|
{
|
||||||
|
return state_follower;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see tap_set_end_state() and tap_get_end_state() accessors.
|
||||||
|
* Actual name is not important because accessors hide it.
|
||||||
|
*/
|
||||||
|
static tap_state_t end_state_follower = TAP_RESET;
|
||||||
|
|
||||||
|
void tap_set_end_state( tap_state_t new_end_state )
|
||||||
|
{
|
||||||
|
/* this is the state we think the TAPs will be in at completion of the
|
||||||
|
current TAP operation, was end_state
|
||||||
|
*/
|
||||||
|
end_state_follower = new_end_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_state_t tap_get_end_state()
|
||||||
|
{
|
||||||
|
return end_state_follower;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int tap_move_ndx( tap_state_t astate )
|
||||||
|
{
|
||||||
|
/* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */
|
||||||
|
|
||||||
|
int ndx;
|
||||||
|
|
||||||
|
switch( astate )
|
||||||
|
{
|
||||||
|
case TAP_RESET: ndx = 0; break;
|
||||||
|
case TAP_DRSHIFT: ndx = 2; break;
|
||||||
|
case TAP_DRPAUSE: ndx = 3; break;
|
||||||
|
case TAP_IDLE: ndx = 1; break;
|
||||||
|
case TAP_IRSHIFT: ndx = 4; break;
|
||||||
|
case TAP_IRPAUSE: ndx = 5; break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR( "fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate) );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ndx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* tap_move[i][j]: tap movement command to go from state i to state j
|
||||||
|
* 0: Test-Logic-Reset
|
||||||
|
* 1: Run-Test/Idle
|
||||||
|
* 2: Shift-DR
|
||||||
|
* 3: Pause-DR
|
||||||
|
* 4: Shift-IR
|
||||||
|
* 5: Pause-IR
|
||||||
|
*
|
||||||
|
* DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
|
||||||
|
*/
|
||||||
|
struct tms_sequences
|
||||||
|
{
|
||||||
|
u8 bits;
|
||||||
|
u8 bit_count;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These macros allow us to specify TMS state transitions by bits rather than hex bytes.
|
||||||
|
* Read the bits from LSBit first to MSBit last (right-to-left).
|
||||||
|
*/
|
||||||
|
#define HEX__(n) 0x##n##LU
|
||||||
|
|
||||||
|
#define B8__(x) \
|
||||||
|
(((x) & 0x0000000FLU)?(1<<0):0) \
|
||||||
|
+(((x) & 0x000000F0LU)?(1<<1):0) \
|
||||||
|
+(((x) & 0x00000F00LU)?(1<<2):0) \
|
||||||
|
+(((x) & 0x0000F000LU)?(1<<3):0) \
|
||||||
|
+(((x) & 0x000F0000LU)?(1<<4):0) \
|
||||||
|
+(((x) & 0x00F00000LU)?(1<<5):0) \
|
||||||
|
+(((x) & 0x0F000000LU)?(1<<6):0) \
|
||||||
|
+(((x) & 0xF0000000LU)?(1<<7):0)
|
||||||
|
|
||||||
|
#define B8(bits,count) { ((u8)B8__(HEX__(bits))), (count) }
|
||||||
|
|
||||||
|
static const struct tms_sequences old_tms_seqs[6][6] = /* [from_state_ndx][to_state_ndx] */
|
||||||
|
{
|
||||||
|
/* value clocked to TMS to move from one of six stable states to another.
|
||||||
|
* N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
|
||||||
|
* N.B. These values are tightly bound to the table in tap_get_tms_path_len().
|
||||||
|
* N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
|
||||||
|
* These extra ones cause no TAP state problem, because we go into reset and stay in reset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* to state: */
|
||||||
|
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
||||||
|
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
||||||
|
{ B8(1111111,7), B8(0000000,7), B8(0100101,7), B8(0000101,7), B8(0101011,7), B8(0001011,7) }, /* IDLE */
|
||||||
|
{ B8(1111111,7), B8(0110001,7), B8(0000000,7), B8(0000001,7), B8(0001111,7), B8(0101111,7) }, /* DRSHIFT */
|
||||||
|
{ B8(1111111,7), B8(0110000,7), B8(0100000,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* DRPAUSE */
|
||||||
|
{ B8(1111111,7), B8(0110001,7), B8(0000111,7), B8(0010111,7), B8(0000000,7), B8(0000001,7) }, /* IRSHIFT */
|
||||||
|
{ B8(1111111,7), B8(0110000,7), B8(0011100,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* IRPAUSE */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const struct tms_sequences short_tms_seqs[6][6] = /* [from_state_ndx][to_state_ndx] */
|
||||||
|
{
|
||||||
|
/* this is the table submitted by Jeff Williams on 3/30/2009 with this comment:
|
||||||
|
|
||||||
|
OK, I added Peter's version of the state table, and it works OK for
|
||||||
|
me on MC1322x. I've recreated the jlink portion of patch with this
|
||||||
|
new state table. His changes to my state table are pretty minor in
|
||||||
|
terms of total transitions, but Peter feels that his version fixes
|
||||||
|
some long-standing problems.
|
||||||
|
Jeff
|
||||||
|
|
||||||
|
I added the bit count into the table, reduced RESET column to 7 bits from 8.
|
||||||
|
Dick
|
||||||
|
|
||||||
|
state specific comments:
|
||||||
|
------------------------
|
||||||
|
*->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to
|
||||||
|
work better on ARM9 with ft2232 driver. (Dick)
|
||||||
|
|
||||||
|
RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
||||||
|
needed on ARM9 with ft2232 driver. (Dick)
|
||||||
|
|
||||||
|
RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
||||||
|
needed on ARM9 with ft2232 driver. (Dick)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* to state: */
|
||||||
|
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
||||||
|
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
||||||
|
{ B8(1111111,7), B8(0000000,7), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */
|
||||||
|
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */
|
||||||
|
{ B8(1111111,7), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */
|
||||||
|
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */
|
||||||
|
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const struct tms_sequences tms_table[6][6];
|
||||||
|
|
||||||
|
static tms_table *tms_seqs=&short_tms_seqs;
|
||||||
|
|
||||||
|
int tap_get_tms_path( tap_state_t from, tap_state_t to )
|
||||||
|
{
|
||||||
|
return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int tap_get_tms_path_len( tap_state_t from, tap_state_t to )
|
||||||
|
{
|
||||||
|
return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool tap_is_state_stable(tap_state_t astate)
|
||||||
|
{
|
||||||
|
bool is_stable;
|
||||||
|
|
||||||
|
/* A switch() is used because it is symbol dependent
|
||||||
|
(not value dependent like an array), and can also check bounds.
|
||||||
|
*/
|
||||||
|
switch( astate )
|
||||||
|
{
|
||||||
|
case TAP_RESET:
|
||||||
|
case TAP_IDLE:
|
||||||
|
case TAP_DRSHIFT:
|
||||||
|
case TAP_DRPAUSE:
|
||||||
|
case TAP_IRSHIFT:
|
||||||
|
case TAP_IRPAUSE:
|
||||||
|
is_stable = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
is_stable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_stable;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
|
||||||
|
{
|
||||||
|
tap_state_t new_state;
|
||||||
|
|
||||||
|
/* A switch is used because it is symbol dependent and not value dependent
|
||||||
|
like an array. Also it can check for out of range conditions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tms)
|
||||||
|
{
|
||||||
|
switch (cur_state)
|
||||||
|
{
|
||||||
|
case TAP_RESET:
|
||||||
|
new_state = cur_state;
|
||||||
|
break;
|
||||||
|
case TAP_IDLE:
|
||||||
|
case TAP_DRUPDATE:
|
||||||
|
case TAP_IRUPDATE:
|
||||||
|
new_state = TAP_DRSELECT;
|
||||||
|
break;
|
||||||
|
case TAP_DRSELECT:
|
||||||
|
new_state = TAP_IRSELECT;
|
||||||
|
break;
|
||||||
|
case TAP_DRCAPTURE:
|
||||||
|
case TAP_DRSHIFT:
|
||||||
|
new_state = TAP_DREXIT1;
|
||||||
|
break;
|
||||||
|
case TAP_DREXIT1:
|
||||||
|
case TAP_DREXIT2:
|
||||||
|
new_state = TAP_DRUPDATE;
|
||||||
|
break;
|
||||||
|
case TAP_DRPAUSE:
|
||||||
|
new_state = TAP_DREXIT2;
|
||||||
|
break;
|
||||||
|
case TAP_IRSELECT:
|
||||||
|
new_state = TAP_RESET;
|
||||||
|
break;
|
||||||
|
case TAP_IRCAPTURE:
|
||||||
|
case TAP_IRSHIFT:
|
||||||
|
new_state = TAP_IREXIT1;
|
||||||
|
break;
|
||||||
|
case TAP_IREXIT1:
|
||||||
|
case TAP_IREXIT2:
|
||||||
|
new_state = TAP_IRUPDATE;
|
||||||
|
break;
|
||||||
|
case TAP_IRPAUSE:
|
||||||
|
new_state = TAP_IREXIT2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (cur_state)
|
||||||
|
{
|
||||||
|
case TAP_RESET:
|
||||||
|
case TAP_IDLE:
|
||||||
|
case TAP_DRUPDATE:
|
||||||
|
case TAP_IRUPDATE:
|
||||||
|
new_state = TAP_IDLE;
|
||||||
|
break;
|
||||||
|
case TAP_DRSELECT:
|
||||||
|
new_state = TAP_DRCAPTURE;
|
||||||
|
break;
|
||||||
|
case TAP_DRCAPTURE:
|
||||||
|
case TAP_DRSHIFT:
|
||||||
|
case TAP_DREXIT2:
|
||||||
|
new_state = TAP_DRSHIFT;
|
||||||
|
break;
|
||||||
|
case TAP_DREXIT1:
|
||||||
|
case TAP_DRPAUSE:
|
||||||
|
new_state = TAP_DRPAUSE;
|
||||||
|
break;
|
||||||
|
case TAP_IRSELECT:
|
||||||
|
new_state = TAP_IRCAPTURE;
|
||||||
|
break;
|
||||||
|
case TAP_IRCAPTURE:
|
||||||
|
case TAP_IRSHIFT:
|
||||||
|
case TAP_IREXIT2:
|
||||||
|
new_state = TAP_IRSHIFT;
|
||||||
|
break;
|
||||||
|
case TAP_IREXIT1:
|
||||||
|
case TAP_IRPAUSE:
|
||||||
|
new_state = TAP_IRPAUSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* tap_state_name(tap_state_t state)
|
||||||
|
{
|
||||||
|
const char* ret;
|
||||||
|
|
||||||
|
switch( state )
|
||||||
|
{
|
||||||
|
case TAP_RESET: ret = "RESET"; break;
|
||||||
|
case TAP_IDLE: ret = "RUN/IDLE"; break;
|
||||||
|
case TAP_DRSELECT: ret = "DRSELECT"; break;
|
||||||
|
case TAP_DRCAPTURE: ret = "DRCAPTURE"; break;
|
||||||
|
case TAP_DRSHIFT: ret = "DRSHIFT"; break;
|
||||||
|
case TAP_DREXIT1: ret = "DREXIT1"; break;
|
||||||
|
case TAP_DRPAUSE: ret = "DRPAUSE"; break;
|
||||||
|
case TAP_DREXIT2: ret = "DREXIT2"; break;
|
||||||
|
case TAP_DRUPDATE: ret = "DRUPDATE"; break;
|
||||||
|
case TAP_IRSELECT: ret = "IRSELECT"; break;
|
||||||
|
case TAP_IRCAPTURE: ret = "IRCAPTURE"; break;
|
||||||
|
case TAP_IRSHIFT: ret = "IRSHIFT"; break;
|
||||||
|
case TAP_IREXIT1: ret = "IREXIT1"; break;
|
||||||
|
case TAP_IRPAUSE: ret = "IRPAUSE"; break;
|
||||||
|
case TAP_IREXIT2: ret = "IREXIT2"; break;
|
||||||
|
case TAP_IRUPDATE: ret = "IRUPDATE"; break;
|
||||||
|
default: ret = "???";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
tap_state_t tap_state_by_name(const char *name)
|
||||||
|
{
|
||||||
|
tap_state_t x;
|
||||||
|
|
||||||
|
for( x = 0 ; x < TAP_NUM_STATES ; x++ ){
|
||||||
|
/* be nice to the human */
|
||||||
|
if( 0 == strcasecmp( name, tap_state_name(x) ) ){
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* not found */
|
||||||
|
return TAP_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG_JTAG_IO_
|
||||||
|
|
||||||
|
#define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \
|
||||||
|
do { buf[len] = bit ? '1' : '0'; } while(0)
|
||||||
|
#define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \
|
||||||
|
DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \
|
||||||
|
tap_state_name(a), tap_state_name(b), astr, bstr)
|
||||||
|
|
||||||
|
tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
|
||||||
|
unsigned tap_bits, tap_state_t next_state)
|
||||||
|
{
|
||||||
|
const u8 *tms_buffer;
|
||||||
|
const u8 *tdi_buffer;
|
||||||
|
unsigned tap_bytes;
|
||||||
|
unsigned cur_byte;
|
||||||
|
unsigned cur_bit;
|
||||||
|
|
||||||
|
unsigned tap_out_bits;
|
||||||
|
char tms_str[33];
|
||||||
|
char tdi_str[33];
|
||||||
|
|
||||||
|
tap_state_t last_state;
|
||||||
|
|
||||||
|
// set startstate (and possibly last, if tap_bits == 0)
|
||||||
|
last_state = next_state;
|
||||||
|
DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state));
|
||||||
|
|
||||||
|
tms_buffer = (const u8 *)tms_buf;
|
||||||
|
tdi_buffer = (const u8 *)tdi_buf;
|
||||||
|
|
||||||
|
tap_bytes = TAP_SCAN_BYTES(tap_bits);
|
||||||
|
DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes);
|
||||||
|
|
||||||
|
tap_out_bits = 0;
|
||||||
|
for(cur_byte = 0; cur_byte < tap_bytes; cur_byte++)
|
||||||
|
{
|
||||||
|
for(cur_bit = 0; cur_bit < 8; cur_bit++)
|
||||||
|
{
|
||||||
|
// make sure we do not run off the end of the buffers
|
||||||
|
unsigned tap_bit = cur_byte * 8 + cur_bit;
|
||||||
|
if (tap_bit == tap_bits)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// check and save TMS bit
|
||||||
|
tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit));
|
||||||
|
JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit);
|
||||||
|
|
||||||
|
// use TMS bit to find the next TAP state
|
||||||
|
next_state = tap_state_transition(last_state, tap_bit);
|
||||||
|
|
||||||
|
// check and store TDI bit
|
||||||
|
tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit));
|
||||||
|
JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit);
|
||||||
|
|
||||||
|
// increment TAP bits
|
||||||
|
tap_out_bits++;
|
||||||
|
|
||||||
|
// Only show TDO bits on state transitions, or
|
||||||
|
// after some number of bits in the same state.
|
||||||
|
if ((next_state == last_state) && (tap_out_bits < 32))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// terminate strings and display state transition
|
||||||
|
tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
|
||||||
|
JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
|
||||||
|
|
||||||
|
// reset state
|
||||||
|
last_state = next_state;
|
||||||
|
tap_out_bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tap_out_bits)
|
||||||
|
{
|
||||||
|
// terminate strings and display state transition
|
||||||
|
tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
|
||||||
|
JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state));
|
||||||
|
|
||||||
|
return next_state;
|
||||||
|
}
|
||||||
|
#endif // _DEBUG_JTAG_IO_
|
||||||
|
|
||||||
|
void tap_use_new_tms_table(bool use_new)
|
||||||
|
{
|
||||||
|
tms_seqs = use_new ? &short_tms_seqs : &old_tms_seqs;
|
||||||
|
}
|
||||||
|
bool tap_uses_new_tms_table(void)
|
||||||
|
{
|
||||||
|
return tms_seqs == &short_tms_seqs;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#ifndef OPENOCD_JTAG_INTERFACE_H
|
#ifndef OPENOCD_JTAG_INTERFACE_H
|
||||||
#define OPENOCD_JTAG_INTERFACE_H
|
#define OPENOCD_JTAG_INTERFACE_H
|
||||||
|
|
||||||
|
#include "jtag.h"
|
||||||
|
|
||||||
/* @file
|
/* @file
|
||||||
* The "Cable Helper API" is what the cable drivers can use to help
|
* The "Cable Helper API" is what the cable drivers can use to help
|
||||||
* implement their "Cable API". So a Cable Helper API is a set of
|
* implement their "Cable API". So a Cable Helper API is a set of
|
||||||
|
|
440
src/jtag/jtag.c
440
src/jtag/jtag.c
|
@ -2795,443 +2795,6 @@ void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----<Cable Helper API>---------------------------------------*/
|
|
||||||
|
|
||||||
/* these Cable Helper API functions are all documented in the jtag.h header file,
|
|
||||||
using a Doxygen format. And since Doxygen's configuration file "Doxyfile",
|
|
||||||
is setup to prefer its docs in the header file, no documentation is here, for
|
|
||||||
if it were, it would have to be doubly maintained.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see tap_set_state() and tap_get_state() accessors.
|
|
||||||
* Actual name is not important since accessors hide it.
|
|
||||||
*/
|
|
||||||
static tap_state_t state_follower = TAP_RESET;
|
|
||||||
|
|
||||||
void tap_set_state_impl( tap_state_t new_state )
|
|
||||||
{
|
|
||||||
/* this is the state we think the TAPs are in now, was cur_state */
|
|
||||||
state_follower = new_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
tap_state_t tap_get_state()
|
|
||||||
{
|
|
||||||
return state_follower;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see tap_set_end_state() and tap_get_end_state() accessors.
|
|
||||||
* Actual name is not important because accessors hide it.
|
|
||||||
*/
|
|
||||||
static tap_state_t end_state_follower = TAP_RESET;
|
|
||||||
|
|
||||||
void tap_set_end_state( tap_state_t new_end_state )
|
|
||||||
{
|
|
||||||
/* this is the state we think the TAPs will be in at completion of the
|
|
||||||
current TAP operation, was end_state
|
|
||||||
*/
|
|
||||||
end_state_follower = new_end_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
tap_state_t tap_get_end_state()
|
|
||||||
{
|
|
||||||
return end_state_follower;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int tap_move_ndx( tap_state_t astate )
|
|
||||||
{
|
|
||||||
/* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */
|
|
||||||
|
|
||||||
int ndx;
|
|
||||||
|
|
||||||
switch( astate )
|
|
||||||
{
|
|
||||||
case TAP_RESET: ndx = 0; break;
|
|
||||||
case TAP_DRSHIFT: ndx = 2; break;
|
|
||||||
case TAP_DRPAUSE: ndx = 3; break;
|
|
||||||
case TAP_IDLE: ndx = 1; break;
|
|
||||||
case TAP_IRSHIFT: ndx = 4; break;
|
|
||||||
case TAP_IRPAUSE: ndx = 5; break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR( "fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate) );
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* tap_move[i][j]: tap movement command to go from state i to state j
|
|
||||||
* 0: Test-Logic-Reset
|
|
||||||
* 1: Run-Test/Idle
|
|
||||||
* 2: Shift-DR
|
|
||||||
* 3: Pause-DR
|
|
||||||
* 4: Shift-IR
|
|
||||||
* 5: Pause-IR
|
|
||||||
*
|
|
||||||
* DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
|
|
||||||
*/
|
|
||||||
struct tms_sequences
|
|
||||||
{
|
|
||||||
u8 bits;
|
|
||||||
u8 bit_count;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These macros allow us to specify TMS state transitions by bits rather than hex bytes.
|
|
||||||
* Read the bits from LSBit first to MSBit last (right-to-left).
|
|
||||||
*/
|
|
||||||
#define HEX__(n) 0x##n##LU
|
|
||||||
|
|
||||||
#define B8__(x) \
|
|
||||||
(((x) & 0x0000000FLU)?(1<<0):0) \
|
|
||||||
+(((x) & 0x000000F0LU)?(1<<1):0) \
|
|
||||||
+(((x) & 0x00000F00LU)?(1<<2):0) \
|
|
||||||
+(((x) & 0x0000F000LU)?(1<<3):0) \
|
|
||||||
+(((x) & 0x000F0000LU)?(1<<4):0) \
|
|
||||||
+(((x) & 0x00F00000LU)?(1<<5):0) \
|
|
||||||
+(((x) & 0x0F000000LU)?(1<<6):0) \
|
|
||||||
+(((x) & 0xF0000000LU)?(1<<7):0)
|
|
||||||
|
|
||||||
#define B8(bits,count) { ((u8)B8__(HEX__(bits))), (count) }
|
|
||||||
|
|
||||||
static const struct tms_sequences old_tms_seqs[6][6] = /* [from_state_ndx][to_state_ndx] */
|
|
||||||
{
|
|
||||||
/* value clocked to TMS to move from one of six stable states to another.
|
|
||||||
* N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
|
|
||||||
* N.B. These values are tightly bound to the table in tap_get_tms_path_len().
|
|
||||||
* N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
|
|
||||||
* These extra ones cause no TAP state problem, because we go into reset and stay in reset.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* to state: */
|
|
||||||
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
|
||||||
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
|
||||||
{ B8(1111111,7), B8(0000000,7), B8(0100101,7), B8(0000101,7), B8(0101011,7), B8(0001011,7) }, /* IDLE */
|
|
||||||
{ B8(1111111,7), B8(0110001,7), B8(0000000,7), B8(0000001,7), B8(0001111,7), B8(0101111,7) }, /* DRSHIFT */
|
|
||||||
{ B8(1111111,7), B8(0110000,7), B8(0100000,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* DRPAUSE */
|
|
||||||
{ B8(1111111,7), B8(0110001,7), B8(0000111,7), B8(0010111,7), B8(0000000,7), B8(0000001,7) }, /* IRSHIFT */
|
|
||||||
{ B8(1111111,7), B8(0110000,7), B8(0011100,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* IRPAUSE */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const struct tms_sequences short_tms_seqs[6][6] = /* [from_state_ndx][to_state_ndx] */
|
|
||||||
{
|
|
||||||
/* this is the table submitted by Jeff Williams on 3/30/2009 with this comment:
|
|
||||||
|
|
||||||
OK, I added Peter's version of the state table, and it works OK for
|
|
||||||
me on MC1322x. I've recreated the jlink portion of patch with this
|
|
||||||
new state table. His changes to my state table are pretty minor in
|
|
||||||
terms of total transitions, but Peter feels that his version fixes
|
|
||||||
some long-standing problems.
|
|
||||||
Jeff
|
|
||||||
|
|
||||||
I added the bit count into the table, reduced RESET column to 7 bits from 8.
|
|
||||||
Dick
|
|
||||||
|
|
||||||
state specific comments:
|
|
||||||
------------------------
|
|
||||||
*->RESET tried the 5 bit reset and it gave me problems, 7 bits seems to
|
|
||||||
work better on ARM9 with ft2232 driver. (Dick)
|
|
||||||
|
|
||||||
RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
|
||||||
needed on ARM9 with ft2232 driver. (Dick)
|
|
||||||
|
|
||||||
RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing.
|
|
||||||
needed on ARM9 with ft2232 driver. (Dick)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* to state: */
|
|
||||||
/* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
|
|
||||||
{ B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
|
|
||||||
{ B8(1111111,7), B8(0000000,7), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */
|
|
||||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */
|
|
||||||
{ B8(1111111,7), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */
|
|
||||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */
|
|
||||||
{ B8(1111111,7), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef const struct tms_sequences tms_table[6][6];
|
|
||||||
|
|
||||||
static tms_table *tms_seqs=&short_tms_seqs;
|
|
||||||
|
|
||||||
int tap_get_tms_path( tap_state_t from, tap_state_t to )
|
|
||||||
{
|
|
||||||
return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int tap_get_tms_path_len( tap_state_t from, tap_state_t to )
|
|
||||||
{
|
|
||||||
return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool tap_is_state_stable(tap_state_t astate)
|
|
||||||
{
|
|
||||||
bool is_stable;
|
|
||||||
|
|
||||||
/* A switch() is used because it is symbol dependent
|
|
||||||
(not value dependent like an array), and can also check bounds.
|
|
||||||
*/
|
|
||||||
switch( astate )
|
|
||||||
{
|
|
||||||
case TAP_RESET:
|
|
||||||
case TAP_IDLE:
|
|
||||||
case TAP_DRSHIFT:
|
|
||||||
case TAP_DRPAUSE:
|
|
||||||
case TAP_IRSHIFT:
|
|
||||||
case TAP_IRPAUSE:
|
|
||||||
is_stable = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
is_stable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_stable;
|
|
||||||
}
|
|
||||||
|
|
||||||
tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
|
|
||||||
{
|
|
||||||
tap_state_t new_state;
|
|
||||||
|
|
||||||
/* A switch is used because it is symbol dependent and not value dependent
|
|
||||||
like an array. Also it can check for out of range conditions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (tms)
|
|
||||||
{
|
|
||||||
switch (cur_state)
|
|
||||||
{
|
|
||||||
case TAP_RESET:
|
|
||||||
new_state = cur_state;
|
|
||||||
break;
|
|
||||||
case TAP_IDLE:
|
|
||||||
case TAP_DRUPDATE:
|
|
||||||
case TAP_IRUPDATE:
|
|
||||||
new_state = TAP_DRSELECT;
|
|
||||||
break;
|
|
||||||
case TAP_DRSELECT:
|
|
||||||
new_state = TAP_IRSELECT;
|
|
||||||
break;
|
|
||||||
case TAP_DRCAPTURE:
|
|
||||||
case TAP_DRSHIFT:
|
|
||||||
new_state = TAP_DREXIT1;
|
|
||||||
break;
|
|
||||||
case TAP_DREXIT1:
|
|
||||||
case TAP_DREXIT2:
|
|
||||||
new_state = TAP_DRUPDATE;
|
|
||||||
break;
|
|
||||||
case TAP_DRPAUSE:
|
|
||||||
new_state = TAP_DREXIT2;
|
|
||||||
break;
|
|
||||||
case TAP_IRSELECT:
|
|
||||||
new_state = TAP_RESET;
|
|
||||||
break;
|
|
||||||
case TAP_IRCAPTURE:
|
|
||||||
case TAP_IRSHIFT:
|
|
||||||
new_state = TAP_IREXIT1;
|
|
||||||
break;
|
|
||||||
case TAP_IREXIT1:
|
|
||||||
case TAP_IREXIT2:
|
|
||||||
new_state = TAP_IRUPDATE;
|
|
||||||
break;
|
|
||||||
case TAP_IRPAUSE:
|
|
||||||
new_state = TAP_IREXIT2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (cur_state)
|
|
||||||
{
|
|
||||||
case TAP_RESET:
|
|
||||||
case TAP_IDLE:
|
|
||||||
case TAP_DRUPDATE:
|
|
||||||
case TAP_IRUPDATE:
|
|
||||||
new_state = TAP_IDLE;
|
|
||||||
break;
|
|
||||||
case TAP_DRSELECT:
|
|
||||||
new_state = TAP_DRCAPTURE;
|
|
||||||
break;
|
|
||||||
case TAP_DRCAPTURE:
|
|
||||||
case TAP_DRSHIFT:
|
|
||||||
case TAP_DREXIT2:
|
|
||||||
new_state = TAP_DRSHIFT;
|
|
||||||
break;
|
|
||||||
case TAP_DREXIT1:
|
|
||||||
case TAP_DRPAUSE:
|
|
||||||
new_state = TAP_DRPAUSE;
|
|
||||||
break;
|
|
||||||
case TAP_IRSELECT:
|
|
||||||
new_state = TAP_IRCAPTURE;
|
|
||||||
break;
|
|
||||||
case TAP_IRCAPTURE:
|
|
||||||
case TAP_IRSHIFT:
|
|
||||||
case TAP_IREXIT2:
|
|
||||||
new_state = TAP_IRSHIFT;
|
|
||||||
break;
|
|
||||||
case TAP_IREXIT1:
|
|
||||||
case TAP_IRPAUSE:
|
|
||||||
new_state = TAP_IRPAUSE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* tap_state_name(tap_state_t state)
|
|
||||||
{
|
|
||||||
const char* ret;
|
|
||||||
|
|
||||||
switch( state )
|
|
||||||
{
|
|
||||||
case TAP_RESET: ret = "RESET"; break;
|
|
||||||
case TAP_IDLE: ret = "RUN/IDLE"; break;
|
|
||||||
case TAP_DRSELECT: ret = "DRSELECT"; break;
|
|
||||||
case TAP_DRCAPTURE: ret = "DRCAPTURE"; break;
|
|
||||||
case TAP_DRSHIFT: ret = "DRSHIFT"; break;
|
|
||||||
case TAP_DREXIT1: ret = "DREXIT1"; break;
|
|
||||||
case TAP_DRPAUSE: ret = "DRPAUSE"; break;
|
|
||||||
case TAP_DREXIT2: ret = "DREXIT2"; break;
|
|
||||||
case TAP_DRUPDATE: ret = "DRUPDATE"; break;
|
|
||||||
case TAP_IRSELECT: ret = "IRSELECT"; break;
|
|
||||||
case TAP_IRCAPTURE: ret = "IRCAPTURE"; break;
|
|
||||||
case TAP_IRSHIFT: ret = "IRSHIFT"; break;
|
|
||||||
case TAP_IREXIT1: ret = "IREXIT1"; break;
|
|
||||||
case TAP_IRPAUSE: ret = "IRPAUSE"; break;
|
|
||||||
case TAP_IREXIT2: ret = "IREXIT2"; break;
|
|
||||||
case TAP_IRUPDATE: ret = "IRUPDATE"; break;
|
|
||||||
default: ret = "???";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
tap_state_t tap_state_by_name(const char *name)
|
|
||||||
{
|
|
||||||
tap_state_t x;
|
|
||||||
|
|
||||||
for( x = 0 ; x < TAP_NUM_STATES ; x++ ){
|
|
||||||
/* be nice to the human */
|
|
||||||
if( 0 == strcasecmp( name, tap_state_name(x) ) ){
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* not found */
|
|
||||||
return TAP_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG_JTAG_IO_
|
|
||||||
|
|
||||||
#define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \
|
|
||||||
do { buf[len] = bit ? '1' : '0'; } while(0)
|
|
||||||
#define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \
|
|
||||||
DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \
|
|
||||||
tap_state_name(a), tap_state_name(b), astr, bstr)
|
|
||||||
|
|
||||||
tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
|
|
||||||
unsigned tap_bits, tap_state_t next_state)
|
|
||||||
{
|
|
||||||
const u8 *tms_buffer;
|
|
||||||
const u8 *tdi_buffer;
|
|
||||||
unsigned tap_bytes;
|
|
||||||
unsigned cur_byte;
|
|
||||||
unsigned cur_bit;
|
|
||||||
|
|
||||||
unsigned tap_out_bits;
|
|
||||||
char tms_str[33];
|
|
||||||
char tdi_str[33];
|
|
||||||
|
|
||||||
tap_state_t last_state;
|
|
||||||
|
|
||||||
// set startstate (and possibly last, if tap_bits == 0)
|
|
||||||
last_state = next_state;
|
|
||||||
DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state));
|
|
||||||
|
|
||||||
tms_buffer = (const u8 *)tms_buf;
|
|
||||||
tdi_buffer = (const u8 *)tdi_buf;
|
|
||||||
|
|
||||||
tap_bytes = TAP_SCAN_BYTES(tap_bits);
|
|
||||||
DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes);
|
|
||||||
|
|
||||||
tap_out_bits = 0;
|
|
||||||
for(cur_byte = 0; cur_byte < tap_bytes; cur_byte++)
|
|
||||||
{
|
|
||||||
for(cur_bit = 0; cur_bit < 8; cur_bit++)
|
|
||||||
{
|
|
||||||
// make sure we do not run off the end of the buffers
|
|
||||||
unsigned tap_bit = cur_byte * 8 + cur_bit;
|
|
||||||
if (tap_bit == tap_bits)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// check and save TMS bit
|
|
||||||
tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit));
|
|
||||||
JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit);
|
|
||||||
|
|
||||||
// use TMS bit to find the next TAP state
|
|
||||||
next_state = tap_state_transition(last_state, tap_bit);
|
|
||||||
|
|
||||||
// check and store TDI bit
|
|
||||||
tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit));
|
|
||||||
JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit);
|
|
||||||
|
|
||||||
// increment TAP bits
|
|
||||||
tap_out_bits++;
|
|
||||||
|
|
||||||
// Only show TDO bits on state transitions, or
|
|
||||||
// after some number of bits in the same state.
|
|
||||||
if ((next_state == last_state) && (tap_out_bits < 32))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// terminate strings and display state transition
|
|
||||||
tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
|
|
||||||
JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
|
|
||||||
|
|
||||||
// reset state
|
|
||||||
last_state = next_state;
|
|
||||||
tap_out_bits = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tap_out_bits)
|
|
||||||
{
|
|
||||||
// terminate strings and display state transition
|
|
||||||
tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
|
|
||||||
JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state));
|
|
||||||
|
|
||||||
return next_state;
|
|
||||||
}
|
|
||||||
#endif // _DEBUG_JTAG_IO_
|
|
||||||
|
|
||||||
void tap_use_new_tms_table(bool use_new)
|
|
||||||
{
|
|
||||||
tms_seqs = use_new ? &short_tms_seqs : &old_tms_seqs;
|
|
||||||
}
|
|
||||||
bool tap_uses_new_tms_table(void)
|
|
||||||
{
|
|
||||||
return tms_seqs == &short_tms_seqs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||||
{
|
{
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
|
@ -3256,9 +2819,6 @@ static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----</Cable Helper API>--------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function jtag_add_statemove
|
* Function jtag_add_statemove
|
||||||
* moves from the current state to the goal \a state. This needs
|
* moves from the current state to the goal \a state. This needs
|
||||||
|
|
Loading…
Reference in New Issue