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.

Handling babble interrupt on TM4C1294

Other Parts Discussed in Thread: TM4C129ENCPDT, EK-TM4C1294XL

Hi,

I'm running usb_host_mouse example on EK-TM1294XL. I added USB hub to the project. I connect a 4-port USB hub to LaunchPad and a USB mouse to the hub. After several (10..100) connect/disconnect of mouse I get babble interrupt. The USB controller seems to resetted and it is in device state. I found an empty 'if' in usbhostenum.c of usblib.

    //
    // Received a reset from the host.
    //
    if(ui32Status & USB_INTCTRL_BABBLE)
    {
    }

What should be done to switch back to host mode?


Regards,

Peter

  • Hello peter

    Handling of Babble Interrupt is not well explained. The general solution is to issue is a bus reset and re-enumerate the device

    Regards
    Amit
  • Is, "Not well explained" almost the same as, "Unexplained?"

    Poster's not the first to encounter/run aground - hopefully this is on (someone's) list...
  • Hello cb1,

    Some explanation like end source clock instability causing bits not to be timed correctly is one of the "not well explained".

    Regards
    Amit
  • Hi Amit,

    Ok, I've added the following lines:
    if(ui32Status & USB_INTCTRL_BABBLE)
    {
    g_sUSBHCD.ui32IntEvents = INT_EVENT_VBUS_ERR;
    }
    It causes to reset the USB0 controller and re-initialize HCD. But the controller stays in device mode and USB bus is remains in suspend. No USB interrupts are generated and the USB_DEVCTL is 0x81 (DEV=1, SESSION=1) when USBOTGSessionRequest() is called. After initialization USB_DEVCTL changes to 0x19 (DEV=0, SESSION=1). What should be done to turn off device mode?

    Regards,
    Peter
  • Hello Peter,

    What needs to be done is to reset the end device as well by forcing the power OFF and ON to the end device for re-enumeration.

    Regards
    Amit
  • Hello Amit,

    I think my last description was ambiguous, sorry.
    After very first initialization the USB_DEVCTL is 0x19 (DEV=0, SESSION=1). When babble occurs USB_DEVCTL changes to 0x80. The USBOTGSessionRequest() is called, so USB_DEVCTL changes to 0x81 (DEV=1, SESSION=1). If unplug/plug the USB device or USB hub many times the situation remains the same: USB_DEVCTL is 0x81, no USB interrupts, USB bus is in suspend. Only resetting of the microcontroller helps.

    Regards,
    Peter
  • Hello Peter,

    OK. Then in this case you do not need to reset the entire uC but just the USB peripheral and restart its initialization.

    Regards
    Amit
  • Hello Amit,

    I am having similar issues to that of Peter’s where the USB switches from host to device. I have actually noticed a couple of threads on e2e with similar issues. I am using a Tiva Tm4c129ENCPDT on a development board which is used as a host only. I tried forcing the USB stack to host only using USBStackModeSet(0,eUSBModeForceHost,0). I also tried placing a hardware watch point on the USB_DEVCTL register and can’t seem to trace when USB_DEVCTL_DEV bit is being set.  I can see the USB_DEVCTL_SESSION bit is being set in the USBOTGSessionRequest. Here are a couple of questions I have:

    -Where is USB_DEVCTL_DEV bit being set?

    -Should the babble interrupt be handled in TI drivers?

    -If the babble interrupt is to be handled by the user, how do you recommend re-initializing the driver and USB stack when sometimes the babble causes us to be stuck in while loop in TI drivers (USBHCDControlTransfer)?

    Thanks,

    Ismail

  • Hello Ismail, Peter,

    I searched the forum for some more data on this.

    e2e.ti.com/.../1366576

    As for the questions
    1. It is done by the USB OTG when it looses the session
    2. No, since we do not know the source of the babble, doing a fixed corrective action may not be always be the case.
    3. To handle it "blindly", the application should check for the babble case and reset the USB peripheral, reconfigure it and then enter the enumeration phase.

    Regards
    Amit
  • Hi Amit,


    The USB peripheral has already resetted this way (case eHCDVBUSError in usbhostneum.c, as babble error sets g_sUSBHCD.ui32IntEvents = INT_EVENT_VBUS_ERR):

                MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);

                //
                // Wait for 100ms before trying to re-power the device.
                //
                OS_DELAY(g_ui32Tickms * 100);

                //
                // Re-initialize the HCD.
                //
                USBHCDInitInternal(0, g_sUSBHCD.pvPool, g_sUSBHCD.ui32PoolSize);

    Is this the correct way to reset the USB controller? I tried to add these lines before resetting:

                MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_USB0);
                OS_DELAY(g_ui32Tickms * 100);
                MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);

    But it does not help: no USB communication, no USB interrupts are generated and the USB_DEVCTL is still 0x81 (DEV=1, SESSION=1).

    Best regards,

    Peter

  • Hello Peter,

    It should be disable-reset-enable.

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_USB0);
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_USB0)
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);

    Regards
    Amit
  • Hello Amit,

    I've tried the above code, but it does not help. And I experienced worrying things: after the babble interrupt occurred I disconnected/connected the USB hub from the development board a few times and the MCU was getting extremely hot in a few seconds. I disconnected the power of development board. What happened?

    Best regards,

    Peter

    Edit: I zipped the edited mouse example and usblib. I uploaded: tiva_ek-tm4c1294xl_usb_host.zip

  • Hello Peter

    Connecting/Disconnecting the USB Hub, may cause the IO Latch Up. This is a known issue and already an errata of GPIO#09 covers the same.

    Also I have not seen a babble interrupt on the development setup, so we may need to see how to get one to occur "reliably".

    Regards
    Amit
  • Amit,


    I was able to recover from the USB being switched to device. I had a higher priority task periodically check the USB_DEVCTL register; once the right conditions were met I would reset the USB peripheral. It seems to be working, however, I am using USBMSCHFatFs and that doesn't seem to fully recover every time. Sometimes I would perform a block read and get stuck in the USBHCDPipeRead while(1) loop. Here is what I do when I detect a babble:


    USBMSCHFatFs_close(usbmschfatfsHandle);
    SysCtlPeripheralDisable(SYSCTL_PERIPH_USB0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_USB0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
    usbmschfatfsParams.servicePriority = 5;
    usbmschfatfsHandle = USBMSCHFatFs_open(USBMSCHFatFs0, 0, &usbmschfatfsParams);
    USBStackModeSet(0,eUSBModeForceHost,0);

    Thanks,

    Ismail

  • Hello Ismail,

    That is one of the good things about the forum is that it is actually a forum of users (minus the occasional give me a project)

    The following post may have the information...
    e2e.ti.com/.../393726

    Regards
    Amit
  • Hi Amit,

    Sometimes 10 connect/disconnect sometimes 100 connect/disconnect needed to get the error. I've got a simple device which can disconnect the 4 wires of USB using a relay. Of course that relay device is not essential, it just makes easier to reproduce the problem.
    The devices are connected this way: EK-TM4C1294XL <- Beagle USB 480 <- USB HUB <- relay device <- USB mouse.

    It looks that type of USB hub is important: the babble error occurs with Trust HU-1240Tp HUB (full speed) and with other noname FS hub.

    Best regards,

    Peter

  • Hello Peter,

    May I suggest adding a cap close to the device on the USB lines. As I mentioned earlier the latch up may be the cause of the high current and device heat up.

    Regards
    Amit
  • Amit,


    I do think e2e is very useful. I think I am coming closer to a solution. I read the link you suggested. They seem to be having similar issues but not quite the same. I don’t have the INT_EVENT_DISCONNECT problem I am mainly stuck in the “interior while loop” only. I have the g_sUSBHCD.psUSBINPipes[ui32PipeIdx].iState = ePipeReadDMA and it is not switching to ePipeDataReady. ui32RemainingBytes is equal to ui32BytesRead. Should I have this question in a different thread?

    Thanks,

    Ismail

  • Hello Ismail,

    You can continue on this thread. There are some threads on the same issue. Use the keyword "USBHCDPipeRead"

    Regards
    Amit
  • Amit,
    I have done that previously. I can't seem to find useful solution. I've noticed a couple of users changed code lines in the TI drivers. I would prefer not going that route.
  • Hello Ismail,

    It is fine to put the lines in the TI drivers and rebuild-reuse the same. The drivers are for user reference and they can modify the same.

    Regards
    Amit
  • Amit,

     The problem is when there is an updated version of the driver I would have to rebuild that aswell. If its an issue I can resolve on the application side that would be better or maybe it is bug and the fix can be included in future driver releases. Either ways I need some direction in figuring out the source of the problem. Why is g_sUSBHCD.psUSBINPipes[ui32PipeIdx].iState not being set to ePipeDataReady.

    Thanks,

    Ismail

  • Hello Ismail,

    The code change for bug fix is already a part of the new release (final phase of testing). In the meantime you can still use the locally updated version to continue the debug.

    Regards
    Amit
  • Thanks Amit. Is there a way to be notified when the update is out?
  • Hello Ismail,

    We are working with Communication to send an update to users who have downloaded the same. Besides that Forum would be notified as well.

    Regards
    Amit
  • Ok. At least I have the device host issue resolved. Thanks
  • Amit,

    I made the changes you suggested and I seem to get stuck in PipeRead instead. Here are the changes I made:



    if(ui32Status & USB_INTCTRL_CONNECT) { // // Set the connect flag and clear disconnect if it happens to be set. // g_sUSBHCD.ui32IntEvents |= INT_EVENT_CONNECT; //g_sUSBHCD.ui32IntEvents &= ~INT_EVENT_DISCONNECT; // // Power the USB bus. // MAP_USBHostPwrEnable(USB0_BASE); }

    if(g_sUSBHCD.ui32IntEvents & (INT_EVENT_DISCONNECT |
    							  INT_EVENT_VBUS_ERR |
    							  INT_EVENT_POWER_FAULT))
    {
    	//
    	// Set the pipe state to error.
    	//
    	g_sUSBHCD.psUSBOUTPipes[ui32PipeIdx].iState = ePipeError;
    
    	//
    	// Needs to be set to exit out of large while loop.
    	//
    	ui32RemainingBytes = 0;
    
    	g_sUSBHCD.ui32IntEvents &= ~INT_EVENT_DISCONNECT;
    
    	break;
    }
    
    

    I reverted the changes and went to my original problem to gather more information. So when I am stuck in the PipeWrite. I notice that 

    g_sUSBHCD.ui32IntEvents is equal to 0x14 which means INT_EVENT_SOF and INT_EVENT_DISCONNECT are set but I never exit the while(1) loop

    I went into the disassembly window and here is what it is showing:

    I am guessing #13 is INT_EVENT_DISCONNECT | INT_EVENT_VBUS_ERR | INT_EVENT_POWER_FAULT

    The value for R1 is 0x10 shouldn't it be 0x14?

    Thanks

  • Hello Ismail,

    #13 is 0xD which is INT_EVENT_DISCONNECT | INT_EVENT_VBUS_ERR | INT_EVENT_POWER_FAULT

    Now r1 shows the value 0x10 but when you check the global variable it shows 0x14. Is that correct?

    Regards
    Amit
  • Yes, that is correct.

  • Hello Ismail,

    Looks to be the fact that the static declaration is the cause in the usbhostenumc. Can you make the structure as volatile?

    Regards
    Amit
  • Ok. I will try that and let you know on monday. Basically I will remove the word static from line 537.
  • Hello Ismail,

    Yes, that is line 537. There would be warnings for recompilation of usblib, but for the moment it is OK to ignore them. Otherwise we have to typecase the static to volatile variable in the function.

    Regards
    Amit
  •  Amit,

    I typecasted the structure as a volatile structure and that seemed to fix the issue. Thank you. Will a fix for this issue be included in the updated driver?

    As I mentioned before there are 2 very similar boards that use the USB functionality one uses the TIVA M4 and the other uses stellaris M3. They both had the same issues with the board switching from host to device and being stuck in either a pipe read or a pipe write. I used a similar fix used in the M4 on the M3 driver and it seemed to work, However, after recovering from the disconnect on the M3 I plug the usb stick back in and when I try to do a write or read I get stuck in the following while loop:

            while(g_sUSBHCD.USBOUTPipes[ulPipeIdx].eState == PIPE_WRITING)
            {
                //
                // Read the status of the endpoint connected to this pipe.
                //
                ulEPStatus = MAP_USBEndpointStatus(USB0_BASE,
                                                   INDEX_TO_USB_EP(ulPipeIdx + 1));
    
                //
                // Check if the device stalled the request.
                //
                if(ulEPStatus & USB_HOST_OUT_STALL)
                {
                    //
                    // If uDMA is being used, then disable the channel.
                    //
                    if(ulPipe & EP_PIPE_USE_UDMA)
                    {
                        MAP_uDMAChannelDisable(UDMA_CHANNEL_USBEP1TX +
                                               (ulPipeIdx * 2));
                    }
                }
    
                //
                // If a disconnect event occurs the exit out of the loop.
                //
                if(g_ulUSBHIntEvents & INT_EVENT_DISCONNECT)
                {
                    //
                    // Set the pipe state to error.
                    //
                    g_sUSBHCD.USBOUTPipes[ulPipeIdx].eState = PIPE_ERROR;
                }
            }

    The g_ulUSBHIntEvents is set to INT_EVENT_SOF. I noticed that in the interrupt handler that I am not able to reach the statement 

               if(g_sUSBHCD.USBOUTPipes[ulIdx].eState == PIPE_WRITING)

    becuase of

            if((g_ulDMAPending == 0) && (ulStatus == 0))
            {
                break;
            }

     Here is the change I made on the M3 to handle disconnect

            if(ulRemainingBytes < 64)
            {
                ulByteToSend = ulRemainingBytes;
            }
            if(g_sUSBHCD.USBOUTPipes[ulPipeIdx].eState == PIPE_ERROR)
            {
                //
                // An error occurred so stop this transaction and set the number
                // of bytes to zero.
                //
            	ulRemainingBytes = 0;
                ulSize = 0;
                break;
            }

    Let me know if I need to clarify anything.

    Thanks

  • Hello Ismail,

    I would need to check if the current test cycle can be interrupted for a fix.

    Also regarding the M3 fix, you had to use the ulRemainingBytes as 0?

    Regards
    Amit
  • Yes. I also had to remove the "else" from the "else if" statment in

    if(g_sUSBHCD.USBOUTPipes[ulPipeIdx].eState == PIPE_ERROR)

    It would never reach it becuase

    if(ulRemainingBytes < 64)

    was always true

  • Hello Ismail,

    Unfortunately we are not making any M3 software release, so the fix would be local to your installation. For TM4C we can try getting it in the next release.

    Regards
    Amit
  • Yes, I understand. I only need help figuring out what the problem is on the M3. Should I ask the question on an M3 thread?
  • Hello Ismail,

    You may want to check the M3 Forum for any such known issues in the software.

    Regards
    Amit
  • Amit,

    I cannot seem to find anything helpful. Should I start a new thread?

    Thanks

  • Amit,

    I tried something in the USB driver on the M3. I added

                    MAP_uDMAChannelDisable(UDMA_CHANNEL_USBEP1TX +
                                           (ulPipeIdx * 2));

     Whenever it detected a disconnect in the pipewrite. I found that this is what happens when there is a pipe stalled event. It seemed to fix the issue. Does this make since?


    I attempted this because I noticed after recovering from the disconnect on the M3 I would get stuck in pipwrite(most of the time) or piperead but this time it was waiting for a status change from the inthandler:

    while(g_sUSBHCD.USBOUTPipes[ulPipeIdx].eState == PIPE_WRITING)

    but there would be no dma transfer pending and the inthandler would not change the status of the pipe.

    Let me know if this needs more clarification

    Thank you for your help

  • Hello,

    I've got another problem. I'm running usb_host_mouse example on EK-TM4C1294XL again. There is a HUB and a FS device connected to the HUB. The FS device can be pendrive, USB serial converter, etc. There is a test script, which connects/disconnets the device for 200 ms, then reconnects. After 2-4 cycles the SETUP packet is sent forever, because it is not ACKed. The interesting thing is that this error can be reproduced with our (HCC Embedded) USB host stack, which has a totally different implementation of TM4C1294's USB driver.

    The test schematic is attached (note: the HUB can be HS or FS hub as well), the test script:

    #!/bin/sh
    for i in `seq 4`; do
      echo "Test #$i..."
      usb_switch_client off
      sleep 1
      usb_switch_client on
      sleep 0.2
      usb_switch_client off
      sleep 0.2
      usb_switch_client on
    done

  • Hi Peter,

    Suggestion 1:

    Peter Ivanov said:
    There is a test script, which connects/disconnets the device for 200 ms, then reconnects.


    Increse the connection/disconnection interval, at least 510ms (255x2),
    so that the host stack could catch the connection change, certainly.

    The host stack polls hub's interrupt IN endpoint (Hub Status) repeatedly.
    When the host stack knows hub status change by this polling, it puts required requests at the stage, GetPortStatus, ClearPortFeature and SetPortFeature.

    In your trace, the host stack seems to poll the interrupt IN (Hub Status) at 255ms.
    - it is known by the first line, "8 IN-NAK: Len(1.78sec)" ----- 1780ms / (8-1) = 254.3ms

    I suppose this interval number derives from the bInterval field of the hub interrupt endpoint descriptor, which is often set to 255 (0xFF: full). The host stack should faithfully follow this interval.

    The second and latter lines of your trace shows three times ClearPortFeature( C_PORT_CONNECTION ). It suggests that the host stack fails to respond to "relatively" quick connection / disconnection change.

    Suggestion 2:
    If you would like to speed up the host stack response, assign shorter interval to the interrupt IN EP than its original bInterval at hub enumeration.

    Although many hubs report full 255ms interval at the interrupt EP descriptor, PC OS used to poll it much quicker. For example, Windows polls it at 32ms, because 32ms is the max interval for the full-speed interrupt EP on Windows.
    USB spec allows shorter interval [**1]

    To assign shorter interval, modify the hub code on the host stack.

    \TivaWare_C_Series-2.1.0.12573\usblib\host\usbhhub.c
    
    static void *
    HubDriverOpen(tUSBHostDevice *psDevice)
    {
    
    line 702:   USBHCDPipeConfig(g_sRootHub.ui32IntInPipe,
                                 psEndpointDescriptor->wMaxPacketSize,
                                 psEndpointDescriptor->bInterval,        // <--------
                                 psEndpointDescriptor->bEndpointAddress &
                                 USB_EP_DESC_NUM_M);

    In above original code, USBHCDPipeConfig() takes the endpoint bInterval (psEndpointDescriptor->bInterval) directly.
    Chenge this line, for example,

    #define HUB_MAX_POLLING_RATE  32
    (psEndpointDescriptor->bInterval < HUB_MAX_POLLING_RATE) ? psEndpointDescriptor->bInterval : HUB_MAX_POLLING_RATE,


    [**1]
    5.7.4 Interrupt Transfer Bus Access Constraints (usb_20.pdf)
    An endpoint for an interrupt pipe specifies its desired bus access period. A full-speed endpoint can specify a desired period from 1 ms to 255 ms. ... The USB System Software will use this information during configuration to determine a period that can be sustained. The period provided by the system may be shorter than that desired by the device up to the shortest period defined by the USB (125 us microframe or 1 ms frame). The client software and device can depend only on the fact that the host will ensure that the time duration between two transaction attempts with the endpoint will be no longer than the desired period.

    Tsuneo