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
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development