Apparently, doing too large read/write I/O on the MPSSE fills up the RX Buffer of the chip, resulting in STALL/NAK of additional transactions of an OUT request. Since the OUT request is issued synchronously, an appropriate IN request cannot be issued, resulting in a deadlock. This problem is handled by submitting small enough OUT requests, that will not fill up the RX buffer and interleaving them with IN requests. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1142 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
2a3ecd0672
commit
a6f4aac8b1
|
@ -7,6 +7,10 @@
|
||||||
error messages. avrftdi_print is changed so that a message is printed when
|
error messages. avrftdi_print is changed so that a message is printed when
|
||||||
the verbosity level is greater or equal the message level, to have always-on
|
the verbosity level is greater or equal the message level, to have always-on
|
||||||
messages.
|
messages.
|
||||||
|
Fix a bug where the RX fifo of the FTDI chip is full, resulting in STALL/NAK
|
||||||
|
of the ongoing OUT request and subsequently timeout, because an IN request
|
||||||
|
cannot be issued due to the synchronous part of libftdi. This should fix
|
||||||
|
#38831 and #38659.
|
||||||
|
|
||||||
2013-04-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
2013-04-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
|
||||||
|
|
||||||
|
|
78
avrftdi.c
78
avrftdi.c
|
@ -95,6 +95,8 @@ typedef struct avrftdi_s {
|
||||||
uint16_t led_mask;
|
uint16_t led_mask;
|
||||||
/* total number of pins supported by a programmer. varies with FTDI chips */
|
/* total number of pins supported by a programmer. varies with FTDI chips */
|
||||||
int pin_limit;
|
int pin_limit;
|
||||||
|
/* internal RX buffer of the device. needed for INOUT transfers */
|
||||||
|
int rx_buffer_size;
|
||||||
} avrftdi_t;
|
} avrftdi_t;
|
||||||
|
|
||||||
static int write_flush(avrftdi_t *);
|
static int write_flush(avrftdi_t *);
|
||||||
|
@ -513,44 +515,65 @@ static int set_led_vfy(struct programmer_t * pgm, int value)
|
||||||
/* Send 'buf_size' bytes from 'cmd' to device and return data from device in
|
/* Send 'buf_size' bytes from 'cmd' to device and return data from device in
|
||||||
* buffer 'data'.
|
* buffer 'data'.
|
||||||
* Write is only performed when mode contains MPSSE_DO_WRITE.
|
* Write is only performed when mode contains MPSSE_DO_WRITE.
|
||||||
* Read is only performed when mode contains MPSSE_DO_READ.
|
* Read is only performed when mode contains MPSSE_DO_WRITE and MPSSE_DO_READ.
|
||||||
*/
|
*/
|
||||||
static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char *cmd,
|
static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char *buf,
|
||||||
unsigned char *data, int buf_size)
|
unsigned char *data, int buf_size)
|
||||||
{
|
{
|
||||||
int k = 0;
|
size_t blocksize;
|
||||||
int n;
|
size_t bsize;
|
||||||
unsigned char buf[4 + buf_size];
|
size_t remaining = buf_size;
|
||||||
|
size_t written = 0;
|
||||||
|
|
||||||
if (mode & MPSSE_DO_WRITE) {
|
unsigned char cmd[3];
|
||||||
buf[0] = mode | MPSSE_WRITE_NEG;
|
// unsigned char si = SEND_IMMEDIATE;
|
||||||
buf[1] = ((buf_size - 1) & 0xff);
|
|
||||||
buf[2] = (((buf_size - 1) >> 8) & 0xff);
|
|
||||||
|
|
||||||
memcpy(buf + 3, cmd, buf_size);
|
cmd[0] = mode | MPSSE_WRITE_NEG;
|
||||||
buf[buf_size + 3] = 0x87;
|
cmd[1] = ((buf_size - 1) & 0xff);
|
||||||
|
cmd[2] = (((buf_size - 1) >> 8) & 0xff);
|
||||||
|
|
||||||
|
//if we are not reading back, we can just write the data out
|
||||||
|
if(!(mode & MPSSE_DO_READ))
|
||||||
|
blocksize = buf_size;
|
||||||
|
else
|
||||||
|
blocksize = pdata->rx_buffer_size;
|
||||||
|
|
||||||
#ifndef DRYRUN
|
#ifndef DRYRUN
|
||||||
E(ftdi_write_data(pdata->ftdic, buf, buf_size + 4) != buf_size + 4, pdata->ftdic);
|
E(ftdi_write_data(pdata->ftdic, cmd, sizeof(cmd)) != sizeof(cmd), pdata->ftdic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while(remaining)
|
||||||
|
{
|
||||||
|
size_t transfer_size = (remaining > blocksize) ? blocksize : remaining;
|
||||||
|
|
||||||
|
#ifndef DRYRUN
|
||||||
|
E(ftdi_write_data(pdata->ftdic, &buf[written], transfer_size) != transfer_size, pdata->ftdic);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
if(remaining < blocksize)
|
||||||
|
E(ftdi_write_data(pdata->ftdic, &si, sizeof(si)) != sizeof(si), pdata->ftdic);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
if (mode & MPSSE_DO_READ) {
|
if (mode & MPSSE_DO_READ) {
|
||||||
memset(buf, 0, sizeof(buf));
|
int n;
|
||||||
|
int k = 0;
|
||||||
do {
|
do {
|
||||||
#ifndef DRYRUN
|
#ifndef DRYRUN
|
||||||
n = ftdi_read_data(pdata->ftdic, buf + k, buf_size - k);
|
n = ftdi_read_data(pdata->ftdic, &data[written + k], transfer_size - k);
|
||||||
E(n < 0, pdata->ftdic);
|
E(n < 0, pdata->ftdic);
|
||||||
#else
|
#else
|
||||||
n = buf_size - k;
|
n = transfer_size - k;
|
||||||
#endif
|
#endif
|
||||||
k += n;
|
k += n;
|
||||||
} while (k < buf_size);
|
} while (k < transfer_size);
|
||||||
|
|
||||||
memcpy(data, buf, buf_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return k;
|
written += transfer_size;
|
||||||
|
remaining -= transfer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_flush(avrftdi_t* pdata)
|
static int write_flush(avrftdi_t* pdata)
|
||||||
|
@ -721,24 +744,33 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
|
||||||
|
|
||||||
/* set pin limit depending on chip type */
|
/* set pin limit depending on chip type */
|
||||||
switch(pdata->ftdic->type) {
|
switch(pdata->ftdic->type) {
|
||||||
#if 0
|
|
||||||
//TODO: issue an error - no MPSSE. hint the user to syncbb?
|
|
||||||
case TYPE_AM:
|
case TYPE_AM:
|
||||||
case TYPE_BM:
|
case TYPE_BM:
|
||||||
case TYPE_R:
|
case TYPE_R:
|
||||||
#endif
|
avrftdi_print(0, "Found unsupported device type AM, BM or R. " \
|
||||||
|
"avrftdi cannot work with your chip. Try the 'synbb' programmer.\n");
|
||||||
case TYPE_2232C:
|
case TYPE_2232C:
|
||||||
pdata->pin_limit = 11;
|
pdata->pin_limit = 11;
|
||||||
|
pdata->rx_buffer_size = 384;
|
||||||
break;
|
break;
|
||||||
case TYPE_2232H:
|
case TYPE_2232H:
|
||||||
|
pdata->pin_limit = 15;
|
||||||
|
pdata->rx_buffer_size = 4096;
|
||||||
|
break;
|
||||||
case TYPE_232H:
|
case TYPE_232H:
|
||||||
pdata->pin_limit = 15;
|
pdata->pin_limit = 15;
|
||||||
|
pdata->rx_buffer_size = 1024;
|
||||||
break;
|
break;
|
||||||
case TYPE_4232H:
|
case TYPE_4232H:
|
||||||
pdata->pin_limit = 7;
|
pdata->pin_limit = 7;
|
||||||
|
pdata->rx_buffer_size = 2048;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//TODO: error/unsupported device
|
avrftdi_print(0, "Found unkown device %x. " \
|
||||||
|
"I will do my best to work with it, but no guarantees ...\n",
|
||||||
|
pdata->ftdic->type);
|
||||||
|
pdata->pin_limit = 7;
|
||||||
|
pdata->rx_buffer_size = pdata->ftdic->max_packet_size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue