From 9324e6280edfda501d1cf52e5d46b1c4aa083935 Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 9 Jan 2009 07:42:45 +0000 Subject: Dick Hollenbeck 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 --- src/jtag/bitbang.c | 37 +++++++++++++++--- src/jtag/dummy.c | 41 +++++++++++++++++--- src/jtag/ft2232.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++----- src/jtag/jtag.c | 63 +++++++++++++++++++++--------- src/jtag/jtag.h | 22 ++++++++++- 5 files changed, 234 insertions(+), 39 deletions(-) (limited to 'src/jtag') diff --git a/src/jtag/bitbang.c b/src/jtag/bitbang.c index 2d04e108..e4191d14 100644 --- a/src/jtag/bitbang.c +++ b/src/jtag/bitbang.c @@ -37,6 +37,10 @@ #include #include + +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); diff --git a/src/jtag/dummy.c b/src/jtag/dummy.c index bfdf0dcc..434a28de 100644 --- a/src/jtag/dummy.c +++ b/src/jtag/dummy.c @@ -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) diff --git a/src/jtag/ft2232.c b/src/jtag/ft2232.c index ad5e6378..c6125025 100644 --- a/src/jtag/ft2232.c +++ b/src/jtag/ft2232.c @@ -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; +} + diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c index a2af3d89..a0cdf014 100644 --- a/src/jtag/jtag.c +++ b/src/jtag/jtag.c @@ -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 diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 82fa061b..cc3c9f0a 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -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 -- cgit v1.2.3