Dick Hollenbeck <dick@softplc.com> adds jtag_add_clocks() and implements those in the bitbang and ft2232.c. nearly a full rewrite of the xsvf.c. improved some messaging only affected by _DEBUG_JTAG_IO_

git-svn-id: svn://svn.berlios.de/openocd/trunk@1308 b42882b7-edfa-0310-969c-e2dbd0fdcd60
__archive__
oharboe 2009-01-09 07:42:45 +00:00
parent ebd5afbb0e
commit 9324e6280e
6 changed files with 1005 additions and 321 deletions

View File

@ -37,6 +37,10 @@
#include <stdlib.h>
#include <unistd.h>
static void bitbang_stableclocks(int num_cycles);
bitbang_interface_t *bitbang_interface;
/* DANGER!!!! clock absolutely *MUST* be 0 in idle or reset won't work!
@ -61,6 +65,8 @@ bitbang_interface_t *bitbang_interface;
int bitbang_execute_queue(void);
/* The bitbang driver leaves the TCK 0 when in idle */
void bitbang_end_state(enum tap_state state)
@ -153,6 +159,21 @@ void bitbang_runtest(int num_cycles)
bitbang_state_move();
}
static void bitbang_stableclocks(int num_cycles)
{
int i;
/* send num_cycles clocks onto the cable */
for (i = 0; i < num_cycles; i++)
{
bitbang_interface->write(1, 0, 0);
bitbang_interface->write(0, 0, 0);
}
}
void bitbang_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
{
enum tap_state saved_end_state = end_state;
@ -247,7 +268,7 @@ int bitbang_execute_queue(void)
{
case JTAG_END_STATE:
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
LOG_DEBUG("end_state: %s", jtag_state_name(cmd->cmd.end_state->end_state) );
#endif
if (cmd->cmd.end_state->end_state != -1)
bitbang_end_state(cmd->cmd.end_state->end_state);
@ -264,15 +285,20 @@ int bitbang_execute_queue(void)
break;
case JTAG_RUNTEST:
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
LOG_DEBUG("runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, jtag_state_name(cmd->cmd.runtest->end_state) );
#endif
if (cmd->cmd.runtest->end_state != -1)
bitbang_end_state(cmd->cmd.runtest->end_state);
bitbang_runtest(cmd->cmd.runtest->num_cycles);
break;
case JTAG_STABLECLOCKS:
bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles);
break;
case JTAG_STATEMOVE:
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
LOG_DEBUG("statemove end in %s", jtag_state_name(cmd->cmd.statemove->end_state));
#endif
if (cmd->cmd.statemove->end_state != -1)
bitbang_end_state(cmd->cmd.statemove->end_state);
@ -280,13 +306,14 @@ int bitbang_execute_queue(void)
break;
case JTAG_PATHMOVE:
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
#endif
bitbang_path_move(cmd->cmd.pathmove);
break;
case JTAG_SCAN:
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("%s scan end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", cmd->cmd.scan->end_state);
LOG_DEBUG("%s scan end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", jtag_state_name(cmd->cmd.scan->end_state) );
#endif
if (cmd->cmd.scan->end_state != -1)
bitbang_end_state(cmd->cmd.scan->end_state);

View File

@ -32,8 +32,13 @@ static tap_state_t dummy_state = TAP_RESET;
static int dummy_clock; /* edge detector */
static int clock_count; /* count clocks in any stable state, only stable states */
static tap_state_t tap_state_transition(tap_state_t cur_state, int tms);
static u32 dummy_data;
int dummy_speed(int speed);
int dummy_register_commands(struct command_context_s *cmd_ctx);
@ -76,7 +81,9 @@ bitbang_interface_t dummy_bitbang =
int dummy_read(void)
{
return 1;
int data = 1 & dummy_data;
dummy_data = (dummy_data >> 1) | (1<<31);
return data;
}
@ -88,9 +95,30 @@ void dummy_write(int tck, int tms, int tdi)
if( tck )
{
int old_state = dummy_state;
dummy_state = tap_state_transition( dummy_state, tms );
dummy_state = tap_state_transition( old_state, tms );
if( old_state != dummy_state )
LOG_DEBUG( "dummy_tap=%s", jtag_state_name(dummy_state) );
{
if( clock_count )
{
LOG_DEBUG("dummy_tap: %d stable clocks", clock_count);
clock_count = 0;
}
LOG_DEBUG("dummy_tap: %s", jtag_state_name(dummy_state) );
#if defined(DEBUG)
if(dummy_state == TAP_DRCAPTURE)
dummy_data = 0x01255043;
#endif
}
else
{
/* this is a stable state clock edge, no change of state here,
* simply increment clock_count for subsequent logging
*/
++clock_count;
}
}
dummy_clock = tck;
}
@ -99,8 +127,11 @@ void dummy_write(int tck, int tms, int tdi)
void dummy_reset(int trst, int srst)
{
dummy_clock = 0;
dummy_state = TAP_RESET;
LOG_DEBUG( "reset to %s", jtag_state_name(dummy_state) );
if (trst || (srst && (jtag_reset_config & RESET_SRST_PULLS_TRST)))
dummy_state = TAP_RESET;
LOG_DEBUG("reset to: %s", jtag_state_name(dummy_state) );
}
static int dummy_khz(int khz, int *jtag_speed)

View File

@ -76,6 +76,18 @@ int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, c
int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
/**
* Function ft2232_stableclocks
* will send out \a num_cycles on the TCK line while the TAP(s)
* are in a stable state. Calling code must ensure that current state is
* stable, that verification is not done in here.
* @param num_cycles is the count of clocks cycles to send.
* @return int - ERROR_OK or ERROR_JTAG_QUEUE_FAILED
*/
static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd);
char *ft2232_device_desc = NULL;
char *ft2232_serial = NULL;
char *ft2232_layout = NULL;
@ -149,10 +161,15 @@ static FT_HANDLE ftdih = NULL;
static struct ftdi_context ftdic;
#endif
static jtag_command_t *first_unsent; /* next command that has to be sent */
static int require_send;
static u8 *ft2232_buffer = NULL;
static int ft2232_buffer_size = 0;
static int ft2232_read_pointer = 0;
static int ft2232_expect_read = 0;
#define FT2232_BUFFER_SIZE 131072
#define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++]
#define BUFFER_READ ft2232_buffer[ft2232_read_pointer++]
@ -344,7 +361,7 @@ void ft2232_end_state(enum tap_state state)
void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size)
{
int num_bytes = ((scan_size + 7) / 8);
int num_bytes = (scan_size + 7) / 8;
int bits_left = scan_size;
int cur_byte = 0;
@ -903,14 +920,14 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type)
if (type == SCAN_IN) /* only from device to host */
{
/* complete bytes */
predicted_size += (CEIL(num_bytes, 65536)) * 3;
predicted_size += CEIL(num_bytes, 65536) * 3;
/* remaining bits - 1 (up to 7) */
predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
}
else /* host to device, or bidirectional */
{
/* complete bytes */
predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3;
predicted_size += num_bytes + CEIL(num_bytes, 65536) * 3;
/* remaining bits -1 (up to 7) */
predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
}
@ -1185,15 +1202,16 @@ void stm32stick_reset(int trst, int srst)
int ft2232_execute_queue()
{
jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
jtag_command_t *first_unsent = cmd; /* next command that has to be sent */
u8 *buffer;
int scan_size; /* size of IR or DR scan */
enum scan_type type;
int i;
int predicted_size = 0;
int require_send = 0;
int retval;
first_unsent = cmd; /* next command that has to be sent */
require_send = 0;
/* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
* that wasn't handled by a caller-provided error handler
*/
@ -1214,6 +1232,7 @@ int ft2232_execute_queue()
if (cmd->cmd.end_state->end_state != -1)
ft2232_end_state(cmd->cmd.end_state->end_state);
break;
case JTAG_RESET:
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 3;
@ -1236,6 +1255,7 @@ int ft2232_execute_queue()
LOG_DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
#endif
break;
case JTAG_RUNTEST:
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 0;
@ -1292,9 +1312,10 @@ int ft2232_execute_queue()
}
require_send = 1;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state);
LOG_DEBUG("runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, jtag_state_name(end_state));
#endif
break;
case JTAG_STATEMOVE:
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 3;
@ -1317,9 +1338,10 @@ int ft2232_execute_queue()
cur_state = end_state;
require_send = 1;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("statemove: %i", end_state);
LOG_DEBUG("statemove: %s", jtag_state_name(end_state));
#endif
break;
case JTAG_PATHMOVE:
/* only send the maximum buffer size that FT2232C can handle */
predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);
@ -1333,9 +1355,11 @@ int ft2232_execute_queue()
ft2232_add_pathmove(cmd->cmd.pathmove);
require_send = 1;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
LOG_DEBUG("pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
#endif
break;
case JTAG_SCAN:
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
type = jtag_scan_type(cmd->cmd.scan);
@ -1375,18 +1399,45 @@ int ft2232_execute_queue()
if (buffer)
free(buffer);
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state);
LOG_DEBUG("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
jtag_state_name(end_state));
#endif
break;
case JTAG_SLEEP:
if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
retval = ERROR_JTAG_QUEUE_FAILED;
first_unsent = cmd->next;
jtag_sleep(cmd->cmd.sleep->us);
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("sleep %i usec", cmd->cmd.sleep->us);
LOG_DEBUG("sleep %i usec while in %s", cmd->cmd.sleep->us, jtag_state_name(cur_state));
#endif
break;
case JTAG_STABLECLOCKS:
/* "if (tap_move_map[cur_state] != -1)" is of no help when cur_state==TAP_IDLE */
switch(cur_state)
{
case TAP_DRSHIFT:
case TAP_IDLE:
case TAP_RESET:
case TAP_DRPAUSE:
case TAP_IRSHIFT:
case TAP_IRPAUSE:
break; /* above stable states are OK */
default:
LOG_ERROR( "jtag_add_clocks() was called with TAP in non-stable state \"%s\"",
jtag_state_name(cur_state) );
retval = ERROR_JTAG_QUEUE_FAILED;
}
if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK)
retval = ERROR_JTAG_QUEUE_FAILED;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, jtag_state_name(cur_state));
#endif
break;
default:
LOG_ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
@ -2279,3 +2330,42 @@ int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd,
return ERROR_OK;
}
static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd)
{
int retval = 0;
while (num_cycles > 0)
{
/* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles
* at most 7 bits per invocation. Here we invoke it potentially
* several times.
*/
int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles;
if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE)
{
if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
retval = ERROR_JTAG_QUEUE_FAILED;
first_unsent = cmd;
}
/* command "Clock Data to TMS/CS Pin (no Read)" */
BUFFER_ADD = 0x4b;
/* scan 7 bit */
BUFFER_ADD = bitcount_per_command - 1;
/* TMS data bits are all zeros to stay in the current stable state */
BUFFER_ADD = 0x0;
require_send = 1;
num_cycles -= bitcount_per_command;
}
return retval;
}

