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

Reply via email to