Implement the new TMS_SEQ command on FT2232 hardware, and remove its now un-needed pathmove() support. This is a net minor code shrink in this driver, combined with the feature addition.
Also, swap a bogus exit() call with a clean failure return. --- src/jtag/drivers/ft2232.c | 133 +++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 75 deletions(-) --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -767,64 +767,6 @@ static int ft2232_send_and_recv(struct j return retval; } -/** - * Function ft2232_add_pathmove - * moves the TAP controller from the current state to a new state through the - * given path, where path is an array of tap_state_t's. - * - * @param path is an array of tap_stat_t which gives the states to traverse through - * ending with the last state at path[num_states-1] - * @param num_states is the count of state steps to move through - */ -static void ft2232_add_pathmove(tap_state_t* path, int num_states) -{ - int state_count = 0; - - assert((unsigned) num_states <= 32u); /* tms_bits only holds 32 bits */ - - DEBUG_JTAG_IO("-"); - - /* this loop verifies that the path is legal and logs each state in the path */ - while (num_states) - { - unsigned char tms_byte = 0; /* zero this on each MPSSE batch */ - int bit_count = 0; - int num_states_batch = num_states > 7 ? 7 : num_states; - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* number of states remaining */ - buffer_write(num_states_batch - 1); - - while (num_states_batch--) { - /* either TMS=0 or TMS=1 must work ... */ - if (tap_state_transition(tap_get_state(), false) - == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x0); - else if (tap_state_transition(tap_get_state(), true) - == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x1); - - /* ... or else the caller goofed BADLY */ - else { - LOG_ERROR("BUG: %s -> %s isn't a valid " - "TAP state transition", - tap_state_name(tap_get_state()), - tap_state_name(path[state_count])); - exit(-1); - } - - tap_set_state(path[state_count]); - state_count++; - num_states--; - } - - buffer_write(tms_byte); - } - tap_set_end_state(tap_get_state()); -} - static void ft2232_add_scan(bool ir_scan, enum scan_type type, uint8_t* buffer, int scan_size) { int num_bytes = (scan_size + 7) / 8; @@ -1618,22 +1560,23 @@ static int ft2232_execute_statemove(stru return retval; } -static int ft2232_execute_pathmove(struct jtag_command *cmd) +/** + * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG + * (or SWD) state machine. + */ +static int ft2232_execute_tms(struct jtag_command *cmd) { - int predicted_size = 0; - int retval = ERROR_OK; - - tap_state_t* path = cmd->cmd.pathmove->path; - int num_states = cmd->cmd.pathmove->num_states; + int retval = ERROR_OK; + unsigned num_bits = cmd->cmd.tms->num_bits; + uint8_t *bits = cmd->cmd.tms->bits; + unsigned count; - DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states, - tap_state_name(tap_get_state()), - tap_state_name(path[num_states-1])); + LOG_INFO("TMS: %d bits", num_bits); +// DEBUG_JTAG_IO("TMS: %d bits", num_bits); /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3 * DIV_ROUND_UP(num_states, 7); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) - { + count = 3 * DIV_ROUND_UP(num_bits, 4); + if (ft2232_buffer_size + count + 1 > FT2232_BUFFER_SIZE) { if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) retval = ERROR_JTAG_QUEUE_FAILED; @@ -1641,9 +1584,46 @@ static int ft2232_execute_pathmove(struc first_unsent = cmd; } - ft2232_add_pathmove(path, num_states); - require_send = 1; + /* Shift out in batches of at most 6 bits; there's a report of an + * FT2232 bug in this area, where shifting exactly 7 bits can make + * problems with TMS signaling for the last clock cycle: + * + * http://developer.intra2net.com/mailarchive/html/ + * libftdi/2009/msg00292.html + * + * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)" + * + * Note that pathmoves in JTAG are not often seven bits, so that + * isn't a particularly likely situation outside of "special" + * signaling such as switching between JTAG and SWD modes. + */ + while (num_bits) { + if (num_bits <= 6) { + buffer_write(0x4b); + buffer_write(num_bits - 1); + buffer_write(*bits & 0x3f); + break; + } + /* Yes, this is lazy ... we COULD shift out more data + * bits per operation, but this is easier and th + */ + buffer_write(0x4b); + buffer_write(3); + buffer_write(*bits & 0xf); + num_bits -= 4; + + count = (num_bits > 4) ? 4 : num_bits; + + buffer_write(0x4b); + buffer_write(count - 1); + buffer_write((*bits >> 4) & 0xf); + num_bits -= count; + + bits++; + } + + require_send = 1; return retval; } @@ -1770,20 +1750,22 @@ static int ft2232_execute_stableclocks(s static int ft2232_execute_command(struct jtag_command *cmd) { int retval; - retval = ERROR_OK; switch (cmd->type) { case JTAG_RESET: retval = ft2232_execute_reset(cmd); break; case JTAG_RUNTEST: retval = ft2232_execute_runtest(cmd); break; case JTAG_STATEMOVE: retval = ft2232_execute_statemove(cmd); break; - case JTAG_PATHMOVE: retval = ft2232_execute_pathmove(cmd); break; case JTAG_SCAN: retval = ft2232_execute_scan(cmd); break; case JTAG_SLEEP: retval = ft2232_execute_sleep(cmd); break; case JTAG_STABLECLOCKS: retval = ft2232_execute_stableclocks(cmd); break; + case JTAG_TMS: + retval = ft2232_execute_tms(cmd); + break; default: LOG_ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); + retval = ERROR_JTAG_QUEUE_FAILED; + break; } return retval; } @@ -4045,6 +4027,7 @@ static const struct command_registration struct jtag_interface ft2232_interface = { .name = "ft2232", + .supported = DEBUG_CAP_TMS_SEQ, .commands = ft2232_command_handlers, .init = ft2232_init, _______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development