summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jtag/zy1000/jtag_minidriver.h19
-rw-r--r--src/jtag/zy1000/zy1000.c61
2 files changed, 76 insertions, 4 deletions
diff --git a/src/jtag/zy1000/jtag_minidriver.h b/src/jtag/zy1000/jtag_minidriver.h
index 0f2b46a0..7e13f666 100644
--- a/src/jtag/zy1000/jtag_minidriver.h
+++ b/src/jtag/zy1000/jtag_minidriver.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2007-2009 by Øyvind Harboe *
+ * Copyright (C) 2007-2010 by Øyvind Harboe *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -63,9 +63,16 @@ static __inline__ void zy1000_flush_readqueue(void)
{
/* Not used w/hardware fifo */
}
+static __inline__ void zy1000_flush_callbackqueue(void)
+{
+ /* Not used w/hardware fifo */
+}
#else
extern void waitIdle(void);
void zy1000_flush_readqueue(void);
+void zy1000_flush_callbackqueue(void);
+void zy1000_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0);
#endif
static __inline__ void waitQueue(void)
@@ -228,6 +235,10 @@ static __inline__ void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
}
}
-/* Must flush any read queue before we can invoke callback */
-#define interface_jtag_add_callback(callback, in) {zy1000_flush_readqueue(); callback(in);}
-#define interface_jtag_add_callback4(callback, in, data1, data2, data3) {zy1000_flush_readqueue(); jtag_set_error(callback(in, data1, data2, data3));}
+#if BUILD_ECOSBOARD
+#define interface_jtag_add_callback(callback, in) callback(in)
+#define interface_jtag_add_callback4(callback, in, data1, data2, data3) jtag_set_error(callback(in, data1, data2, data3))
+#else
+#define interface_jtag_add_callback(callback, in) zy1000_jtag_add_callback(callback, in)
+#define interface_jtag_add_callback4(callback, in, data1, data2, data3) zy1000_jtag_add_callback4(callback, in, data1, data2, data3)
+#endif
diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c
index a2b88917..28c65b6e 100644
--- a/src/jtag/zy1000/zy1000.c
+++ b/src/jtag/zy1000/zy1000.c
@@ -468,6 +468,9 @@ int interface_jtag_execute_queue(void)
*/
zy1000_flush_readqueue();
+ /* and handle any callbacks... */
+ zy1000_flush_callbackqueue();
+
if (zy1000_rclk)
{
/* Only check for errors when using RCLK to speed up
@@ -1222,6 +1225,64 @@ void zy1000_flush_readqueue(void)
readqueue_pos = 0;
}
+/* By queuing the callback's we avoid flushing the
+read queue until jtag_execute_queue(). This can
+reduce latency dramatically for cases where
+callbacks are used extensively.
+*/
+#define callbackqueue_size 128
+static struct callbackentry
+{
+ jtag_callback_t callback;
+ jtag_callback_data_t data0;
+ jtag_callback_data_t data1;
+ jtag_callback_data_t data2;
+ jtag_callback_data_t data3;
+} callbackqueue[callbackqueue_size];
+
+static int callbackqueue_pos = 0;
+
+void zy1000_jtag_add_callback4(jtag_callback_t callback, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+ if (callbackqueue_pos >= callbackqueue_size)
+ {
+ zy1000_flush_callbackqueue();
+ }
+
+ callbackqueue[callbackqueue_pos].callback = callback;
+ callbackqueue[callbackqueue_pos].data0 = data0;
+ callbackqueue[callbackqueue_pos].data1 = data1;
+ callbackqueue[callbackqueue_pos].data2 = data2;
+ callbackqueue[callbackqueue_pos].data3 = data3;
+ callbackqueue_pos++;
+}
+
+static int zy1000_jtag_convert_to_callback4(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+ ((jtag_callback1_t)data1)(data0);
+ return ERROR_OK;
+}
+
+void zy1000_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
+{
+ zy1000_jtag_add_callback4(zy1000_jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
+}
+
+void zy1000_flush_callbackqueue(void)
+{
+ /* we have to flush the read queue so we have access to
+ the data the callbacks will use
+ */
+ zy1000_flush_readqueue();
+ int i;
+ for (i = 0; i < callbackqueue_pos; i++)
+ {
+ struct callbackentry *entry = &callbackqueue[i];
+ jtag_set_error(entry->callback(entry->data0, entry->data1, entry->data2, entry->data3));
+ }
+ callbackqueue_pos = 0;
+}
+
static void writeShiftValue(uint8_t *data, int bits)
{
waitIdle();