improve USB Blaster performance and

[ 1980984 ] Wrong TDO sampling in USB Blaster


git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1273 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Arnim Läuger 17 years ago
parent 3137094290
commit db24683939

@ -1,3 +1,10 @@
2008-06-05 Arnim Laeuger <arniml@users.sourceforge.net>
* src/tap/usbconn/libftdi.c: issue device reset in usbconn_ftdi_open(), fixes
hang of FT245 chip when initializing the cable more than once
* src/tap/cable/usbblaster.c: split get_tdo and transfer functions into schedule
finish parts for deeper queueing with extended flush function
2008-06-05 Kolja Waschk <kawk>
* src/bus/bf548_ezkit.c, src/bus/fjmem.c, src/bus/ppc405ep.c,

@ -122,7 +122,7 @@ usbblaster_cable_free( cable_t *cable )
}
static void
usbblaster_clock( cable_t *cable, int tms, int tdi, int n )
usbblaster_clock_schedule( cable_t *cable, int tms, int tdi, int n )
{
params_t *params = (params_t *)cable->params;
cx_cmd_root_t *cmd_root = &(params->cmd_root);
@ -154,20 +154,26 @@ usbblaster_clock( cable_t *cable, int tms, int tdi, int n )
m -= (chunkbytes << 3);
}
cx_xfer( cmd_root, NULL, cable, COMPLETELY );
}
for (i = 0; i < m; i++) {
cx_cmd_queue( cmd_root, 0 );
cx_cmd_push( cmd_root, OTHERS | (0 << TCK) | tms | tdi );
cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | tms | tdi );
cx_xfer( cmd_root, NULL, cable, COMPLETELY );
}
}
static int
usbblaster_get_tdo( cable_t *cable )
static void
usbblaster_clock( cable_t *cable, int tms, int tdi, int n )
{
params_t *params = (params_t *)cable->params;
usbblaster_clock_schedule( cable, tms, tdi, n );
cx_xfer( &(params->cmd_root), NULL, cable, COMPLETELY );
}
static void
usbblaster_get_tdo_schedule( cable_t *cable )
{
params_t *params = (params_t *)cable->params;
cx_cmd_root_t *cmd_root = &(params->cmd_root);
@ -175,31 +181,42 @@ usbblaster_get_tdo( cable_t *cable )
cx_cmd_queue( cmd_root, 1 );
cx_cmd_push( cmd_root, OTHERS ); /* TCK low */
cx_cmd_push( cmd_root, OTHERS | (1 << READ) ); /* TCK low */
cx_xfer( cmd_root, NULL, cable, COMPLETELY );
}
static int
usbblaster_get_tdo_finish( cable_t *cable )
{
#if 0
{
char x = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0;
printf("GetTDO %d\n", x);
return x;
}
char x = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0;
printf("GetTDO %d\n", x);
return x;
#else
return ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0;
#endif
}
static int
usbblaster_get_tdo( cable_t *cable )
{
params_t *params = (params_t *)cable->params;
usbblaster_get_tdo_schedule( cable );
cx_xfer( &(params->cmd_root), NULL, cable, COMPLETELY );
return usbblaster_get_tdo_finish( cable );
}
static int
usbblaster_set_trst( cable_t *cable, int trst )
{
return 1;
}
static int
usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
static void
usbblaster_transfer_schedule( cable_t *cable, int len, char *in, char *out )
{
params_t *params = (params_t *)cable->params;
cx_cmd_root_t *cmd_root = &(params->cmd_root);
int in_offset = 0;
int out_offset = 0;
cx_cmd_queue( cmd_root, 0 );
cx_cmd_push( cmd_root, OTHERS ); /* TCK low */
@ -235,7 +252,34 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
unsigned char b = 0;
for(j=1; j<256; j<<=1) if(in[in_offset++]) b |= j;
cx_cmd_push( cmd_root, b );
};
}
}
while(len > in_offset)
{
char tdi = in[in_offset++] ? 1 : 0;
cx_cmd_queue( cmd_root, out ? 1 : 0 );
cx_cmd_push( cmd_root, OTHERS | (tdi << TDI));/* TCK low */
cx_cmd_push( cmd_root, OTHERS | ((out)?(1 << READ):0) | (1 << TCK) | (tdi << TDI));
}
}
static int
usbblaster_transfer_finish( cable_t *cable, int len, char *out )
{
params_t *params = (params_t *)cable->params;
cx_cmd_root_t *cmd_root = &(params->cmd_root);
int out_offset = 0;
if (out == NULL)
return 0;
while(len - out_offset >= 8)
{
int i;
int chunkbytes = ((len-out_offset)>>3);
if(chunkbytes > 63) chunkbytes = 63;
if(out)
{
@ -250,153 +294,128 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
#endif
for(j=1; j<256; j<<=1) out[out_offset++] = (b & j) ? 1:0;
};
};
};
while(len > in_offset)
{
char tdi = in[in_offset++] ? 1 : 0;
cx_cmd_queue( cmd_root, out ? 1 : 0 );
cx_cmd_push( cmd_root, OTHERS | ((out)?(1 << READ):0) | (tdi << TDI));/* TCK low */
cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | (tdi << TDI));
}
}
}
if(out)
{
cx_xfer( cmd_root, NULL, cable, COMPLETELY );
while(len > out_offset)
out[out_offset++] = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0;
while(len > out_offset)
out[out_offset++] = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0;
#if 0
{
int o;
printf("%d out: ", len);
for(o=0;o<len;o++) printf("%c", out[o]?'1':'0');
printf("\n");
}
#endif
{
int o;
printf("%d out: ", len);
for(o=0;o<len;o++) printf("%c", out[o]?'1':'0');
printf("\n");
}
#endif
return 0;
}
static int
usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
{
params_t *params = (params_t *)cable->params;
usbblaster_transfer_schedule( cable, len, in, out );
cx_xfer( &(params->cmd_root), NULL, cable, COMPLETELY );
return usbblaster_transfer_finish( cable, len, out );
}
static void
usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much )
{
params_t *params = (params_t *)cable->params;
cx_cmd_root_t *cmd_root = &(params->cmd_root);
if( how_much == OPTIONALLY ) return;
if (how_much == OPTIONALLY) return;
if (cable->todo.num_items == 0)
cx_xfer( &(params->cmd_root), NULL, cable, how_much );
while (cable->todo.num_items > 0)
{
int i, j, n, to_send = 0;
int i, j, n;
for(j=i=cable->todo.next_item, n=0; to_send < 64 && n<cable->todo.num_items; n++)
for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items; n++)
{
if(cable->todo.data[i].action == CABLE_TRANSFER) break;
switch(cable->todo.data[i].action)
switch (cable->todo.data[i].action)
{
case CABLE_CLOCK:
{
int tms = cable->todo.data[i].arg.clock.tms ? (1<<TMS) : 0;
int tdi = cable->todo.data[i].arg.clock.tdi ? (1<<TDI) : 0;
int m = cable->todo.data[i].arg.clock.n;
// printf("clock: %d %d %d\n", tms, tdi, m);
for(; m>0; m--)
{
cx_cmd_queue( cmd_root, 0 );
cx_cmd_push( cmd_root, OTHERS | tms | tdi );
cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | tms | tdi );
to_send += 2;
}
break;
}
case CABLE_GET_TDO:
{
cx_cmd_queue( cmd_root, 1 );
cx_cmd_push( cmd_root, OTHERS ); /* TCK low */
cx_cmd_push( cmd_root, OTHERS | (1 << READ) ); /* TCK low */
// printf("get_tdo\n");
to_send += 2;
break;
}
default:
break;
};
case CABLE_CLOCK:
usbblaster_clock_schedule( cable,
cable->todo.data[i].arg.clock.tms,
cable->todo.data[i].arg.clock.tdi,
cable->todo.data[i].arg.clock.n );
break;
case CABLE_GET_TDO:
usbblaster_get_tdo_schedule( cable );
break;
case CABLE_TRANSFER:
usbblaster_transfer_schedule( cable,
cable->todo.data[i].arg.transfer.len,
cable->todo.data[i].arg.transfer.in,
cable->todo.data[i].arg.transfer.out );
break;
default:
break;
}
i++;
if (i >= cable->todo.max_items) i=0;
};
#if 0
if(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER)
{
cx_cmd_push( cmd_root, OTHERS ); /* TCK low */
};
#endif
if(to_send > 0)
{
cx_xfer( cmd_root, NULL, cable, COMPLETELY );
if (i >= cable->todo.max_items)
i = 0;
}
while(j!=i)
cx_xfer( &(params->cmd_root), NULL, cable, how_much );
while (j != i)
{
switch(cable->todo.data[j].action)
switch (cable->todo.data[j].action)
{
case CABLE_GET_TDO:
case CABLE_GET_TDO:
{
int tdo = (cx_xfer_recv( cable ) & (1<<TDO)) ? 1 : 0;
int m = cable_add_queue_item( cable, &(cable->done) );
int m;
m = cable_add_queue_item( cable, &(cable->done) );
cable->done.data[m].action = CABLE_GET_TDO;
cable->done.data[m].arg.value.tdo = tdo;
cable->done.data[m].arg.value.tdo = usbblaster_get_tdo_finish( cable );
break;
}
case CABLE_GET_TRST:
case CABLE_GET_TRST:
{
int m = cable_add_queue_item( cable, &(cable->done) );
cable->done.data[m].action = CABLE_GET_TRST;
cable->done.data[m].arg.value.trst = 1;
break;
}
case CABLE_TRANSFER:
{
int r = usbblaster_transfer_finish( cable,
cable->todo.data[j].arg.transfer.len,
cable->todo.data[j].arg.transfer.out );
free( cable->todo.data[j].arg.transfer.in );
if (cable->todo.data[j].arg.transfer.out)
{
int m = cable_add_queue_item( cable, &(cable->done) );
if (m < 0)
printf("out of memory!\n");
cable->done.data[m].action = CABLE_TRANSFER;
cable->done.data[m].arg.xferred.len = cable->todo.data[j].arg.transfer.len;
cable->done.data[m].arg.xferred.res = r;
cable->done.data[m].arg.xferred.out = cable->todo.data[j].arg.transfer.out;
}
}
default:
break;
};
default:
break;
}
j++;
if (j >= cable->todo.max_items) j=0;
cable->todo.num_items --;
};
while(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER)
{
int r = usbblaster_transfer( cable,
cable->todo.data[i].arg.transfer.len,
cable->todo.data[i].arg.transfer.in,
cable->todo.data[i].arg.transfer.out);
free(cable->todo.data[i].arg.transfer.in);
if(cable->todo.data[i].arg.transfer.out != NULL)
{
int m = cable_add_queue_item( cable, &(cable->done) );
if(m < 0) printf("out of memory!!\n");
cable->done.data[m].action = CABLE_TRANSFER;
cable->done.data[m].arg.xferred.len = cable->todo.data[i].arg.transfer.len;
cable->done.data[m].arg.xferred.res = r;
cable->done.data[m].arg.xferred.out = cable->todo.data[i].arg.transfer.out;
};
i++;
if (i >= cable->todo.max_items) i=0;
cable->todo.num_items --;
};
if (j >= cable->todo.max_items)
j = 0;
cable->todo.num_items--;
}
cable->todo.next_item = i;
}