View File

@ -79,22 +79,22 @@ int tap_move_map[16] = {
tap_transition_t tap_transitions[16] =
{
{TAP_RESET, TAP_IDLE}, /* RESET */
{TAP_IRSELECT, TAP_DRCAPTURE}, /* DRSELECT */
{TAP_DREXIT1, TAP_DRSHIFT}, /* DRCAPTURE */
{TAP_DREXIT1, TAP_DRSHIFT}, /* DRSHIFT */
{TAP_RESET, TAP_IDLE}, /* RESET */
{TAP_IRSELECT, TAP_DRCAPTURE}, /* DRSELECT */
{TAP_DREXIT1, TAP_DRSHIFT}, /* DRCAPTURE */
{TAP_DREXIT1, TAP_DRSHIFT}, /* DRSHIFT */
{TAP_DRUPDATE, TAP_DRPAUSE}, /* DREXIT1 */
{TAP_DREXIT2, TAP_DRPAUSE}, /* DRPAUSE */
{TAP_DREXIT2, TAP_DRPAUSE}, /* DRPAUSE */
{TAP_DRUPDATE, TAP_DRSHIFT}, /* DREXIT2 */
{TAP_DRSELECT, TAP_IDLE}, /* DRUPDATE */
{TAP_DRSELECT, TAP_IDLE}, /* IDLE */
{TAP_RESET, TAP_IRCAPTURE}, /* IRSELECT */
{TAP_IREXIT1, TAP_IRSHIFT}, /* IRCAPTURE */
{TAP_IREXIT1, TAP_IRSHIFT}, /* IRSHIFT */
{TAP_DRSELECT, TAP_IDLE}, /* DRUPDATE */
{TAP_DRSELECT, TAP_IDLE}, /* IDLE */
{TAP_RESET, TAP_IRCAPTURE}, /* IRSELECT */
{TAP_IREXIT1, TAP_IRSHIFT}, /* IRCAPTURE */
{TAP_IREXIT1, TAP_IRSHIFT}, /* IRSHIFT */
{TAP_IRUPDATE, TAP_IRPAUSE}, /* IREXIT1 */
{TAP_IREXIT2, TAP_IRPAUSE}, /* IRPAUSE */
{TAP_IREXIT2, TAP_IRPAUSE}, /* IRPAUSE */
{TAP_IRUPDATE, TAP_IRSHIFT}, /* IREXIT2 */
{TAP_DRSELECT, TAP_IDLE} /* IRUPDATE */
{TAP_DRSELECT, TAP_IDLE} /* IRUPDATE */
};
char* jtag_event_strings[] =
@ -983,7 +983,6 @@ int MINIDRIVER(interface_jtag_add_tlr)()
(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
(*last_cmd)->cmd.statemove->end_state = state;
return ERROR_OK;
}
@ -1074,6 +1073,33 @@ void jtag_add_runtest(int num_cycles, enum tap_state state)
jtag_error=retval;
}
int MINIDRIVER(interface_jtag_add_clocks)( int num_cycles )
{
jtag_command_t **last_cmd = jtag_get_last_command_p();
/* allocate memory for a new list member */
*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
(*last_cmd)->next = NULL;
last_comand_pointer = &((*last_cmd)->next);
(*last_cmd)->type = JTAG_STABLECLOCKS;
(*last_cmd)->cmd.stableclocks = cmd_queue_alloc(sizeof(stableclocks_command_t));
(*last_cmd)->cmd.stableclocks->num_cycles = num_cycles;
return ERROR_OK;
}
void jtag_add_clocks( int num_cycles )
{
int retval;
jtag_prelude1();
retval=interface_jtag_add_clocks(num_cycles);
if (retval!=ERROR_OK)
jtag_error=retval;
}
void jtag_add_reset(int req_tlr_or_trst, int req_srst)
{
int trst_with_tlr = 0;
@ -1252,6 +1278,8 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
bit_count = 0;
LOG_DEBUG("num_fields: %i",cmd->num_fields);
for (i = 0; i < cmd->num_fields; i++)
{
if (cmd->fields[i].out_value)
@ -1261,12 +1289,13 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
#endif
buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("fields[%i].out_value: 0x%s", i, char_buf);
LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf);
free(char_buf);
#endif
}
bit_count += cmd->fields[i].num_bits;
LOG_DEBUG("bit_count totalling: %i", bit_count );
}
return bit_count;
@ -1292,10 +1321,8 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
#ifdef _DEBUG_JTAG_IO_
char *char_buf;
char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
LOG_DEBUG("fields[%i].in_value: 0x%s", i, char_buf);
char *char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf);
free(char_buf);
#endif

