This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TivaWare : USB reconnection failure after disconnection in the middle of communication

I develop HID devices on TM4C129x with TivaWare USB library (Ver 2.1.0).
I am troubled by issue of USB re-connection.


When USB cable is disconnected in the middle of data communication, Tiva USB driver is not recognized by Host-PC after that.


The following is the detailed sequence:

  1. Connects my device to Host-PC with a USB cable.
  2. Host-PC recognizes my device as USB HID device.
  3. Starts many control transfer operation from Host-PC to my device.
  4. Disconnects the USB cable in the middle of data transmission directly.
  5. Connects the USB cable from Host-PC to my device again.
  6. Host-PC does NOT recognize my device. (Host-PC reports unknown device error)

   (If USB cable is disconnected after data transmission finished, Host-PC recognizes my device again.)

In Step 5:
TivaWare USB Library catched USB_INTCTRL_RESET, USB_INTEP_0 and some events.
However, USBLib's iEP0state(*) remaining in "eUSBStateRx", therefore EP0 request was not processed and Host-PC did not recognize my device.

(*) "g_psDCDInst[0].iEP0State" in "usbdenum.c".


I think iEP0State should be initialized on USB_INTCTRL_RESET event handler.
However I cannot judge whether it is right fix.

Should I call some usblib's function on my driver's reset handler ?
Or is event handing incomplete?

  • @Tomohiko,

    May I commend you on a most thoughtful, well organized and detailed post?   Simply terrific! 

    I'm bit, "out over my skis" to assist in this area - yet appears you've provided key info - to best enable skilled assistance.

    Tsuneo & Amit (one hopes) will arrive to best guide & assist.   In the interim - you may search the forum for similar posts - perhaps your issue has landed before...

  • Tomohiko Yabui said:
    I think iEP0State should be initialized on USB_INTCTRL_RESET event handler.
    However I cannot judge whether it is right fix.

    Yah, it's the right place to rest the iEP0State to the default, eUSBStateIdle.


    \TivaWare_C_Series-2.1.0.12573\usblib\device\usbdenum.c

    void
    USBDeviceEnumResetHandler(tDCDInstance *pDevInstance)
    {
        ...
        //
        // reset the state variable of Control transfer state machine
        //
        pDevInstance->iEP0State = eUSBStateIdle;
    }


    I examined the state transitions in Control transfer state machine, implemented in USBDeviceEnumHandler() (<-- bad naming, USBDeviceCtrlXferHandler is better)
    This state machine should work well, as long as host would run ordinary sequence of Control transfers. However, this implementation doesn't count in these regular "error recovery" sequence, at all.
    a) Bus reset, in the midst of Control transfer
    b) Early SETUP transaction, to cancel previous Control transfer (**1)

    As of bus reset, above revision would be enough.
    For Early SETUP transaction,
    the USB Device controller of TM4C raises USBCSRL0.SETEND bit, when it receives "early" SETUP transaction in DATA stage. Firmware should clear this bit by USBCSRL0.SETENDC, and reset the iEP0State to eUSBStateIdle.


    (**1) "5.5.5 Control Transfer Data Sequences" in usb_20.pdf
    If a Setup transaction is received by an endpoint before a previously initiated control transfer is completed, the device must abort the current transfer/operation and handle the new control Setup transaction.

    Tsuneo

  • Thank you for detailed examination and advice of other error case. 

    Tsuneo Chinzei said:
    a) Bus reset, in the midst of Control transfer
    b) Early SETUP transaction, to cancel previous Control transfer (**1)

    case a) :

    Thanks for suggestion. I will append the reset sequence  to USBDeviceEnumResetHandler() function.

    case b) :

    I understand cancel case by Early SETUP. I intend to handle "Early SETUP" at the top of USBDeviceEnumHandler() function.  (See below)

    Is confirmation of iEP0State necessary? (Data stage only?)

    void
    USBDeviceEnumHandler(tDCDInstance *pDevInstance)
    {
        uint32_t ui32EPStatus, ui32DataSize;
    
        //
        // Get the end point 0 status.
        //
        ui32EPStatus = MAP_USBEndpointStatus(USB0_BASE, USB_EP_0);
    
        ///// Handle Cancel transaction by Early Setup before DATA_END 
        if( ui32EPStatus & USB_DEV_EP0_SETUP_END )
        {
    		MAP_USBDevEndpointStatusClear(USB0_BASE, USB_EP_0, USB_DEV_EP0_SETUP_END);
    		pDevInstance->iEP0State = eUSBStateIdle;
        }
        /////
    ... }

  • Tomohiko Yabui said:
    case b) :

    I understand cancel case by Early SETUP. I intend to handle "Early SETUP" at the top of USBDeviceEnumHandler() function.  (See below)

    Excellent!!!
    Your fix works very well.
    It was confirmed, as follows,

    Just for debug purpose, a "bug" was introduced at the handler of Get_Descriptor( String )

    usbdenum_mod.c
    
    static void
    USBDEP0StateTx(uint32_t ui32Index)
    {
        ...
        ...
    
        //
        // Save the pointer so that it can be passed to the USBEndpointDataPut()
        // function.
        //
        pui8Data = (uint8_t *)g_psDCDInst[0].pui8EP0Data;
    
    #if 1
    // This section introduces a "bug" intentionally for debug purpose.
    // This "bug" keeps the Control transfer state machine in eUSBStateTx
    // when serial string (3) is requested. This tweak works just once.
    {
    static int debug_just_once = 1;
        tDeviceInfo *psDevice;
        psDevice = g_ppsDevInfo[0];
    
        if ( (pui8Data == psDevice->ppui8StringDescriptors[3]) && debug_just_once) {
            debug_just_once = 0;
            return;
        }
    }
    #endif
    


    Here is the bus trace.
    By this "bug", the device stack failed Get_Descriptor( String:3 ), as we intended.
    Also, it failed following Get_Descriptor( String:0 ), too. As the original stack doesn't reset the state variable, the error was carried over to the next Control transfer.

    By adding your fix, the stack beautifully recovers at the next SETUP transaction. The next Control transfer was successfully handled.

    Tomohiko Yabui said:
    Is confirmation of iEP0State necessary? (Data stage only?)


    Not necessarily.
    The USB engine traces Control transfer sequence by itself. It raises USBCSRL0.SETEND flag just at early SETUP on DATA stage.

    For early SETUP on STATUS stage, the TI's original stack works without problem.

    Tsuneo

  • Thank you for detailed verification to my modification!

    Your test code and test reports are very helpful. 

    I think this problem has been fixed.