git-svn-id: svn://svn.berlios.de/openocd/trunk@1360 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.2.0
@@ -38,6 +38,14 @@ | |||||
#include <unistd.h> | #include <unistd.h> | ||||
/** | |||||
* Function bitbang_stableclocks | |||||
* issues a number of clock cycles while staying in a stable state. | |||||
* Because the TMS value required to stay in the RESET state is a 1, whereas | |||||
* the TMS value required to stay in any of the other stable states is a 0, | |||||
* this function checks the current stable state to decide on the value of TMS | |||||
* to use. | |||||
*/ | |||||
static void bitbang_stableclocks(int num_cycles); | static void bitbang_stableclocks(int num_cycles); | ||||
@@ -162,13 +170,14 @@ void bitbang_runtest(int num_cycles) | |||||
static void bitbang_stableclocks(int num_cycles) | static void bitbang_stableclocks(int num_cycles) | ||||
{ | { | ||||
int tms = (cur_state == TAP_RESET ? 1 : 0); | |||||
int i; | int i; | ||||
/* send num_cycles clocks onto the cable */ | /* send num_cycles clocks onto the cable */ | ||||
for (i = 0; i < num_cycles; i++) | for (i = 0; i < num_cycles; i++) | ||||
{ | { | ||||
bitbang_interface->write(1, 0, 0); | |||||
bitbang_interface->write(0, 0, 0); | |||||
bitbang_interface->write(1, tms, 0); | |||||
bitbang_interface->write(0, tms, 0); | |||||
} | } | ||||
} | } | ||||
@@ -293,6 +302,9 @@ int bitbang_execute_queue(void) | |||||
break; | break; | ||||
case JTAG_STABLECLOCKS: | case JTAG_STABLECLOCKS: | ||||
/* this is only allowed while in a stable state. A check for a stable | |||||
* state was done in jtag_add_clocks() | |||||
*/ | |||||
bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles); | bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles); | ||||
break; | break; | ||||
@@ -1415,22 +1415,9 @@ int ft2232_execute_queue() | |||||
break; | break; | ||||
case JTAG_STABLECLOCKS: | 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; | |||||
} | |||||
/* this is only allowed while in a stable state. A check for a stable | |||||
* state was done in jtag_add_clocks() | |||||
*/ | |||||
if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) | if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) | ||||
retval = ERROR_JTAG_QUEUE_FAILED; | retval = ERROR_JTAG_QUEUE_FAILED; | ||||
#ifdef _DEBUG_JTAG_IO_ | #ifdef _DEBUG_JTAG_IO_ | ||||
@@ -2336,11 +2323,15 @@ static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd) | |||||
{ | { | ||||
int retval = 0; | int retval = 0; | ||||
/* 7 bits of either ones or zeros. */ | |||||
u8 tms = (cur_state == TAP_RESET ? 0x7F : 0x00); | |||||
while (num_cycles > 0) | while (num_cycles > 0) | ||||
{ | { | ||||
/* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles | /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles | ||||
* at most 7 bits per invocation. Here we invoke it potentially | * at most 7 bits per invocation. Here we invoke it potentially | ||||
* several times. | * several times. | ||||
* see: http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf | |||||
*/ | */ | ||||
int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; | int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; | ||||
@@ -2358,8 +2349,8 @@ static int ft2232_stableclocks(int num_cycles, jtag_command_t *cmd) | |||||
/* scan 7 bit */ | /* scan 7 bit */ | ||||
BUFFER_ADD = bitcount_per_command - 1; | BUFFER_ADD = bitcount_per_command - 1; | ||||
/* TMS data bits are all zeros to stay in the current stable state */ | |||||
BUFFER_ADD = 0x0; | |||||
/* TMS data bits are either all zeros or ones to stay in the current stable state */ | |||||
BUFFER_ADD = tms; | |||||
require_send = 1; | require_send = 1; | ||||
@@ -1093,11 +1093,31 @@ void jtag_add_clocks( int num_cycles ) | |||||
{ | { | ||||
int retval; | int retval; | ||||
jtag_prelude1(); | |||||
/* "if (tap_move_map[cm_queue_cur_state] != -1)" is of no help when cur_state==TAP_IDLE */ | |||||
switch(cmd_queue_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(cmd_queue_cur_state) ); | |||||
jtag_error = ERROR_JTAG_NOT_STABLE_STATE; | |||||
return; | |||||
} | |||||
retval=interface_jtag_add_clocks(num_cycles); | |||||
if (retval!=ERROR_OK) | |||||
jtag_error=retval; | |||||
if( num_cycles > 0 ) | |||||
{ | |||||
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) | void jtag_add_reset(int req_tlr_or_trst, int req_srst) | ||||
@@ -1287,7 +1307,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) | |||||
if (cmd->fields[i].out_value) | if (cmd->fields[i].out_value) | ||||
{ | { | ||||
#ifdef _DEBUG_JTAG_IO_ | #ifdef _DEBUG_JTAG_IO_ | ||||
char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16); | |||||
char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits, 16); | |||||
#endif | #endif | ||||
buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); | buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits); | ||||
#ifdef _DEBUG_JTAG_IO_ | #ifdef _DEBUG_JTAG_IO_ | ||||
@@ -1297,9 +1317,6 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer) | |||||
} | } | ||||
bit_count += cmd->fields[i].num_bits; | bit_count += cmd->fields[i].num_bits; | ||||
#ifdef _DEBUG_JTAG_IO_ | |||||
LOG_DEBUG("bit_count totalling: %i", bit_count ); | |||||
#endif | |||||
} | } | ||||
return bit_count; | return bit_count; | ||||
@@ -1325,7 +1342,7 @@ 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); | u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits); | ||||
#ifdef _DEBUG_JTAG_IO_ | #ifdef _DEBUG_JTAG_IO_ | ||||
char *char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); | |||||
char *char_buf = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); | |||||
LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf); | LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf); | ||||
free(char_buf); | free(char_buf); | ||||
#endif | #endif | ||||
@@ -1391,13 +1408,13 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field) | |||||
jtag_tap_name(field->tap)); | jtag_tap_name(field->tap)); | ||||
if (compare_failed) | if (compare_failed) | ||||
{ | { | ||||
char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16); | |||||
char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16); | |||||
char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); | |||||
char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); | |||||
if (field->in_check_mask) | if (field->in_check_mask) | ||||
{ | { | ||||
char *in_check_mask_char; | char *in_check_mask_char; | ||||
in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16); | |||||
in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16); | |||||
LOG_WARNING("value captured during scan didn't pass the requested check:"); | LOG_WARNING("value captured during scan didn't pass the requested check:"); | ||||
LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s", | LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s", | ||||
captured_char, in_check_value_char, in_check_mask_char); | captured_char, in_check_value_char, in_check_mask_char); | ||||
@@ -34,6 +34,11 @@ | |||||
#define _DEBUG_JTAG_IO_ | #define _DEBUG_JTAG_IO_ | ||||
#endif | #endif | ||||
#ifndef DEBUG_JTAG_IOZ | |||||
#define DEBUG_JTAG_IOZ 64 | |||||
#endif | |||||
/* 16 Tap States, from page 21 of ASSET InterTech, Inc.'s svf.pdf | /* 16 Tap States, from page 21 of ASSET InterTech, Inc.'s svf.pdf | ||||
*/ | */ | ||||
typedef enum tap_state | typedef enum tap_state | ||||
@@ -499,12 +504,14 @@ void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e); | |||||
* JTAG subsystem uses codes between -100 and -199 */ | * JTAG subsystem uses codes between -100 and -199 */ | ||||
#define ERROR_JTAG_INIT_FAILED (-100) | #define ERROR_JTAG_INIT_FAILED (-100) | ||||
#define ERROR_JTAG_INVALID_INTERFACE (-101) | |||||
#define ERROR_JTAG_INVALID_INTERFACE (-101) | |||||
#define ERROR_JTAG_NOT_IMPLEMENTED (-102) | #define ERROR_JTAG_NOT_IMPLEMENTED (-102) | ||||
#define ERROR_JTAG_TRST_ASSERTED (-103) | |||||
#define ERROR_JTAG_TRST_ASSERTED (-103) | |||||
#define ERROR_JTAG_QUEUE_FAILED (-104) | #define ERROR_JTAG_QUEUE_FAILED (-104) | ||||
#define ERROR_JTAG_NOT_STABLE_STATE (-105) | |||||
#define ERROR_JTAG_DEVICE_ERROR (-107) | #define ERROR_JTAG_DEVICE_ERROR (-107) | ||||
/* this allows JTAG devices to implement the entire jtag_xxx() layer in hw/sw */ | /* this allows JTAG devices to implement the entire jtag_xxx() layer in hw/sw */ | ||||
#ifdef HAVE_JTAG_MINIDRIVER_H | #ifdef HAVE_JTAG_MINIDRIVER_H | ||||
/* Here a #define MINIDRIVER() and an inline version of hw fifo interface_jtag_add_dr_out can be defined */ | /* Here a #define MINIDRIVER() and an inline version of hw fifo interface_jtag_add_dr_out can be defined */ | ||||
@@ -107,6 +107,7 @@ LSDR 1 TDI (0) | |||||
#define LCOUNT 0x19 | #define LCOUNT 0x19 | ||||
#define LDELAY 0x1A | #define LDELAY 0x1A | ||||
#define LSDR 0x1B | #define LSDR 0x1B | ||||
#define XTRST 0x1C | |||||
/* XSVF valid state values for the XSTATE command, from appendix B of xapp503.pdf */ | /* XSVF valid state values for the XSTATE command, from appendix B of xapp503.pdf */ | ||||
@@ -127,6 +128,11 @@ LSDR 1 TDI (0) | |||||
#define XSV_IREXIT2 0x0E | #define XSV_IREXIT2 0x0E | ||||
#define XSV_IRUPDATE 0x0F | #define XSV_IRUPDATE 0x0F | ||||
/* arguments to XTRST */ | |||||
#define XTRST_ON 0 | |||||
#define XTRST_OFF 1 | |||||
#define XTRST_Z 2 | |||||
#define XTRST_ABSENT 3 | |||||
#define XSTATE_MAX_PATH 12 | #define XSTATE_MAX_PATH 12 | ||||
@@ -210,7 +216,7 @@ static void xsvf_add_statemove(tap_state_t state) | |||||
int xsvf_register_commands(struct command_context_s *cmd_ctx) | int xsvf_register_commands(struct command_context_s *cmd_ctx) | ||||
{ | { | ||||
register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command, | register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command, | ||||
COMMAND_EXEC, "run xsvf <file> [virt2]"); | |||||
COMMAND_EXEC, "run xsvf <file> [virt2] [quiet]"); | |||||
return ERROR_OK; | return ERROR_OK; | ||||
} | } | ||||
@@ -288,6 +294,8 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
int unsupported = 0; | int unsupported = 0; | ||||
int tdo_mismatch = 0; | int tdo_mismatch = 0; | ||||
int result; | int result; | ||||
int verbose = 1; | |||||
char* filename; | |||||
int runtest_requires_tck = 0; /* a flag telling whether to clock TCK during waits, or simply sleep, controled by virt2 */ | int runtest_requires_tck = 0; /* a flag telling whether to clock TCK during waits, or simply sleep, controled by virt2 */ | ||||
@@ -300,10 +308,12 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
if (argc < 2) | if (argc < 2) | ||||
{ | { | ||||
command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>"); | |||||
command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> [<variant>] [quiet]"); | |||||
return ERROR_FAIL; | return ERROR_FAIL; | ||||
} | } | ||||
filename = args[1]; /* we mess with args starting point below, snapshot filename here */ | |||||
if (strcmp(args[0], "plain") != 0) | if (strcmp(args[0], "plain") != 0) | ||||
{ | { | ||||
tap = jtag_TapByString( args[0] ); | tap = jtag_TapByString( args[0] ); | ||||
@@ -314,9 +324,9 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
} | } | ||||
} | } | ||||
if ((xsvf_fd = open(args[1], O_RDONLY)) < 0) | |||||
if ((xsvf_fd = open(filename, O_RDONLY)) < 0) | |||||
{ | { | ||||
command_print(cmd_ctx, "file \"%s\" not found", args[1]); | |||||
command_print(cmd_ctx, "file \"%s\" not found", filename); | |||||
return ERROR_FAIL; | return ERROR_FAIL; | ||||
} | } | ||||
@@ -324,9 +334,16 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
if ((argc > 2) && (strcmp(args[2], "virt2") == 0)) | if ((argc > 2) && (strcmp(args[2], "virt2") == 0)) | ||||
{ | { | ||||
runtest_requires_tck = 1; | runtest_requires_tck = 1; | ||||
--argc; | |||||
++args; | |||||
} | |||||
if ((argc > 2) && (strcmp(args[2], "quiet") == 0)) | |||||
{ | |||||
verbose = 0; | |||||
} | } | ||||
LOG_USER("xsvf processing file: \"%s\"", args[1]); | |||||
LOG_USER("xsvf processing file: \"%s\"", filename); | |||||
while( read(xsvf_fd, &opcode, 1) > 0 ) | while( read(xsvf_fd, &opcode, 1) > 0 ) | ||||
{ | { | ||||
@@ -462,7 +479,8 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
jtag_add_pathmove( sizeof(exception_path)/sizeof(exception_path[0]), exception_path); | jtag_add_pathmove( sizeof(exception_path)/sizeof(exception_path[0]), exception_path); | ||||
LOG_USER("%s %d retry %d", op_name, xsdrsize, attempt); | |||||
if (verbose) | |||||
LOG_USER("%s %d retry %d", op_name, xsdrsize, attempt); | |||||
} | } | ||||
field.tap = tap; | field.tap = tap; | ||||
@@ -749,7 +767,8 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
} while (uc != 0); | } while (uc != 0); | ||||
comment[sizeof(comment)-1] = 0; /* regardless, terminate */ | comment[sizeof(comment)-1] = 0; /* regardless, terminate */ | ||||
LOG_USER(comment); | |||||
if (verbose) | |||||
LOG_USER(comment); | |||||
} | } | ||||
break; | break; | ||||
@@ -918,20 +937,24 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
{ | { | ||||
scan_field_t field; | scan_field_t field; | ||||
xsvf_add_statemove( loop_state ); | |||||
jtag_add_clocks(loop_clocks); | |||||
jtag_add_sleep(loop_usecs); | |||||
field.tap = tap; | field.tap = tap; | ||||
field.num_bits = xsdrsize; | field.num_bits = xsdrsize; | ||||
field.out_value = dr_out_buf; | field.out_value = dr_out_buf; | ||||
field.out_mask = NULL; | field.out_mask = NULL; | ||||
field.in_value = NULL; | field.in_value = NULL; | ||||
if (attempt > 0) | |||||
if (attempt > 0 && verbose) | |||||
LOG_USER("LSDR retry %d", attempt); | LOG_USER("LSDR retry %d", attempt); | ||||
jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); | jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL); | ||||
if (tap == NULL) | if (tap == NULL) | ||||
jtag_add_plain_dr_scan(1, &field, loop_state); | |||||
jtag_add_plain_dr_scan(1, &field, TAP_DRPAUSE); | |||||
else | else | ||||
jtag_add_dr_scan(1, &field, loop_state); | |||||
jtag_add_dr_scan(1, &field, TAP_DRPAUSE); | |||||
/* LOG_DEBUG("FLUSHING QUEUE"); */ | /* LOG_DEBUG("FLUSHING QUEUE"); */ | ||||
result = jtag_execute_queue(); | result = jtag_execute_queue(); | ||||
@@ -940,9 +963,6 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
matched = 1; | matched = 1; | ||||
break; | break; | ||||
} | } | ||||
jtag_add_clocks(loop_clocks); | |||||
jtag_add_sleep(loop_usecs); | |||||
} | } | ||||
if (!matched ) | if (!matched ) | ||||
@@ -954,6 +974,34 @@ static int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, cha | |||||
} | } | ||||
break; | break; | ||||
case XTRST: | |||||
{ | |||||
u8 trst_mode; | |||||
if (read(xsvf_fd, &trst_mode, 1) < 0) | |||||
{ | |||||
do_abort = 1; | |||||
break; | |||||
} | |||||
switch( trst_mode ) | |||||
{ | |||||
case XTRST_ON: | |||||
jtag_add_reset(1, 0); | |||||
break; | |||||
case XTRST_OFF: | |||||
case XTRST_Z: | |||||
jtag_add_reset(0, 0); | |||||
break; | |||||
case XTRST_ABSENT: | |||||
break; | |||||
default: | |||||
LOG_ERROR( "XTRST mode argument (0x%02X) out of range", trst_mode ); | |||||
do_abort = 1; | |||||
} | |||||
} | |||||
break; | |||||
default: | default: | ||||
LOG_ERROR("unknown xsvf command (0x%02X)\n", uc); | LOG_ERROR("unknown xsvf command (0x%02X)\n", uc); | ||||
unsupported = 1; | unsupported = 1; | ||||