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.

problems with USB OTG and CDC driver

I previously had code using the CDC device library running fine on my DK-TM4C129X dev kit. I have been trying to get OTG implemented, but am not having much luck.

I copied over a bunch of code from the usb_otg_mouse example project and I think I have done all the initialization properly. When I run the code, though, the callback specified in my call to USBStackModeSet() is never getting called.

The weird thing is that the control callback for my CDC device does get called. But every 2 seconds (which just happens to be the time I specified for OTG polling) it gets a disconnect event followed immediately by a connect event. I can actually send and receive characters during the 2 seconds between these events.

Any idea what might cause this behavior? I don't actually use the host mode yet, but I did register a driver (I just copied the example code), although I did not start up anything (e.g., mouse).

I am calling USBOTGMain() every 2 ms from a low priority task.

In case it helps, here is the init code I use:

void UsbCdc::initialize(
                void(*processRxCharsFunc)(const U8 *rxChars, U32 numChars),
                void(*processConnectionFunc)(bool connectStatus))
{
    // initialize class' static variables
    currentMode = eUSBModeNone;
    newMode = false;
    connected = false;
    txCompleted = true;
    processRxCharsCallback = processRxCharsFunc;
    processConnectionCallback = processConnectionFunc;

    // the RTOS requires that interrupt service routines be placed in a special
    // interrupt vector table by calling the following function.
    BSP_IntVectSet(BSP_INT_ID_USB_MAC, &USB0DeviceIntHandler);

    // GPIO pin initialization for the USB circuit is done in
    //      Gpio::initialize()

    // configure USB for OTG operation
    otgInit();

    // initialize host stack
    hostInit();

    // initialize device stack
    deviceInit();

    // initialize the USB controller for dual mode operation with a 2ms 
    // polling rate 
    USBOTGModeInit(0, OTG_POLLING_RATE_MS, hcdMemoryPool, HCD_MEMORY_SIZE);
}

void UsbCdc::otgInit(void)
{
    // enable the USB controller
    SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);

    // Initialize the power configuration. This sets the power enable signal
    // to be active high and does not enable the power fault. 
    USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER);

    // tell the USB library the PLL frequency
    bool ok;
    U32 pllRate = PLL_RATE;
    ok = USBOTGFeatureSet(0, USBLIB_FEATURE_USBPLL, &pllRate);
    assert(ok);

    // initialize the USB OTG mode and pass in a mode callback
    USBStackModeSet(0, eUSBModeOTG, modeCallback);

    // configure low power mode feature
    tLPMFeature lpmFeature;
    lpmFeature.ui32HIRD = HIRD_US;
    lpmFeature.ui32Features =       USBLIB_FEATURE_LPM_EN 
                                |   USBLIB_FEATURE_LPM_RMT_WAKE;
    USBHCDFeatureSet(0, USBLIB_FEATURE_LPM, &lpmFeature);
}

void UsbCdc::hostInit(void)
{
    USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers);
}

void UsbCdc::deviceInit(void)
{
    // initialize the transmit and receive buffers
    const tUSBBuffer *buf;
    buf = USBBufferInit(&txBuffer);
    assert(buf != 0);

    buf = USBBufferInit(&rxBuffer);
    assert(buf != 0);

    // pass our device information to the USB library and place the device
    // on the bus
    void *p;
    p = USBDCDCInit(0, (tUSBDCDCDevice *)&cdcDevice);
    assert(p != 0);
}

void UsbCdc::modeCallback(U32 index, tUSBMode mode)
{
    currentMode = mode;
    newMode = true;

    switch(mode)
    {
        case eUSBModeHost:
            break;

        case eUSBModeDevice:
            break;

        case eUSBModeNone:
            break;

        default:
            break;
    }
}

Thanks for any insight you can provide.

Regards,

Dave
  • Hello Dave

    In the original code the OTG Init is being called with the callback function as a parameter

    USBOTGInit(uint32_t ui32ClockRate, tUSBModeCallback pfnModeCallback)

    Which does not see to be the case in your code where it is being void

    Regards
    Amit
  • Hi, Amit,


    In the example code the clock rate and callback pointer are passed to USBOTGInit(), which is not a USB library function but rather a function in the usb_otg_mouse.c file. That function then calls USBOTGFeatureSet() to set the clock and PLL rates and USBStackModeSet() to set the callback. My otgInit() function does not require parameters, since it just accesses the callback pointer directly when calling USBStackModeSet(). But unless I am missing something obvious, the same code is executed in either case. It is just a matter of style.


    Regards,

    Dave

  • Hello Dave,

    Since you mentioned that the call back function was not being called, I checked apple-2-apple between the two codes and this stood out.

    Also the original application calls

    USBOTGFeatureSet(0, USBLIB_FEATURE_USBPLL, &pllRate);

    with call for both CPU CLK and USB PLL.

    Regards
    Amit
  • Hi, Amit,

    The reason I did not call USBOTGFeatureSet() to set the CPU clock was that in a prior thread I learned that calling USBDCDFeatureSet() and passing the USBLIB_FEATURE_CPUCLK parameter resulted in the function returning an error, and that it was no longer needed for the TM4C129 family.

    I took a closer look and discovered that USBOTGFeatureSet() calls both USBDCDFeatureSet() and USBHCDFeatureSet() with the same parameters that were passed to it. USBDCDFeatureSet() will return an error, but interestingly USBHCDFeatureSet() does not. However, the net result is that USBOTGFeatureSet() returns an error if you call it with USBLIB_FEATURE_CPUCLK. This seems to be a bug in the library code.

    Nonetheless, I added the call to USBOTGFeatureSet() to set the clock rate and just ignored the return value. The problem still exists even after adding this call. So there must be something else going on.

    Regards,

    Dave

  • Hello Dave,

    If the code is in CCS then can you send over the project so that i can check it on the DK-TM4C129X?

    Regards
    Amit
  • Hi, Amit,

    The code is in IAR. Will that work for you? If so, I can upload it to you via PM.


    Thanks,

    Dave

  • Hi, Amit,

    I think I found at least one reason for my problems. I neglected to replace the interrupt vector table entry with USB0OTGModeIntHandler(), so it was still using the device handler ISR. I have been in meetings most of the morning, so I have not had a chance to test it. But I am pretty sure when I change that I will at least be getting calls to my callback function. We'll see how things work then.

    Regards,

    Dave
  • Hello Dave,

    Yes, that may in fact be the issue.

    Regards
    Amit
  • Hi, Amit,

    I finally got out of 5 hours of meetings! I tried things with the proper ISR in the vector table, and it seems to work okay now. No more disconnect/connect every 2 seconds. And the code now recognizes switching between host and device mode when switching the cable around.

    Regards,

    Dave
  • Hello Dave,

    And this is the HNP+SRP implemented or the same usb_otg example as in the TivaWare

    Regards
    Amit
  • Hi, Amit,

    This is using the code from the usb_otg example in TivaWare, but with CDC instead of HID driver. I only have CDC device working. I am going to try to get Gavin's host CDC working next. (see ).

    It turns out that I will probably not need the HNP functionality, although I did do the NDA and got the full version of the data sheet just in case.

    Regards,

    Dave