Why does fastboot sometimes hang?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why does fastboot sometimes hang?

Jump to solution
2,997 Views
shanegrif
Contributor III

Working with custom hardware, using Android BSP for iMX53 ARD.

I've recently added fastboot to u-boot, in order to program new kernel/system images to SD card via USB.

I've found that fastboot hangs quite frequently. I've got a script that attempts to program 4 images to my SD card, and it never manages to program more than 3 before hanging (usually dies after 2). I have to power-down or unplug my target for the host-side fastboot application to see that something has gone wrong and exit. I've also confirmed that the problem happens when simple fastboot cmds are repeated manually e.g. fastboot getvar version, after just a few iterations.

I also noticed that when I run fastboot devices repeatedly, the response changes after a few iterations:

First few times, I get:

1                    fastboot

Then it changes to:

??????????     fastboot

I tried deleting the host-side fastboot application that gets built as part of the full Android build, and installed the latest fastboot using apt-get, but the results are exactly the same. Looks like some problem with target-side fastboot library, or possibly something going wrong at USB level in u-boot.

Are there any known issues with freescale's target-side fastboot library? Is anybody else using this successfully?

Labels (2)
Tags (1)
0 Kudos
1 Solution
1,704 Views
shanegrif
Contributor III

I spent some time debugging this, and it looks like fastboot is hanging because one of the USB DMA buffers is left in an active state following a non-fatal error during fastboot init.

When I run fastboot on the target, I get the following output:

MX53-ARD-DDR3 U-Boot > fastboot

fastboot is in init......flash target is MMC:0

USB Mini b cable Connected!

fastboot initialized

USB_SUSPEND

USB_RESET

USB_RESET

Invalid string index 238

The "Invalid string index 238" message seems to be normal enough (based on google search), but the error handler in Freescale's implementation stalls USB endpoint 0 and returns early. I changed the code to prevent this from happening, and now fastboot is working reliably. Patch details below:

diff -r 9f3d80b181e5 -r 2d4af89a12a2 bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c

--- a/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c    Fri Jul 11 15:20:44 2014 +0100

+++ b/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c    Mon Jul 14 16:52:36 2014 +0100

@@ -555,49 +555,52 @@

         mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

     }

     if (ep0_recv_setup(ep0_urb)) {

-        mxc_ep0_stall();

-        return;

-    }

-    switch (s->bRequest) {

-    case USB_REQ_GET_STATUS:

-        if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=

-                     (USB_DIR_IN | USB_TYPE_STANDARD))

-            break;

-        ch9getstatus(s->bmRequestType, s->wValue,

-                s->wIndex, s->wLength);

-        return;

-    case USB_REQ_SET_ADDRESS:

-        if (s->bmRequestType != (USB_DIR_OUT |

-                USB_TYPE_STANDARD | USB_RECIP_DEVICE))

-            break;

-        mxc_udc.setaddr = 1;

-        mxc_udc.ep0_dir = USB_DIR_IN;

-        mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

-        usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);

-        return;

-    case USB_REQ_SET_CONFIGURATION:

-        usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);

-    case USB_REQ_CLEAR_FEATURE:

-    case USB_REQ_SET_FEATURE:

-    {

-        int rc = -1;

-        if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==

-                 (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))

-            rc = 0;

-        else if ((s->bmRequestType &

-                (USB_RECIP_MASK | USB_TYPE_MASK)) ==

-                 (USB_RECIP_DEVICE | USB_TYPE_STANDARD))

-            rc = 0;

-        else

-            break;

-        if (rc == 0) {

+        /* Eliminated the stall, as it caused problems for subsequent

+         * fastboot operations. Also restructured code so that tidy-up

+         * still happens. */

+        //mxc_ep0_stall();

+    } else {

+        switch (s->bRequest) {

+        case USB_REQ_GET_STATUS:

+            if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=

+                         (USB_DIR_IN | USB_TYPE_STANDARD))

+                break;

+            ch9getstatus(s->bmRequestType, s->wValue,

+                    s->wIndex, s->wLength);

+            return;

+        case USB_REQ_SET_ADDRESS:

+            if (s->bmRequestType != (USB_DIR_OUT |

+                    USB_TYPE_STANDARD | USB_RECIP_DEVICE))

+                break;

+            mxc_udc.setaddr = 1;

             mxc_udc.ep0_dir = USB_DIR_IN;

             mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

+            usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);

+            return;

+        case USB_REQ_SET_CONFIGURATION:

+            usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);

+        case USB_REQ_CLEAR_FEATURE:

+        case USB_REQ_SET_FEATURE:

+        {

+            int rc = -1;

+            if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==

+                     (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))

+                rc = 0;

+            else if ((s->bmRequestType &

+                    (USB_RECIP_MASK | USB_TYPE_MASK)) ==

+                     (USB_RECIP_DEVICE | USB_TYPE_STANDARD))

+                rc = 0;

+            else

+                break;

