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.

TM4C1294KCPDT: Disabled USB0 analog VBUS/ID pins

Guru 55883 points
Part Number: TM4C1294KCPDT

There seem to be conditions when external un-configured analog VBUS, ID pins register control via USBGPCS can randomly change back to POR state in USBLIB control of them.

Does Tivaware USB library randomly check status of USBGPCS 0x41C to determine host connected end points are indeed still connected?

It would seem VBUS, ID pins being un-configured and forced HIGH via USBGPCS can arbitrarily revoke pins enable status if not being refreshed in some consistent time frame. Likewise GPIO enabled analog VBUS, ID pins seem to have less frequent client endpoint disconnects but they do randomly occur as well. It would seem USB0 clock control and register reads are not without pitfalls relative to other peripherals that occupy the AHB bus at the very same time. 

Point is the AHB timing of USB0 and register reads of USBGPCS randomly exhibit evidence (errata) of skipping CPU ticks when several other NVIC interrupt sources (consistently) occupy the AHB. That is the most logical deduction that can be concluded in the erratic behavior of USB0 endpoints being randomly disconnected for no good reason. We happen to link high PWM peripheral active with NVIC and application execution (CPU) being highly suspect in AHB timing issues relative to USB library calls refreshing status from the bits being set in USBGPCS register.

  • Hi BP101,

    Are you referring to the USB#03 errata or please clarify which errata you are referring to? The USB#03 is only applicable to silicon revision 1 which I'm afraid is not applicable to your units. This errata can affect the non-USB register read after accessing the USBPC. This errata does not affect the reading of the USBPC register.

    Can you setup a watchpoint for any writes to the USBGPCS register if you suspect that the register is changed by the USBLIB inadvertently.
  • Hi Charles,

    It would seem USBGPCS is not changing per say as the target interface link into PC (CDC) remains connected after client posts an exception. The bulk device client exception reports an error occurred in the RX pipe after perhaps disconnecting the endpoint?

    The USB tick timer call to 7 established endpoints seemingly fails to scan USBGPCS register during missed tick cycles.  So tick timer thinks the client initiated an endpoint disconnect when it did not. Typically USB endpoints teardown of remote pipes would occur had the USB cable been unplugged from target or host. The debug watch USB0 connection status (UARRTprintf()) never reports disconnect/connect unless we physically remove USB cable from port.  That toggles the VBUS/ID pin polarity or being forced high via USBGPCS register when analog GIPO PB1, PB2 are disabled. So the same endpoint exception failure is occurring either way USBGPCS is being updated or configured.

    Oddly there are only 6 tick handlers configured for 7 bulk endpoints, perhaps uDMA transfers of end point pipe data are not emptying ring buffers fast enough during times of heavy AHB traffic. Sometimes the pipe exception on Windows bulk client happens immediately. Other times of heavy AHB traffic bulk data transfers of several IOT variable print status lasts for a few report cycles then crashes. The only way to fix the target bulk device end points requires re-plug USB cable and re-starting the device client. The target should automatically rebuild the disconnected pipe since the USBGPCS never indicated USB cable being unplugged from target. Seemingly the 7 endpoints linked to CDC low level driver should always be refreshing as part of target endpoint pipe links via tick handlers and cyclic USB library calls. This might even be the bulk device windows client to blame but pipe disconnect seems to be initiated from the target.

    bool
    USBDeviceConfig(tDCDInstance *psDevInst, const tConfigHeader *psConfig)
    {
        uint32_t ui32Loop, ui32Count, ui32NumInterfaces, ui32EpIndex, ui32EpType,
                 ui32MaxPkt, ui32NumEndpoints, ui32Flags, ui32BytesUsed,
                 ui32Section;
        tInterfaceDescriptor *psInterface;
        tEndpointDescriptor *psEndpoint;
        tUSBEndpointInfo psEPInfo[NUM_USB_EP - 1];//NUM_USB_EP = 8
    
        //
        // How many (total) endpoints does this configuration describe?
        //
        ui32NumEndpoints = USBDCDConfigDescGetNum(psConfig,
                                                  USB_DTYPE_ENDPOINT);
    }

    //*****************************************************************************
    //
    // This internal function initializes the variables used in processing timer
    // ticks.
    //
    // This function should only be called from within the USB library.  It is set
    // up to ensure that it can be called multiple times if necessary without
    // the previous configuration being erased (to cater for OTG mode switching).
    //
    // \return None.
    //
    //*****************************************************************************
    void
    InternalUSBTickInit(void)
    {
        uint32_t ui32Loop;
    
        if(!g_bUSBTimerInitialized)
        {
            for(ui32Loop = 0; ui32Loop < MAX_USB_TICK_HANDLERS; ui32Loop++)
            {
                g_pfnTickHandlers[ui32Loop] = (tUSBTickHandler)0;
                g_pvTickInstance[ui32Loop] = 0;
            }
    
            g_bUSBTimerInitialized = true;
        }
    }

  • And another find related to module timing under the USB hood may relate to service intervals being interrupted by higher priority peripherals (PWM, ADC0) that have CPU's undivided attention.

    //*****************************************************************************
    //
    // usblibpriv.h - Private header file used to share internal variables and
    //                function prototypes between the various modules in the USB
    //                library.  This header MUST NOT be used by application code.
    //*****************************************************************************
    //
    // Internal interrupt handlers called from the main vectors in device and
    // host mode.
    //
    //*****************************************************************************
    extern void USBDeviceIntHandlerInternal(uint32_t ui32Index,
                                            uint32_t ui32Status);
    extern void USBHostIntHandlerInternal(uint32_t ui32Index, uint32_t ui32Status);

    //*****************************************************************************
    //
    // The maximum number of tick handlers that can be registered in a system.
    //
    //*****************************************************************************
    #define MAX_USB_TICK_HANDLERS       6
    
    //*****************************************************************************
    //
    // This value defines the number of SOF ticks that must pass before a call
    // is made to InternalUSBStartOfFrameTick.  The value 5 ensures that the
    // function is called every 5 milliseconds assuming that SOF interrupts are
    // enabled and SOF is present.
    //
    //*****************************************************************************
    #define USB_SOF_TICK_DIVIDE 5

  • Hi BP101,
    Is this issue resolved?
  • Well it was an attempt to try and understand why USB0 endpoint pipe was being bounced by the target MCU. Is it resolved ? not even by direct control of VBUS pin does USB endpoint pipe remain connected during (rapid) PWM0 activity. It would seem the speed at which NVIC changes priority from USB0 0x80 to PWM0 0x20 could be partly the cause of why or when the bulk device FIFO pipe collapses to the host.

    So no, issue remains. Yet has shown host VBUS remains enabled removes suspicion the host being the culprit. Also wrote several recovery methods bulk client attempt to reestablish a pipe in the still connected endpoint. Could not recoup from the targets bounce of the pipe in the host device driver refusal to reconnect the targets pipe until the client was closed, USB cable re-plugged , client opened again.
  • Hi Charles,

    Odd thing is setting the USB clock divisor 8=60mHz, 16=30mHz both would eventually randomly close the end pipe. Odder yet setting the PLL divisor 30=16Mhz USB clock when PLL=480mHz and seems to stop the more frequent end pipe error of bulk device client. The (USBdenum.c) USBDCDInit() configures the USB clock for PLL=480mHz.

    How can the USB even run 16mHz according to datasheet it must be 60mHz?

    USB Clock Control
    When the USB module uses the integrated USB PHY, the MOSC must be the clock source, either with or without using the PLL, and the system clock must be at least 30 MHz. In addition, only integer divisors should be used to achieve the 60 MHz USB clock source. Fractional divisors may increase jitter and compromise USB function. The USB Clock Control Register (USBCC) register contains
    a CLKDIV bit field which can be programmed to specify the divisor used to reduce the PLL VCO output to the 60 MHz clock source required for the serialization/deserialization module of the USB controller.
  • Hello BP101,

    Not all peripherals are 'locked' to prevent running out of spec, however when not running USB at 60 MHz the device is considered running out of specification and TI has no liability for any performance because it violates datasheet requirements.
  • Hi Ralph,

    I think the datasheet is not being specific for typical USB single point connections, rather makes a blanket statement to achieve 480 MBPS transfer speed with external PHY (HUB) requires 60mHz clock rate. It is impossible to achieve 480 MBPS packet transfers to an end point, so the external PHY bus speed is my take on what the text is referring to. Hope NDA USB PDF has a better perspective on this requirement.

    At lest at 16mHz USB clock with 25Mhz MOSC the target is not randomly trashing the end pipe of the host device. Seemingly something ain't exactly right in the USB library management of buffer full status handling as it can quickly crash the end pipe by flooding it with high speed data transfers even at 16mHz. Below is a threshold test after packet transfers are complete checking the ring buffer space is not <128 bytes. Disabling the buffer check results in quickly trashing the end pipe client via non-interrupted packet transfers. Typically the application processes 64 byte packet transfers in 1 second intervals to the bulk device. So that is not as volatile as doing non-interrupted packet transfers to the bulk device client. Even the 1 second intervals seemed to rapidly fill the buffer from blocked USB Status updates when the AHB gets real busy at times with higher priority NVIC INT pends.  

    //*****************************************************************************
    uint32_t
    TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
              void *pvMsgData)
    {
        uint32_t ui32Space;
        //
        // We are not required to do anything in response to any transmit event
        // in this example. All we do is update our transmit counter.
        //
        if(ui32Event == USB_EVENT_TX_COMPLETE)
        {
            //
            // How much space is there in the transmit buffer?
            //
             ui32Space = USBBufferSpaceAvailable(&g_sTxBuffer);
    
            if(ui32Space < 128)
            {
              /* Flush the TX buffer of any overflow data */
              USBBufferFlush(&g_sTxBuffer);
            }
    
            g_ui32TxCount += ui32MsgValue;
        }
        return(0);
    }

  • Hello BP101,

    BP101 said:
    Seemingly something ain't exactly right in the USB library management of buffer full status handling as it can quickly crash the end pipe by flooding it with high speed data transfers even at 16mHz.

    Are you truly using high speed mode, or just full speed? Not many use High Speed mode. If you are using High Speed, check if applying the following bug fix helps: e2e.ti.com/.../2518648

    BP101 said:
    Below is a threshold test after packet transfers are complete checking the ring buffer space is not <128 bytes. Disabling the buffer check results in quickly trashing the end pipe client via non-interrupted packet transfers.

    I am not sure what you are trying to prove here, of course disabling the buffer check is going to mess things up. If it wasn't needed, it wouldn't be there in the first place.

  • Hi Ralph,

    From my understanding the bulk device driver is in high speed mode is being set during USB0 initialization.

    The buffer status was added by me, the USB library is supposed to handle the buffer space status callback but it does not do a very good job when doing direct calls to USBBufferWrite() via the (usb_bulk_structs.c) typedef struct defined buffers size.

  • BTW the bulk device driver initializes the DCD mode not DCH, my guess H specifies USB configured for HID driver support.
  • Hello BP101,

    USB High Speed is not that simple... you need an external High Speed USB PHY to use High Speed with the device, and then have to toggle on software that High Speed is being used.

    See www.ti.com/.../TIDM-TM4C129USBHS for details.

    The vast majority of applications are done with full speed mode.

    Regarding buffer checks, can you elaborate more on the TxHandler then? What layer is it used in? What interrupt (if any) triggers it? Is it based of any TivaWare file I can look to compare to and get a better idea of what is going on? How does the TxHandler relate to 'trashing the endpipe' if it's not part of the USB stack?
  • Hello BP101,

    I would need to see the full variable or function names, but I would guess the D is for Device and the H is for Host.
  • Hey Ralph,

    Yep your right, it is actually host versus device.

    The USB library lower level call back status update for write buffer channel control does not (always) keep pace with 64 byte packets (256KBPS) no matter how large the structs R/W buffers are configured. Guessing 16mHz USB clock is just fast enough for 4 channels of serialization or 256KBPS*16x*4CH=16,384,000mHz. When the USB clock is >=30mHz the USB write buffer fills even faster, perhaps why buffer overrun threshold improves at reduced USB clock rates.

    Can someone have a look at why USBWriteBuffer() can flood (usb_bulk_structs.c) high speed mode WR buffer? Adding my secondary buffer controls do not stop end pipe from eventually collapsing at lower level of target. Seems as AHB traffic picks up during packet transfers the USB callback of client buffer status updates gets delayed.
  • Hi Ralph,

    Ralph Jacobi said:
    USB High Speed is not that simple... you need an external High Speed USB PHY to use High Speed with the device, and then have to toggle on software that High Speed is being used.

    Perhaps device mode defaults to FS since the ULPI feature is never set (usb_dev_bulk.c) call to USBBulkInit() call to USBDCDIniti(). Below it looks like speed actually defaults to FS if the ULPI feature mode is never configured?

    usbdenum.c --> USBDCDInit()

            //
            // Configure ULPI support.
            //
            if(g_ui32ULPISupport != USBLIB_FEATURE_ULPI_NONE) //NONE=0x0000.0000
            {
                USBULPIEnable(USB0_BASE);
    
                if(g_ui32ULPISupport & USBLIB_FEATURE_ULPI_HS)
                {
                    ULPIConfigSet(USB0_BASE, ULPI_CFG_HS);
                }
                else
                {
                    ULPIConfigSet(USB0_BASE, ULPI_CFG_FS);
                }
            }
            else
            {
                USBULPIDisable(USB0_BASE);
            }

     

  • Configuring USB feature set for ULPI mode, enable/disable and configuring USB_ULPI for FS or HS locks up MCU during USB initialization. It would seem bulk device does not use FS or HS modes and does another kind of lower level device_mode setup in the USB library.
  • Hello BP101,

    Do you have a USB high-speed ULPI interface attached to your MCU? The ULPI is used to interface with an external PHY in order to allow High Speed USB to work. That is what the TI Design I posted before references. It includes hardware design considerations as well as offers software configurations. Not even our LaunchPad's support high speed from a hardware level, only full speed. This is also why all TivaWare defaults everything to FS and users have to go out of their way to configure HS... anyone who actually can use HS will have designed the hardware to support it and won't be burdened much to turn on a few knobs, but anyone working from a LaunchPad etc. has to have FS only.

    And with all that said, my understanding is you don't have that additional hardware built onto your board as it was based on the LaunchPad design, so you should be using USB Full Speed mode only as well.
  • Hi Ralph,

    The source code does not make that point so clear and complicates the topic by throwing LPM under ULPI controls UBSOTGFeatureSet() when set to disabled or ULPI_NONE.

    It would seem somehow WAKE and other LPM modes are part of ULPI for OTG device support. It would also seem necessary to have LMP control with the HIB module power controls of USB0. Perhaps a grey area or someone used the acronym ULPI in text to include LPM parameters also available in FS mode?