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.

USB ISR/Driver on TI C5509a stuck in perpetual USB_EVENT_RESUME loop



Hi,  I have encountered a strange problem with the USB Driver using TI DSP/BIOS CSL libraries running on TI C5509A DSP.

The USB ISR occasionally will be stuck in a perpetual loop handling the USB_EVENT_RESUME event when the USB cable is NOT plugged in to the host.

Here are some more information about the problem:

1)      Electrical interface is standard high speed mode with 3.3V over Rpu = 1.5K on the USB D+ line

2)      The USB driver layer is setup using TI DSP/BIOS CSLs following the reference code in CSL design guide.

3)      If the USB interface is not terminated (i.e. one end of the USB cable connected to USB lines on DSP and the other end loose), occasionally the USB driver will receive a USB_EVENT_RESUME

Event and it will cause the USB ISR handler to enter perpetual loop (enter isr, handle RESUME event, exist isr, enter isr, handle RESUME event, … etc)

 

The first line of code in ISR is to get events from end points and this should be sufficient to clear ALL pending events from these end points.

 

            USB_EVENT_MASK  USB_ctl_events;

            USB_ctl_events = (USB_getEvents(hEp0Out) | USB_getEvents(hEp0In));

hEp0Out and hEp0In are handles for 2 Control end points on USB0. 

The event returned is 8 (USB_EVENT_RESUME)

4)      When DSP is in this USB ISR perpetual loop, if the loose end of the USB cable are plugged in to the host, sub-sequence USB reset due to cable connection will clear this perpetual loop and DSP will behave normally from that point on.