View File

@ -29,6 +29,7 @@
#include "command.h"
#if 0
#define _DEBUG_JTAG_IO_
#endif
@ -112,6 +113,13 @@ typedef struct runtest_command_s
enum tap_state end_state; /* TAP state in which JTAG commands should finish */
} runtest_command_t;
typedef struct stableclocks_command_s
{
int num_cycles; /* number of clock cycles that should be sent */
} stableclocks_command_t;
typedef struct reset_command_s
{
int trst; /* trst/srst 0: deassert, 1: assert, -1: don't change */
@ -134,6 +142,7 @@ typedef union jtag_command_container_u
statemove_command_t *statemove;
pathmove_command_t *pathmove;
runtest_command_t *runtest;
stableclocks_command_t *stableclocks;
reset_command_t *reset;
end_state_command_t *end_state;
sleep_command_t *sleep;
@ -144,7 +153,8 @@ enum jtag_command_type
JTAG_SCAN = 1,
JTAG_STATEMOVE = 2, JTAG_RUNTEST = 3,
JTAG_RESET = 4, JTAG_END_STATE = 5,
JTAG_PATHMOVE = 6, JTAG_SLEEP = 7
JTAG_PATHMOVE = 6, JTAG_SLEEP = 7,
JTAG_STABLECLOCKS = 8
};
typedef struct jtag_command_s
@ -434,6 +444,16 @@ extern int interface_jtag_add_end_state(enum tap_state endstate);
extern void jtag_add_sleep(u32 us);
extern int interface_jtag_add_sleep(u32 us);
/**
* Function jtag_add_stable_clocks
* first checks that the state in which the clocks are to be issued is
* stable, then queues up clock_count clocks for transmission.
*/
void jtag_add_clocks( int num_cycles );
int interface_jtag_add_clocks( int num_cycles );
/*
* For software FIFO implementations, the queued commands can be executed
* during this call or earlier. A sw queue might decide to push out

File diff suppressed because it is too large Load Diff