Why does fastboot sometimes hang?

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Why does fastboot sometimes hang?

ソリューションへジャンプ
3,003件の閲覧回数
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?

ラベル(2)
タグ(1)
0 件の賞賛
1 解決策
1,710件の閲覧回数
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 件の賞賛
2 返答(返信)
1,710件の閲覧回数
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 件の賞賛
1,711件の閲覧回数
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 件の賞賛