diff --git a/urjtag/ChangeLog b/urjtag/ChangeLog index ddfa3be0..3ec1506d 100644 --- a/urjtag/ChangeLog +++ b/urjtag/ChangeLog @@ -1,3 +1,11 @@ +2010-02-06 Jie Zhang + + * include/urjtag/cable.h (enum action): Add URJ_TAP_CABLE_CLOCK_COMPACT. + * src/tap/cable/generic.c (do_one_queued_action): Handle + URJ_TAP_CABLE_CLOCK_COMPACT to turn off GCC warning. + * src/tap/cable/ft2232.c (ft2232_clock_compact_schedule): New. + (ft2232_flush): Compact consecutive clocks. + 2010-02-05 Mike Frysinger * acinclude.m4 (AS_VAR_APPEND): Fix a few typos. diff --git a/urjtag/include/urjtag/cable.h b/urjtag/include/urjtag/cable.h index 5f8f5da8..0038551f 100644 --- a/urjtag/include/urjtag/cable.h +++ b/urjtag/include/urjtag/cable.h @@ -102,6 +102,7 @@ struct URJ_CABLE_QUEUE enum { URJ_TAP_CABLE_CLOCK, + URJ_TAP_CABLE_CLOCK_COMPACT, URJ_TAP_CABLE_GET_TDO, URJ_TAP_CABLE_TRANSFER, URJ_TAP_CABLE_SET_SIGNAL, diff --git a/urjtag/src/tap/cable/ft2232.c b/urjtag/src/tap/cable/ft2232.c index 69691c60..1eaa88fb 100644 --- a/urjtag/src/tap/cable/ft2232.c +++ b/urjtag/src/tap/cable/ft2232.c @@ -1254,6 +1254,29 @@ ft2232_clock_schedule (urj_cable_t *cable, int tms, int tdi, int n) } +static void +ft2232_clock_compact_schedule (urj_cable_t *cable, int length, uint8_t byte) +{ + params_t *params = (params_t *)cable->params; + urj_tap_cable_cx_cmd_root_t *cmd_root = &(params->cmd_root); + + urj_tap_cable_cx_cmd_queue (cmd_root, 0); + /* Clock Data to TMS/CS Pin (no Read) */ + urj_tap_cable_cx_cmd_push (cmd_root, MPSSE_WRITE_TMS | + MPSSE_LSB | MPSSE_BITMODE | + MPSSE_WRITE_NEG ); + urj_tap_cable_cx_cmd_push (cmd_root, length); + urj_tap_cable_cx_cmd_push (cmd_root, byte); + + params->signals &= ~(URJ_POD_CS_TMS | URJ_POD_CS_TDI | URJ_POD_CS_TCK); + if (byte >> length) + params->signals |= URJ_POD_CS_TMS; + if (byte >> 7) + params->signals |= URJ_POD_CS_TDI; + // if (tck) params->signals |= URJ_POD_CS_TCK; +} + + static void ft2232_clock (urj_cable_t *cable, int tms, int tdi, int n) { @@ -1627,6 +1650,12 @@ ft2232_flush (urj_cable_t *cable, urj_cable_flush_amount_t how_much) int last_tdo_valid_schedule = params->last_tdo_valid; int last_tdo_valid_finish = params->last_tdo_valid; + if (cable->todo.num_items == 1 + && cable->todo.data[cable->todo.next_item].action + == URJ_TAP_CABLE_CLOCK_COMPACT + && how_much != URJ_TAP_CABLE_COMPLETELY) + break; + for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items; n++) { @@ -1634,12 +1663,68 @@ ft2232_flush (urj_cable_t *cable, urj_cable_flush_amount_t how_much) switch (cable->todo.data[i].action) { case URJ_TAP_CABLE_CLOCK: - ft2232_clock_schedule (cable, - cable->todo.data[i].arg.clock.tms, - cable->todo.data[i].arg.clock.tdi, - cable->todo.data[i].arg.clock.n); - last_tdo_valid_schedule = 0; - break; + case URJ_TAP_CABLE_CLOCK_COMPACT: + { + int tdi = cable->todo.data[i].arg.clock.tdi ? 1 << 7 : 0; + int length = 0; + uint8_t byte = 0; + int tms = 0; + int cn = 0; + + if (cable->todo.data[i].action == URJ_TAP_CABLE_CLOCK_COMPACT) + { + length = cable->todo.data[i].arg.clock.n; + byte = cable->todo.data[i].arg.clock.tms; + } + + more_cable_clock: + + if (cable->todo.data[i].action == URJ_TAP_CABLE_CLOCK) + { + tms = cable->todo.data[i].arg.clock.tms ? 1 : 0; + cn = cable->todo.data[i].arg.clock.n; + } + while (cn > 0) + { + byte |= tms << length; + cn--; + length++; + if (length == 7) + { + ft2232_clock_compact_schedule (cable, 6, byte | tdi); + length = 0; + byte = 0; + } + } + if (n + 1 < cable->todo.num_items + && cable->todo.data[(i + 1) % cable->todo.max_items].action == URJ_TAP_CABLE_CLOCK + && (cable->todo.data[(i + 1) % cable->todo.max_items].arg.clock.tdi ? 1 << 7 : 0) == tdi) + { + i++; + if (i >= cable->todo.max_items) + i = 0; + n++; + goto more_cable_clock; + } + if (length) + { + if (n + 1 < cable->todo.num_items + || how_much == URJ_TAP_CABLE_COMPLETELY) + ft2232_clock_compact_schedule (cable, length - 1, byte | tdi); + else + { + cable->todo.data[i].action = URJ_TAP_CABLE_CLOCK_COMPACT; + cable->todo.data[i].arg.clock.tms = byte; + cable->todo.data[i].arg.clock.n = length; + i--; + if (i == -1) + i = cable->todo.max_items; + } + } + + last_tdo_valid_schedule = 0; + break; + } case URJ_TAP_CABLE_GET_TDO: if (!last_tdo_valid_schedule) @@ -1697,6 +1782,20 @@ ft2232_flush (urj_cable_t *cable, urj_cable_flush_amount_t how_much) params->last_tdo_valid = last_tdo_valid_finish = 0; break; } + case URJ_TAP_CABLE_CLOCK_COMPACT: + { + post_signals &= + ~(URJ_POD_CS_TCK | URJ_POD_CS_TDI | URJ_POD_CS_TMS); + post_signals |= + ((cable->todo.data[j].arg.clock. + tms >> cable->todo.data[j].arg.clock. + n) ? URJ_POD_CS_TMS : 0); + post_signals |= + (cable->todo.data[j].arg.clock. + tdi ? URJ_POD_CS_TDI : 0); + params->last_tdo_valid = last_tdo_valid_finish = 0; + break; + } case URJ_TAP_CABLE_GET_TDO: { int tdo; diff --git a/urjtag/src/tap/cable/generic.c b/urjtag/src/tap/cable/generic.c index 2c54bca6..79a13d69 100644 --- a/urjtag/src/tap/cable/generic.c +++ b/urjtag/src/tap/cable/generic.c @@ -177,6 +177,8 @@ do_one_queued_action (urj_cable_t *cable) cable->driver->get_signal (cable, cable->todo.data[i].arg.value.sig); break; + case URJ_TAP_CABLE_CLOCK_COMPACT: /* Turn off GCC warning */ + break; } urj_log (URJ_LOG_LEVEL_DETAIL, "do_one_queued done\n");