@ -309,48 +309,6 @@ usbconn_ftdi_common_open( usbconn_t *conn )
/* ---------------------------------------------------------------------- */
static int
usbconn_ftdi_open( usbconn_t *conn )
{
ftdi_param_t *p = conn->params;
struct ftdi_context *fc = p->fc;
int r;
if (usbconn_ftdi_common_open( conn ) < 0)
return -1;
if ((r = ftdi_disable_bitbang( fc )) < 0)
perror( ftdi_get_error_string( fc ) );
if (r >= 0) if ((r = ftdi_set_latency_timer( fc, 2 )) < 0)
perror( ftdi_get_error_string( fc ) );
#if 1
/* libftdi 0.6 doesn't allow high baudrates, so we send the control
message outselves */
if (r >= 0) if (usb_control_msg( fc->usb_dev, 0x40, 3, 1, 0, NULL, 0, fc->usb_write_timeout ) != 0)
{
perror( "Can't set max baud rate.\n" );
r = -1;
}
#else
if (r >= 0) if ((r = ftdi_set_baudrate( fc, 48000000 )) < 0)
perror( ftdi_get_error_string( fc ) );
#endif
if (r < 0)
{
ftdi_usb_close( fc );
ftdi_deinit( fc );
/* mark ftdi layer as not initialized */
p->fc = NULL;
}
return r < 0 ? -1 : 0;
}
/* ---------------------------------------------------------------------- */
#undef LIBFTDI_UNIMPLEMENTED
static int
@ -403,6 +361,53 @@ seq_reset( struct ftdi_context *fc )
return r < 0 ? -1 : 0;
}
/* ---------------------------------------------------------------------- */
static int
usbconn_ftdi_open( usbconn_t *conn )
{
ftdi_param_t *p = conn->params;
struct ftdi_context *fc = p->fc;
int r;
if (usbconn_ftdi_common_open( conn ) < 0)
return -1;
r = seq_reset( fc );
if (r >= 0) r = seq_purge( fc, 1, 0 );
if (r >= 0) if ((r = ftdi_disable_bitbang( fc )) < 0)
perror( ftdi_get_error_string( fc ) );
if (r >= 0) if ((r = ftdi_set_latency_timer( fc, 2 )) < 0)
perror( ftdi_get_error_string( fc ) );
#if 0
/* libftdi 0.6 doesn't allow high baudrates, so we send the control
message outselves */
if (r >= 0) if (usb_control_msg( fc->usb_dev, 0x40, 3, 1, 0, NULL, 0, fc->usb_write_timeout ) != 0)
{
perror( "Can't set max baud rate.\n" );
r = -1;
}
#else
if (r >= 0) if ((r = ftdi_set_baudrate( fc, 3E6 )) < 0)
perror( ftdi_get_error_string( fc ) );
#endif
if (r < 0)
{
ftdi_usb_close( fc );
ftdi_deinit( fc );
/* mark ftdi layer as not initialized */
p->fc = NULL;
}
return r < 0 ? -1 : 0;
}
/* ---------------------------------------------------------------------- */
static int
usbconn_ftdi_mpsse_open( usbconn_t *conn )
{

Loading…
Cancel
Save