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