+            if (rc == 0) {

+                mxc_udc.ep0_dir = USB_DIR_IN;

+                mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

+            }

+            return;

         }

-        return;

-    }

-    default:

-        break;

+        default:

+            break;

+        }

     }

     if (s->wLength) {

         mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?

View solution in original post

0 Kudos
2 Replies
1,704 Views
shanegrif
Contributor III

Update: I've looked into this some more, and I now believe that the breakdown is happening at USB level, probably nothing to do with fastboot. It doesn't help that fastboot just hangs without timing out, but that seems to be how it behaves.

I added some debug to the host-side fastboot application, and when things go wrong, I'm getting timeout errors on attempting to read the device serial number (USB IOCTL failure).

As our USB interface appears to be working fine after Linux has booted, I am assuming that the problem is somewhere in the u-boot USB code. Any suggestions would be welcome!

0 Kudos
1,705 Views
shanegrif
Contributor III

I spent some time debugging this, and it looks like fastboot is hanging because one of the USB DMA buffers is left in an active state following a non-fatal error during fastboot init.

When I run fastboot on the target, I get the following output:

MX53-ARD-DDR3 U-Boot > fastboot

fastboot is in init......flash target is MMC:0

USB Mini b cable Connected!

fastboot initialized

USB_SUSPEND

USB_RESET

USB_RESET

Invalid string index 238

The "Invalid string index 238" message seems to be normal enough (based on google search), but the error handler in Freescale's implementation stalls USB endpoint 0 and returns early. I changed the code to prevent this from happening, and now fastboot is working reliably. Patch details below:

diff -r 9f3d80b181e5 -r 2d4af89a12a2 bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c

--- a/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c    Fri Jul 11 15:20:44 2014 +0100

+++ b/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c    Mon Jul 14 16:52:36 2014 +0100

@@ -555,49 +555,52 @@

         mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

     }

     if (ep0_recv_setup(ep0_urb)) {

-        mxc_ep0_stall();

-        return;

-    }

-    switch (s->bRequest) {

-    case USB_REQ_GET_STATUS:

-        if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=

-                     (USB_DIR_IN | USB_TYPE_STANDARD))

-            break;

-        ch9getstatus(s->bmRequestType, s->wValue,

-                s->wIndex, s->wLength);

-        return;

-    case USB_REQ_SET_ADDRESS:

-        if (s->bmRequestType != (USB_DIR_OUT |

-                USB_TYPE_STANDARD | USB_RECIP_DEVICE))

-            break;

-        mxc_udc.setaddr = 1;

-        mxc_udc.ep0_dir = USB_DIR_IN;

-        mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

-        usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);

-        return;

-    case USB_REQ_SET_CONFIGURATION:

-        usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);

-    case USB_REQ_CLEAR_FEATURE:

-    case USB_REQ_SET_FEATURE:

-    {

-        int rc = -1;

-        if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==

-                 (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))

-            rc = 0;

-        else if ((s->bmRequestType &

-                (USB_RECIP_MASK | USB_TYPE_MASK)) ==

-                 (USB_RECIP_DEVICE | USB_TYPE_STANDARD))

-            rc = 0;

-        else

-            break;

-        if (rc == 0) {

+        /* Eliminated the stall, as it caused problems for subsequent

+         * fastboot operations. Also restructured code so that tidy-up

+         * still happens. */

+        //mxc_ep0_stall();

+    } else {

+        switch (s->bRequest) {

+        case USB_REQ_GET_STATUS:

+            if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=

+                         (USB_DIR_IN | USB_TYPE_STANDARD))

+                break;

+            ch9getstatus(s->bmRequestType, s->wValue,

+                    s->wIndex, s->wLength);

+            return;

+        case USB_REQ_SET_ADDRESS:

+            if (s->bmRequestType != (USB_DIR_OUT |

+                    USB_TYPE_STANDARD | USB_RECIP_DEVICE))

+                break;

+            mxc_udc.setaddr = 1;

             mxc_udc.ep0_dir = USB_DIR_IN;

             mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

+            usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);

+            return;

+        case USB_REQ_SET_CONFIGURATION:

+            usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);

+        case USB_REQ_CLEAR_FEATURE:

+        case USB_REQ_SET_FEATURE:

+        {

+            int rc = -1;

+            if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==

+                     (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))

+                rc = 0;

+            else if ((s->bmRequestType &

+                    (USB_RECIP_MASK | USB_TYPE_MASK)) ==

+                     (USB_RECIP_DEVICE | USB_TYPE_STANDARD))

+                rc = 0;

+            else

+                break;

+            if (rc == 0) {

+                mxc_udc.ep0_dir = USB_DIR_IN;

+                mxc_udc_queue_update(0, NULL, 0, 0xffffffff);

+            }

+            return;

         }

-        return;

-    }

-    default:

-        break;

+        default:

+            break;

+        }

     }

     if (s->wLength) {

         mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?

0 Kudos