Skip to content

Commit 9e06f3e

Browse files
committed
esp_usb_jtag: Re-enumerates device in case of data transfer problem
1 parent dbdfdfb commit 9e06f3e

File tree

2 files changed

+176
-22
lines changed

2 files changed

+176
-22
lines changed

src/jtag/drivers/esp_usb_jtag.c

Lines changed: 149 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ struct jtag_proto_caps_speed_apb {
190190
*to be read, we have multiple buffers to store those before the bitq interface reads them out. */
191191
#define IN_BUF_CT 8
192192

193+
/*
194+
* comment from libusb:
195+
* As per the USB 3.0 specs, the current maximum limit for the depth is 7.
196+
*/
197+
#define MAX_USB_PORTS 7
198+
193199
/*Private data */
194200
struct esp_usb_jtag {
195201
struct jtag_libusb_device_handle *usb_device;
@@ -234,6 +240,9 @@ static struct esp_usb_jtag *priv= &esp_usb_jtag_priv;
234240
const char *cmds_string[]= {"000", "001", "010", "011", "100", "101", "110", "111",
235241
"srst0", "srst1", "flush", "rsv", "rep0", "rep1", "rep2", "rep3"};
236242

243+
static int esp_usb_jtag_init(void);
244+
static int esp_usb_jtag_quit(void);
245+
237246
static void log_cmds(uint8_t *buf, int ct, int wr)
238247
{
239248
fprintf(priv->logfile, "Wrote %d of %d bytes:%s\n", wr, ct, wr != ct ? "***ERROR***" : "");
@@ -269,6 +278,90 @@ static void log_resp(uint8_t *buf, int ct, int recvd)
269278
fflush(priv->logfile);
270279
}
271280

281+
static bool esp_usb_jtag_libusb_location_equal(libusb_device *dev1, libusb_device *dev2)
282+
{
283+
if (libusb_get_bus_number(dev1) != libusb_get_bus_number(dev2))
284+
return false;
285+
286+
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
287+
uint8_t port_path1[MAX_USB_PORTS], port_path2[MAX_USB_PORTS];
288+
289+
int path_len1 = libusb_get_port_numbers(dev1, port_path1, MAX_USB_PORTS);
290+
if (path_len1 == LIBUSB_ERROR_OVERFLOW) {
291+
LOG_WARNING("cannot determine path to usb device! (more than %i ports in path)\n",
292+
MAX_USB_PORTS);
293+
return false;
294+
}
295+
296+
int path_len2 = libusb_get_port_numbers(dev2, port_path2, MAX_USB_PORTS);
297+
if (path_len2 == LIBUSB_ERROR_OVERFLOW) {
298+
LOG_WARNING("cannot determine path to usb device! (more than %i ports in path)\n",
299+
MAX_USB_PORTS);
300+
return false;
301+
}
302+
303+
if (path_len1 != path_len2)
304+
return false;
305+
306+
for (int i = 0; i < path_len1; i++) {
307+
if (port_path1[i] != port_path2[i])
308+
return false;
309+
}
310+
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
311+
if (libusb_get_device_address(dev1) != libusb_get_device_address(dev2))
312+
return false;
313+
return true;
314+
}
315+
316+
static int esp_usb_jtag_revive_device(struct jtag_libusb_device_handle *usb_device)
317+
{
318+
const uint16_t vids[]= {USB_VID, 0}; /* must be null terminated */
319+
const uint16_t pids[]= {USB_PID, 0}; /* must be null terminated */
320+
libusb_device *cur_dev = libusb_get_device(usb_device);
321+
libusb_device *new_dev = NULL;
322+
int ret, tries = 5;
323+
324+
while (tries-- >= 0) {
325+
new_dev = jtag_libusb_find_device(vids, pids, esp_usb_jtag_serial);
326+
if (new_dev) {
327+
if (esp_usb_jtag_libusb_location_equal(cur_dev, new_dev)) {
328+
/* device is still at the same location on bus and with the same address,
329+
try to reset it */
330+
int rc = jtag_libusb_reset_device(usb_device);
331+
if (rc == LIBUSB_ERROR_NOT_FOUND || rc == LIBUSB_ERROR_NO_DEVICE) {
332+
/* re-enumeration is necessary */
333+
break;
334+
}
335+
libusb_unref_device(new_dev);
336+
return rc == 0 ? ERROR_OK : ERROR_WAIT;
337+
}
338+
break;
339+
}
340+
jtag_sleep(100000);
341+
}
342+
if (new_dev == NULL) {
343+
LOG_ERROR("esp_usb_jtag: device not found!");
344+
return ERROR_FAIL;
345+
}
346+
libusb_unref_device(new_dev);
347+
ret = esp_usb_jtag_quit();
348+
if (ret != ERROR_OK) {
349+
LOG_ERROR("esp_usb_jtag: failed to deinit (%d)", ret);
350+
return ret;
351+
}
352+
tries = 5;
353+
while (tries-- >= 0) {
354+
ret = esp_usb_jtag_init();
355+
if (ret == ERROR_OK)
356+
break;
357+
jtag_sleep(100000);
358+
}
359+
if (ret != ERROR_OK) {
360+
LOG_ERROR("esp_usb_jtag: failed to init (%d)", ret);
361+
return ret;
362+
}
363+
return ERROR_OK;
364+
}
272365

273366
/*Try to receive from USB endpoint into the current priv->in_buf */
274367
static int esp_usb_jtag_recv_buf(void)
@@ -328,6 +421,7 @@ static int esp_usb_jtag_send_buf(void)
328421
{
329422
size_t ct= priv->out_buf_pos_nibbles/2;
330423
size_t n= 0;
424+
331425
n= jtag_libusb_bulk_write(priv->usb_device,
332426
priv->write_ep,
333427
((char *)priv->out_buf),
@@ -337,7 +431,12 @@ static int esp_usb_jtag_send_buf(void)
337431
if (priv->logfile)
338432
log_cmds(priv->out_buf, ct, n);
339433
if (n != ct) {
340-
LOG_ERROR("esp_usb_jtag: usb sent only %d out of %d bytes.", (int)n, (int)ct);
434+
LOG_WARNING("esp_usb_jtag: usb sent only %d out of %d bytes.", (int)n, (int)ct);
435+
int ret = esp_usb_jtag_reenum_device(priv->usb_device);
436+
if (ret != ERROR_OK) {
437+
LOG_ERROR("esp_usb_jtag: failed to re-enum USB device!");
438+
return ret;
439+
}
341440
return ERROR_FAIL;
342441
}
343442
priv->out_buf_pos_nibbles= 0;
@@ -354,59 +453,80 @@ static int esp_usb_jtag_send_buf(void)
354453

355454
/*Simply adds a command to the buffer. Is called by the RLE encoding mechanism.
356455
*Also sends the intermediate buffer if there's enough to go into one USB packet. */
357-
static void esp_usb_jtag_command_add_raw(int cmd)
456+
static int esp_usb_jtag_command_add_raw(int cmd)
358457
{
458+
int ret;
459+
359460
if ((priv->out_buf_pos_nibbles & 1) == 0)
360461
priv->out_buf[priv->out_buf_pos_nibbles/2] = (cmd<<4);
361462
else
362463
priv->out_buf[priv->out_buf_pos_nibbles/2] |= cmd;
363464
priv->out_buf_pos_nibbles++;
364465

365-
if (priv->out_buf_pos_nibbles == OUT_BUF_SZ*2)
366-
esp_usb_jtag_send_buf();
466+
if (priv->out_buf_pos_nibbles == OUT_BUF_SZ*2) {
467+
ret = esp_usb_jtag_send_buf();
468+
if (ret != ERROR_OK)
469+
return ret;
470+
}
367471
if (priv->out_buf_pos_nibbles%(OUT_EP_SZ*2) == 0) {
368-
if (priv->pending_in_bits > (IN_BUF_SZ + priv->hw_in_fifo_len - 1) * 8)
369-
esp_usb_jtag_send_buf();
472+
if (priv->pending_in_bits > (IN_BUF_SZ + priv->hw_in_fifo_len - 1) * 8) {
473+
ret = esp_usb_jtag_send_buf();
474+
if (ret != ERROR_OK)
475+
return ret;
476+
}
370477
}
478+
return ERROR_OK;
371479
}
372480

373481
/*Writes a command stream equivalent to writing `cmd` `ct` times. */
374-
static void esp_usb_jtag_write_rlestream(int cmd, int ct)
482+
static int esp_usb_jtag_write_rlestream(int cmd, int ct)
375483
{
484+
int ret;
376485
/*Special case: stacking flush commands does not make sense (and may not make the hardware
377486
* very happy) */
378487
if (cmd == CMD_FLUSH)
379488
ct= 1;
380489
/*Output previous command and repeat commands */
381-
esp_usb_jtag_command_add_raw(cmd);
490+
ret = esp_usb_jtag_command_add_raw(cmd);
491+
if (ret != ERROR_OK)
492+
return ret;
382493
ct--; /*as the previous line already executes the command one time */
383494
while (ct > 0) {
384-
esp_usb_jtag_command_add_raw(CMD_REP(ct&3));
495+
ret = esp_usb_jtag_command_add_raw(CMD_REP(ct&3));
496+
if (ret != ERROR_OK)
497+
return ret;
385498
ct>>= 2;
386499
}
500+
return ERROR_OK;
387501
}
388502

389503

390504
/*Adds a command to the buffer of things to be sent. Transparently handles RLE compression using
391505
*the CMD_REP_x commands */
392-
static void esp_usb_jtag_command_add(int cmd)
506+
static int esp_usb_jtag_command_add(int cmd)
393507
{
394508
if (cmd == priv->prev_cmd && priv->prev_cmd_repct < CMD_REP_MAX_REPS)
395509
priv->prev_cmd_repct++;
396510
else {
397511
/*We can now write out the previous command plus repeat count. */
398-
if (priv->prev_cmd_repct)
399-
esp_usb_jtag_write_rlestream(priv->prev_cmd, priv->prev_cmd_repct);
512+
if (priv->prev_cmd_repct) {
513+
int ret = esp_usb_jtag_write_rlestream(priv->prev_cmd, priv->prev_cmd_repct);
514+
if (ret != ERROR_OK)
515+
return ret;
516+
}
400517
/*Ready for new command. */
401518
priv->prev_cmd= cmd;
402519
priv->prev_cmd_repct= 1;
403520
}
521+
return ERROR_OK;
404522
}
405523

406524
/*Called by bitq interface to output a bit on tdi and perhaps read a bit from tdo */
407525
static int esp_usb_jtag_out(int tms, int tdi, int tdo_req)
408526
{
409-
esp_usb_jtag_command_add(CMD_CLK(tdo_req, tdi, tms));
527+
int ret = esp_usb_jtag_command_add(CMD_CLK(tdo_req, tdi, tms));
528+
if (ret != ERROR_OK)
529+
return ret;
410530
if (tdo_req)
411531
priv->pending_in_bits++;
412532
return ERROR_OK;
@@ -415,22 +535,30 @@ static int esp_usb_jtag_out(int tms, int tdi, int tdo_req)
415535
/*Called by bitq interface to flush all output commands and get returned data ready to read */
416536
static int esp_usb_jtag_flush(void)
417537
{
538+
int ret;
418539
/*Make sure last command is written */
419-
if (priv->prev_cmd_repct)
420-
esp_usb_jtag_write_rlestream(priv->prev_cmd, priv->prev_cmd_repct);
540+
if (priv->prev_cmd_repct) {
541+
ret = esp_usb_jtag_write_rlestream(priv->prev_cmd, priv->prev_cmd_repct);
542+
if (ret != ERROR_OK)
543+
return ret;
544+
}
421545
priv->prev_cmd_repct= 0;
422546
/*Flush in buffer */
423-
esp_usb_jtag_command_add_raw(CMD_FLUSH);
547+
ret = esp_usb_jtag_command_add_raw(CMD_FLUSH);
548+
if (ret != ERROR_OK)
549+
return ret;
424550
/*Make sure we have an even amount of commands, as we can't write a nibble by itself. */
425551
if (priv->out_buf_pos_nibbles & 1) {
426552
/*If not, pad with an extra FLUSH */
427-
esp_usb_jtag_command_add_raw(CMD_FLUSH);
553+
ret = esp_usb_jtag_command_add_raw(CMD_FLUSH);
554+
if (ret != ERROR_OK)
555+
return ret;
428556
}
429557
LOG_DEBUG_IO("esp_usb_jtag: Flush!");
430558
/*Send off the buffer. */
431-
int r= esp_usb_jtag_send_buf();
432-
if (r != ERROR_OK)
433-
return r;
559+
ret = esp_usb_jtag_send_buf();
560+
if (ret != ERROR_OK)
561+
return ret;
434562

435563
/*Immediately fetch the response bits. */
436564
while (priv->pending_in_bits > 0) {
@@ -456,8 +584,7 @@ static int esp_usb_jtag_reset(int trst, int srst)
456584
/*ToDo: handle trst using setup commands. Kind-of superfluous, however, as we can also do */
457585
/*a tap reser using tms, and it's also not implemented on other ESP32 chips with external
458586
* JTAG. */
459-
esp_usb_jtag_command_add(CMD_RST(srst));
460-
return ERROR_OK;
587+
return esp_usb_jtag_command_add(CMD_RST(srst));
461588
}
462589

463590
/*Called by bitq to see if the IN data already is returned to the host. */

src/jtag/drivers/libusb1_common.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,33 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in
9898
return matched;
9999
}
100100

101+
libusb_device *jtag_libusb_find_device(const uint16_t vids[], const uint16_t pids[])
102+
{
103+
libusb_device **devices, *found_dev = NULL;
104+
105+
int cnt = libusb_get_device_list(jtag_libusb_context, &devices);
106+
107+
for (int idx = 0; idx < cnt; idx++) {
108+
struct libusb_device_descriptor dev_desc;
109+
110+
if (libusb_get_device_descriptor(devices[idx], &dev_desc) != 0)
111+
continue;
112+
113+
if (jtag_libusb_match(&dev_desc, vids, pids)) {
114+
LOG_DEBUG("USB dev found %x:%x @ %d:%d-%d", dev_desc.idVendor, dev_desc.idProduct,
115+
libusb_get_bus_number(devices[idx]),
116+
libusb_get_port_number(devices[idx]),
117+
libusb_get_device_address(devices[idx]));
118+
found_dev = devices[idx];
119+
libusb_ref_device(found_dev);
120+
break;
121+
}
122+
}
123+
if (cnt >= 0)
124+
libusb_free_device_list(devices, 1);
125+
return found_dev;
126+
}
127+
101128
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
102129
const char *serial,
103130
struct jtag_libusb_device_handle **out)

0 commit comments

Comments
 (0)