This patch tries to optimize TMS clocks by compacting multiple clocks
into one FT2232 command. This gives us 6% flash program time reduction.
And it gives us more performance improvement for gdbproxy when loading
program via our gnICE and gnICE+ cables. I think this will help other
JTAG cables based on FT2232(H).
But there is one problem I don't know the resolution. What is
post_signals in ft2232.c for? How should I set it for
URJ_TAP_CABLE_CLOCK_COMPACT?
And any comments?
Thanks,
Jie
* 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_schedule_compact): New.
(ft2232_flush): Compact consecutive clocks.
Index: include/urjtag/cable.h
===================================================================
--- include/urjtag/cable.h (revision 1754)
+++ include/urjtag/cable.h (working copy)
@@ -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,
Index: src/tap/cable/generic.c
===================================================================
--- src/tap/cable/generic.c (revision 1754)
+++ src/tap/cable/generic.c (working copy)
@@ -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");
Index: src/tap/cable/ft2232.c
===================================================================
--- src/tap/cable/ft2232.c (revision 1754)
+++ src/tap/cable/ft2232.c (working copy)
@@ -1247,6 +1247,22 @@ ft2232_clock_schedule (urj_cable_t *cabl
static void
+ft2232_clock_schedule_compact (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);
+}
+
+
+static void
ft2232_clock (urj_cable_t *cable, int tms, int tdi, int n)
{
params_t *params = (params_t *) cable->params;
@@ -1619,6 +1635,12 @@ ft2232_flush (urj_cable_t *cable, urj_ca
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++)
{
@@ -1626,12 +1648,68 @@ ft2232_flush (urj_cable_t *cable, urj_ca
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_schedule_compact (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_schedule_compact (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)
@@ -1689,6 +1767,11 @@ ft2232_flush (urj_cable_t *cable, urj_ca
params->last_tdo_valid = last_tdo_valid_finish = 0;
break;
}
+ case URJ_TAP_CABLE_CLOCK_COMPACT:
+ {
+ params->last_tdo_valid = last_tdo_valid_finish = 0;
+ break;
+ }
case URJ_TAP_CABLE_GET_TDO:
{
int tdo;
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
UrJTAG-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/urjtag-development