I've now typed up and committed a new postprocessing/callback
API that will be used to fix the USB performance regression in svn head.

To recap: USB needs to send large clock out/in commands to avoid
performance deterioration due to long turnaround times.

The solution that was previously used was pretty elegant at
it's core: create a list of callbacks to be executed later to
do the processing. This places the code that sends the JTAG
command and the postprocessing conveniently at the same place.

The problem that I wanted to address was that the precise implementation
caused thousands of lines of code to be added unecessarily to the
calling code and the drivers were made more complicated and
embedded hosts where inefficient. The callback/postprocessing concept
really is quite independant of the JTAG API as such.

The new API completely decouples the postprocessing/callback from
the JTAG commands as such. The new API has been tested & committed,
but is not currently being used(see attached patch). Next I will try to write
a patch to restore the USB performance. I'll then do a bit of testing and
try to get some feedback on that patch.

Even if I write & post that as one giant patch, I'll commit it as numerous
small versions so as to allow bisection in the event that I screw something up.


Example of use:

----
static void arm7flip32(u8 *in)
{
        *((u32 *)in)=flip_u32(le_to_h_u32(in), 32);
}


        fields[0].tap = jtag_info->tap;
        fields[0].num_bits = 1;
        fields[0].out_value = NULL;
        fields[0].in_value = NULL;

        fields[1].tap = jtag_info->tap;
        fields[1].num_bits = 32;
        fields[1].out_value = NULL;
        fields[1].in_value = (u8 *)in;

        jtag_add_dr_scan(2, fields, TAP_INVALID);

        jtag_add_callback(arm7flip32, (u8 *)in);
----


Some comments:

- the callbacks are executed *AFTER* the *ENTIRE* JTAG queue has been
flushed.
- there is another jtag_add_callback3() which I should be able to use
to implement jtag_check_value_mask(), not tested yet.
- the calling code is responsible for providing storage for the "in"
parameter above. This means that no allocation needs to happen
on embedded hosts.
- the callbacks are executed in order
- for embedded hosts where jtag_add_dr_scan() is executed synchronously,
so is jtag_add_callback(). in fact arm7flip32 is inlined in -O3 if
jtag_add_callback()
is implemented as a macro.






-- 
Øyvind Harboe
Embedded software and hardware consulting services
http://consulting.zylin.com
### Eclipse Workspace Patch 1.0
#P openocd
Index: src/target/arm_adi_v5.c
===================================================================
--- src/target/arm_adi_v5.c     (revision 1690)
+++ src/target/arm_adi_v5.c     (working copy)
@@ -99,6 +99,12 @@
        return ERROR_OK;
 }
 
+/* having this in the same file allows inlining for embedded hosts @ -O3 */
+static void adi_le_to_h_u32(u8 *in)
+{
+       *((u32 *)in)=le_to_h_u32(in);
+}
+
 /* Scan out and in from host ordered u32 variables */
 int adi_jtag_dp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, 
u32 outvalue, u32 *invalue, u8 *ack)
 {
@@ -126,11 +132,10 @@
 
        if (invalue)
        {
-               u8 tmp[4];
-               fields[1].in_value = tmp;
-               jtag_add_dr_scan_now(2, fields, TAP_INVALID);
+               fields[1].in_value = (u8 *)invalue;
+               jtag_add_dr_scan(2, fields, TAP_INVALID);
 
-               *invalue=le_to_h_u32(tmp);
+               jtag_add_callback(adi_le_to_h_u32, (u8 *)invalue);
        } else
        {
 
Index: src/target/arm7tdmi.c
===================================================================
--- src/target/arm7tdmi.c       (revision 1690)
+++ src/target/arm7tdmi.c       (working copy)
@@ -175,6 +175,11 @@
        return arm7tdmi_clock_out_inner(jtag_info, out, breakpoint);
 }
 
+static void arm7flip32(u8 *in)
+{
+       *((u32 *)in)=flip_u32(le_to_h_u32(in), 32);
+}
+
 /* clock the target, reading the databus */
 int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
 {
@@ -196,15 +201,11 @@
        fields[1].tap = jtag_info->tap;
        fields[1].num_bits = 32;
        fields[1].out_value = NULL;
-       u8 tmp[4];
-       fields[1].in_value = tmp;
+       fields[1].in_value = (u8 *)in;
 
-       jtag_add_dr_scan_now(2, fields, TAP_INVALID);
+       jtag_add_dr_scan(2, fields, TAP_INVALID);
 
-       if (jtag_error==ERROR_OK)
-       {
-               *in=flip_u32(le_to_h_u32(tmp), 32);
-       }
+       jtag_add_callback(arm7flip32, (u8 *)in);
 
        jtag_add_runtest(0, TAP_INVALID);
 
@@ -258,7 +259,12 @@
                        *((u8 *)in)= readback & 0xff;
                        break;
        }
+}
 
+static int arm7endianness(u8 *in, jtag_callback_data_t size, 
jtag_callback_data_t be)
+{
+       arm_endianness(in, in, (int)size, (int)be, 1);
+       return ERROR_OK;
 }
 
 /* clock the target, and read the databus
@@ -285,12 +291,11 @@
        fields[1].tap = jtag_info->tap;
        fields[1].num_bits = 32;
        fields[1].out_value = NULL;
-       u8 tmp[4];
-       fields[1].in_value = tmp;
+       fields[1].in_value = (u8 *)in;
 
-       jtag_add_dr_scan_now(2, fields, TAP_INVALID);
+       jtag_add_dr_scan(2, fields, TAP_INVALID);
 
-       arm_endianness(tmp, in, size, be, 1);
+       jtag_add_callback3(arm7endianness, in, (jtag_callback_data_t)size, 
(jtag_callback_data_t)be);
 
        jtag_add_runtest(0, TAP_INVALID);
 
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to