Has anyone seen or heard similar issues ?

 

  • Hi,

    If you can provide us your test code, it'll speed up to look into it.

    Regards,

    Hyun

  • Hyun,

      Below is the code snipet.

      1) During Power up, USB_Init() is called to initialize USB driver module.

      2)  RESUME event occurs and triggers EndPoint handler USB_ctl_handler(), which calls USB_ctl(...)

      3) For normal execution, everything will be fine, and USB_EVENT_RESET, USB_EVENT_RESUME, and USB_EVENT_SUSPEND all handled correctly by USB_ctl()

      4) When the stuck at USB_EVENT_RESUME condition occurs, it will be in and out of USB_ctl() forever because the USB_EVENT_RESUME never clears from the End Point.

           The issue is really at the driver/module level which is TI DSP/BIOS code and the user do not have access to source.

    ===========================================================

    #include <std.h>
    #include <stddef.h>
    #include <csl.h>
    #include <csl_adc.h>
    #include <csl_chip.h>
    #include <csl_dma.h>
    #include <csl_emif.h>
    #include <csl_gpio.h>
    #include <csl_irq.h>
    #include <csl_mcbsp.h>
    #include <csl_mmc.h>
    #include <csl_pll.h>
    #include <csl_pwr.h>
    #include <csl_std.h>
    #include <csl_timer.h>
    #include <csl_usb.h>
    #include <csl_usbhal.h> // this *should be* included by <csl_usb.h>  *sigh*

    USB_EpObj   usbEp0_CntrOut, usbEp0_CntrIn;   // Control Endpoint Objects
    USB_EpObj   usbEp1_IntrOut, usbEp1_IntrIn;   // Interrupt endpoint objects
    USB_EpObj   usbEp2_BulkOut, usbEp2_BulkIn;   // Bulk endpoint objects

    USB_EpHandle  myUsbConfig[] =
    {
     &usbEp0_CntrOut , &usbEp0_CntrIn ,
     &usbEp1_IntrOut , &usbEp1_IntrIn ,
     &usbEp2_BulkOut , &usbEp2_BulkIn ,
     NULL
    };

    unsigned short USB_Init()
    {
        USB_Boolean  usbStatus;
        Uint16       unEventMask;

     USB_setAPIVectorAddress();

     USB_initPLL( TIMING_DSP_INPUT_CLOCK , TIMING_USB_CLOCK , 0 );

        IRQ_clear( IRQ_EVT_USB );

        // initialize endpoint objects

        // init endpoint 0 objects
        // endpoint out0 will respond to following events.
        unEventMask = USB_EVENT_RESET |
            USB_EVENT_SETUP |
            USB_EVENT_SUSPEND |
                     USB_EVENT_RESUME |
                     USB_EVENT_EOT;

        USB_initEndptObj(
         USB0 ,
         &usbEp0_CntrOut ,
      USB_OUT_EP0 ,
      USB_CTRL ,
      0x40 ,
      unEventMask ,
      USB_ctl_handler
     );

        USB_initEndptObj(
         USB0 ,
         &usbEp0_CntrIn ,
         USB_IN_EP0 ,
         USB_CTRL ,
         0x40 ,
         USB_EVENT_EOT ,
         USB_ctl_handler
        );

        // init endpoint1 object - interrupt mode
        USB_initEndptObj(
         USB0,
         &usbEp1_IntrOut,
         USB_OUT_EP1,
         USB_INTR,
         USB_ENDPT_PACKET_SIZE,
      USB_EVENT_EOT,
      NULL // Should be USB_intrOutEvtHandler if USB_evDispatch worked...
     );

     USB_initEndptObj(
      USB0,
      &usbEp1_IntrIn,
         USB_IN_EP1,
         USB_INTR,
         USB_ENDPT_PACKET_SIZE,
      USB_EVENT_EOT,
      NULL // Should be USB_intrInEvtHandler if USB_evDispatch worked...
     );

                // lookup the USB request handler

                fpRequestHandler = USB_lookupReqHandler(Request, USB_ReqTable);

        // init endpoint 2 objects - bulk mode
        USB_initEndptObj(
         USB0,
         &usbEp2_BulkOut,
         USB_OUT_EP2,
         USB_BULK,
      USB_ENDPT_PACKET_SIZE,
      USB_EVENT_EOT,
      NULL // Should be USB_bulkOutEvtHandler if USB_evDispatch worked...
     );

        USB_initEndptObj(
         USB0,
         &usbEp2_BulkIn,
      USB_IN_EP2,
      USB_BULK,
      USB_ENDPT_PACKET_SIZE,
      USB_EVENT_EOT, //|USB_EVENT_RESET,
      NULL // Should be USB_bulkInEvtHandler if USB_evDispatch worked...
     );

        // init USB module - module will assume configuration defined by myUsbConfig[]
        // PSOF is generally used with Isochronus tranfers, which we don't use, so we
        // set the timer to 0 to disable it.
     usbStatus = USB_init( USB0, myUsbConfig, 0 );

     // Point Bulk Data Buffer pointers to inital buffers (used for double buffering
     // USB buffers)
     gpunUsbBulkFillBuff = USB_BulkDataBuffA;
     gpunUsbBulkGetBuff = USB_BulkDataBuffB;

        // if the USB module configured properly,
        // connect it to up stream port
        if( usbStatus )
        {
         USB_connectDev( USB0 );
     }

     USB_ClearTxBuffer();

        /* Clear any pending interrupts for DMA channels */
        IRQ_clear( IRQ_EVT_USB );
        IRQ_enable( IRQ_EVT_USB );

        return 0;

    }   // end of USB_Init

    void USB_ctl(USB_DevNum DevNum, USB_EpHandle hEp0In,USB_EpHandle hEp0Out)
    {
        Uint16  Request;
        E_USB_REQUEST_RET eReqHandlerRet = E_USB_REQUEST_DONE;
        USB_EVENT_MASK  USB_ctl_events;

        // find out the endpt0 event caused this funcion to be called
        // and respond to the events
        USB_ctl_events = (USB_getEvents(hEp0Out) | USB_getEvents(hEp0In));

     // [JYING Comment #1] For Failure Condition, USB_ctl_events = 0x08 (USB_EVENT_RESUME)
        //                    USB_getEvents(hEp0Out) and USB_getEvents(hEp0In) will clear events on READ
        //                    according to the DSP/BIOS guide

        // if the USB reset request received, abort all endpoint activities
        // and reconfigure the USB module
        if(USB_ctl_events & USB_EVENT_RESET)        // USB RESET event received
        {
            USB_abortAllTransaction(DevNum);        // stop all data transfer activities
            usbCurConfigStat = 0x00;                // reset device config number
            USB_init(USB0, myUsbConfig, 0x80);      // reconfig the USB module
        }

        if (USB_ctl_events & USB_EVENT_SUSPEND)     // USB SUSPEND event received
        {
      // Should check if RemoteWakeup is desired
      if ( USB_getRemoteWakeupStat( DevNum ) )
      {
       USB_issueRemoteWakeup( DevNum );
      }
        }

        // if the event is a setup packet received event then read the setup packet,
        // and lookup the USB_ReqTable[] for the appropriate request handler
        if((USB_ctl_events & USB_EVENT_SETUP) == USB_EVENT_SETUP)
        {
      geUSB_State = E_USB_STATE_SETUP;

            // read the setup packet, if something wrong with setup packet then stall
            // the control endpints
            if (USB_getSetupPacket(DevNum, &USB_Setup) == USB_FALSE)
            {
                eReqHandlerRet = E_USB_REQUEST_STALL;
            }
            else
            {
                Request = ((USB_Setup.bmRequestType&0xC0)<<8)|USB_Setup.bRequest;
       // Handle setup packet hereUSB_ctl_handler()
            }
        }   // end of if setup event received

     // [JYING Comment #2] RESUME event requires no special processing so nothing is done except
        //                    clearing the event from EndPoint

        // clear the flags if a new setup packet is received
        if(USB_Setup.New)
        {
            USB_Setup.New = 0;
        }
    }

    void USB_ctl_handler()
    {
        // instead of calling USB_ctl( ) this routine can post a SWI of DSP/BIOS
        // and SWI will in turn call the USB-ctl( )
        USB_ctl(USB0, &usbEp0_CntrIn , &usbEp0_CntrOut);
    }

    void USB_isr()
    {
     Uint16 intf;

     // Call the CSL's function to process other USB commands
        USB_evDispatch( );

     // [JYING Comment #3] USB_evDispatch() will trigger the corrsponding endpoint handler

     asm(" NOP");asm(" NOP");asm(" NOP");

     // check Endpoint OUT Interrupt flags
     intf = USBOEPIF;

     // [JYING Comment #4] When Stuck at RESUME, USBOEPIF is 0

     if( intf != 0 )
     {
      asm(" NOP");
     }

     // check Endpoint OUT Interrupt flags
     intf = USBOEPIF;

     // [JYING Comment #5] When Stuck at RESUME, USBOEPIF is 0

     if( intf != 0 )
     {
      // Handle interrupt ...

      // clear the endpoint interrupt flag
      USBOEPIF |= intf;
     }

     // check Endpoint IN Interrupt flags
     intf = USBIEPIF;

     // [JYING Comment #6] When Stuck at RESUME, USBIEPIF is 0

     if( intf != 0 )
     {
      // Handle interrupt ...

      // clear the endpoint interrupt flag
      USBIEPIF |= intf;
     }
    }

  • Here is the software configuration and TI DSP/BIOS versions that the code was compiled with.

    Code Composer Version:  3.1.0

    Integrated Development:  5.90.0.227

    BIOS : 5.2.0.46 (04-29-2006)

    Code Generation Tools:  v3.2.2