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.

TM4C1294NCPDT: usb_host_serial example

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL, MSP432E401Y

Hello TM4C support,

Our customer is looking for an example to use as a starting point for implementing a USB Host as a CDC serial port.  Where do I find a finished example of usb_host_serial for the TM4C129 (or TM4C123)?

Thanks,

Darren

  • Hello Darren,

    We have a fully built example and the associated files to make that work for the EK-TM4C1294XL LaunchPad.

    The customer will need to place the four new usblib files in their TivaWare usblib folders. The path will be [Install Path]\TivaWare_C_Series-2.1.4.178\usblib\host

    The files are usbhcdc.c and .h and usbhcdcserial.c and .h. They are included in the zip below.

    Once those files are in place, they need to import usblib into CCS and rebuild it for the files to be built into the library file which is used for the example project.

    After that, they will want to place the new example project in [Install Path]\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c1294xl and then import it, this will make sure it pulls all the required TivaWare dependencies properly.

    Depending on how they want to test it, the host example has notes about the power configuration inside. They may need to adjust that depending on their test case. Those notes are around line 500 for the USBHCDPowerConfigInit API.

    Here is the zip directory with all required files: 2476.usb_host_serial.zip

  • Hello Ralph,

    This 430KB file appears to be, "good stuff."    Thank you for this.

    We note that the T.I. requester (Darren) sought, "Example of usb_host_serial for the TM4C129 (or TM4C123")?

    Your post specifically addressed the TM4C129.    Other than altering the device pin-outs - is this file expected to work w/the TM4C123 family?    And - has this work received "reasonable (i.e. beyond the code developer's individual) testing" - for (both) MCU families?

    Our firm & multiple of our clients look forward to this new (hopefully robust/tested) addition...

  • Hi cb1,

    We had considered expanding the USB host examples for TM4C123x, but because the LaunchPad is very poorly configured for host - need to do blue wire soldering levels of board modification to make USB host operational - we did not do much on that front and I did not try and develop a host CDC example for TM4C123x as a result.

    That said, the four usblib files should work for TM4C123x, so it would be more application level code changes that are needed.

    I'll keep that in mind for when we look into app notes & collateral to see if we want to make a small offering of TM4C123x host projects available along with an app note to walk through all the hardware modifications required to make them operational... more food for thought to beef up our offering!

  • Hi Ralph,

    Ay Caramba ... that "Whoosh" just heard resulted from ALL of the Air being sucked out of our (neatly appointed/equipped) Back-Room!

    Are we correct in believing that "testing" was performed by, "developer only?"   (Clients have "pushed me" for that...)

  • Hello cb1,

    For the example, the testing was done by myself (developer) and Charles. I used a USB analyzer to validate the data transfers, but there could certainly be more testing done to how the example works... I would like to put together a more interactive example between host and device LaunchPad's.

    The usblib files have been around for a while but never released, and I did the leg work internally to verify how they were developed and tested and have high confidence in their reliability across all TM4C devices.

  • Thank you Ralph,

    Believe it proves easier for you to, "Tell us here once" rather than receive multiple client questions - each seeking (near) identical information.   (Clients have, "Nowhere near the familiarity w/this forum - and 'cast of characters' - as does our small group!")

    Pity that the '123 could not be included - it fits a highly particular "Sweet-Spot" for over 40 of our long-term clients...

  • Hi Ralph,

    With the help of Darren Jenkins, I was able to to retrieve and review usb_host_serial example posted by you.  I had few questions:

    1.  The example is requiring to read and write data to/from USB from the polling method in the main loop.  Is there a way we can extend the example to use an interrupt function to read the data from USB, store into the ring buffer.  And then write data asynchronously to another ring buffer, and then have the interrupt function to read data from that ring buffer and send it out to USB?  This is similar to the USB device Serial example.

    2. In your example, the function USBHCDCGetDataFromDevice is used to retrieve data from USB bulk endpoint.  But it is a blocking function because it is eventually calling USBHCDPipeRead. 

    Is there any dangers in calling the non-blocking function, USBHCDPipeReadNonBlocking?

    Dennis

     

  • Hello Dennis,

    You can definitely use the example with an interrupt function instead. That's an improvement I'd like to include on our end at some point as well, I'm not too happy with how the interface with the equivalent usb_dev_cdcserial project works honestly. I think what you described would work well.

    Dennis Tan said:
    Is there any dangers in calling the non-blocking function, USBHCDPipeReadNonBlocking?

    If you mean inside of USBHCDCReadData instead of USBHCDPipeRead, then the challenge is that the NonBlocking version can return early if it has read all the data available on the pipe, so that case would need to be handled.

    What you could do to start is trying doing stress tests with both and see what performance you get and see if there are issues with the NonBlocking version returning early and then assess from there whether the NonBlocking functionality would be worth having if the extra functionality needs to be added.

  • Hi Ralph,

    Thanks for your response. 

    1) My application is using an RTOS and would not prefer to use a thread for the polling read and write.  Could you provide an extended version of the host serial example on how to use interrupt function and ring buffer?  I had reviewed the usb_dev_serial example and it is quite different from the host example.  Any guidelines and helps would be greatly appreciated.  I am quite familiar with the TI ring buffer but not sure how to tailor USB API together with the interrupt function.

    2) I read the description for USBHCDPipeRead function.  Does it block until all the data requested are fulfilled?  What happen if I ask for 64 bytes and the pipe would only return 32 bytes?  Will it block forever?

    3) Could you elaborate the issue of early return for the nonblocking version?  If I use a ring buffer to store the received data and constantly calling the non-block function, will I still have this issue?

  • Hello Dennis,

    Honestly I am not very familiar with the USB Host + Interrupt setup yet - that was a piece that I would have liked to delve into more but haven't had the bandwidth to do so from an application construction standpoint.

    Are you using TI-RTOS or a third party RTOS?

    There is intelligence in the USBHCDPipeRead such as checking if the device stalled the request and looking for states like DISCONNECT / POWER_FAULT in order to avoid such issues of blocking forever.

    RE: The non-blocking version, if it returns earlier - say you got 32 of 64 bytes in - you need to know to call the USBHCDPipeReadNonBlocking function again at some point to get the other 32 bytes or they would be lost. I think storing in ring buffer and calling the USBHCDPipeReadNonBlocking often enough will be fine, just was making a point of that's extra handling to keep in mind so it isn't just a one line replacement and everything will work 100%.

  • Hi Ralph,

    1) We are using a third party RTOS.  I think the entry point to an interrupt function is for USB host is USBHostIntHandlerInternal.  I compared the logic for the corresponding device, USBDeviceIntHandlerInternal.  The difference is the structure.  The device structure has a ringbuffer, whereas the host structure doe not.  It is not trivial to duplicate the same interface in device to the host.  

    Does anyone in TI did something similar?  If yes, please share with us.

    2) I saw the intelligence you talk about for USBHCDPipeRead.  If it detects stall, it will break out of loop. What is the gap between a detected stall and the last character read from end point?

    Another question: What is exactly the difference between USBHCDPipeRead. and USBHCDPipeReadNonBlocking?

    Both functions can return the size less than expected.  

  • Hello Dennis,

    There is a TI-RTOS USB CDC Host example for the MSP432E401Y.

    You can find it at [SimpleLink MSP432E4 SDK Install]\examples\rtos\MSP_EXP432E401Y\usblib\usb_cdc_serial_host

    Dennis Tan said:
    What is the gap between a detected stall and the last character read from end point?

    Honestly I am not sure - I did not write & test usblib and I haven't tried to measure that before. I didn't see much regarding that on E2E either so I don't know if the exact timing had been assessed.

    The USBHCDPipeReadNonBlocking API just does a quick readout of all data available in the pipe up to a maximum number of bytes that is requested. The ui32Size parameter is returned to indicate how many bytes are read. The application needs to be responsible for what happens if the returned ui32Size is less than the requested ui32Size.

    The USBHCDPipeRead API has a more involved process. It will continue to try and read data until it receives the number of bytes requested by ui32Size OR if an error occurs. It will also return the ui32Size which needs to be checked, but in this case, if the ui32Size is less than the requested ui32Size, you would check the USB event flags to understand what went wrong. A re-try would likely be needed in this case. But you would get the amount of data requested as long as no error events occurred, so you don't need to worry as much about handling 'okay I got 30 of 50 bytes, I need to read 20 more...' It would be 'I got 30 of 50 bytes, a USB error occurred, what happened and how to resolve?'.

    Hopefully that helps further explain the differences.

  • Hi Ralph,

    You mentioned that there was another example of host USB serial.

    The information provided is  

    SimpleLink MSP432E4 SDK Install]\examples\rtos\MSP_EXP432E401Y\usblib\usb_cdc_serial_host

    I had downloaded the SDK and only find a directory called MSP_EXP432E401R, not MSP_EXP432E401Y.

    Could you give me more details in finding that example,  "MSP_EXP432E401Y\usblib\usb_cdc_serial_host" ?

    Thanks

    Dennis

  • Hello Dennis,

    There is no MSP_EXP432E401R. It would be either MSP_EXP432E401Y or MSP_EXP432P401R

    I think you probably downloaded the MSP432P4 SDK. Make sure your SDK is: simplelink_msp432e4_sdk_3_40_01_02

  • Hi Ralph,

    I used your example on my project and for some reasons the CDC device is not detected even the device is physically connected to the host.

    Specifically, I am not seeing the USB_EVENT_CONNECTED from the USBHCDEvents call back function.

    Any help is greatly appreciated.

    Here is the segment of code for your reference.

    uint32_t ui32PLLRate = 0;
    uint32_t ui32SysClock = SystemClockFreqGet();

    //
    // Initially wait for device connection.
    //
    g_eUSBState = STATE_NO_DEVICE;

    // Configure the required pins for USB operation.
    //ROM_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    ROM_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);

    //
    // Enable the uDMA controller and set up the control table base.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    usleep(1000);
    ROM_uDMAEnable();
    ROM_uDMAControlBaseSet(g_sDMAControlTable);

    i_set_interrupt(INT_USB0, USB0OTGModeIntHandler, 0);
    ROM_IntPrioritySet(INT_USB0, USB0_INTERRUPT_LEVEL);

    //
    // Initialize the USB stack in host mode. No callback is needed at this
    // time.
    //
    USBStackModeSet(0, eUSBModeForceHost, 0);

    //
    // Register the host class drivers.
    //
    USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers);

    //
    // Open an instance of the CDC driver. The CDC device does not need
    // to be present at this time, this just saves a place for it and allows
    // the applications to be notified when a CDC device is present.
    //
    g_psCDCSerialInstance = USBHCDCSerialOpen(CDCSerialCallback);

    //
    // Initialize the power configuration. This sets the power enable signal
    // to be active low which means that the VBUS pin of USB Device connector
    // for the EK-TM4C1294XL LaunchPad will not be supplied with +5V.
    //
    // If connecting to another EK-TM4C1294XL LaunchPad, USBHCD_VBUS_AUTO_HIGH
    // should only be used if the USB Device LaunchPad has the power selection
    // jumper set to "OTG". If the ICDI is used to power the USB Device
    // LaunchPad and the USB Host LaunchPad outputs VBUS, the USB interface
    // could become **PERMANENTLY DAMAGED**!!!
    //
    // If connecting to a generic USB device that should be powered by the
    // USB host, use USBHCD_VBUS_AUTO_HIGH to allow the LaunchPad to supply
    // +5V to the VBUS pin of the USB device connector.
    //
    USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_LOW | USBHCD_VBUS_FILTER);

    //
    // Tell the USB library the CPU clock and the PLL frequency.
    //
    SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate);
    USBHCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &ui32SysClock);
    USBHCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate);

    #ifdef USE_ULPI
    //
    // Tell the USB library to use ULPI interface
    //
    ui32ULPI = USBLIB_FEATURE_ULPI_HS;
    USBHCDFeatureSet(0, USBLIB_FEATURE_USBULPI, &ui32ULPI);
    #endif

    //
    // Initialize the USB controller for host operation.
    //
    USBHCDInit(0, g_pHCDPool, HCD_MEMORY_SIZE);

    // Notify the calling thread that the function had been entered into server mode
    m_gThreadCheckRet = 1;
    sem_post(&sema_USBThreadCheck);

    //
    // The main loop for the application.
    //
    while (1)
    {
    USBThread_counter = 0;
    #if RTOS_DEBUG
    checkIstack (); // test Interrupt and thread stack water level
    #endif

    //! This function is the main routine for the host controller driver, and must
    //! be called periodically by the main application outside of a callback
    //! context. This allows for a simple cooperative system to access the the
    //! host controller driver interface without the need for an RTOS. All time
    //! critical operations are handled in interrupt context but all blocking
    //! operations are run from the this function to allow them to block and wait
    //! for completion without holding off other interrupts.
    USBHCDMain();

    switch(g_eUSBState)
    {
    //
    // This state is entered when the CDC device is first detected.
    //
    case STATE_CDC_DEVICE_INIT:
    {
    //
    // Initialize the newly connected CDC device.
    //
    USBHCDCSerialInit(g_psCDCSerialInstance);

    //
    // Proceed to the connected CDC device state.
    //
    g_eUSBState = STATE_CDC_DEVICE_CONNECTED;

    break;
    }
    case STATE_CDC_DEVICE_CONNECTED:
    {
    //
    // Start polling for data on interface 1.
    //
    USBHCDCGetDataFromDevice(g_psCDCSerialInstance,
    BULK_ENDPOINT_INTERFACE_1);

    /*
    USBHCDCSendDataToDevice(g_psCDCSerialInstance,
    BULK_ENDPOINT_INTERFACE_1,
    ui8SendArray, ui8DataSize);
    */
    break;
    }
    case STATE_UNKNOWN_DEVICE:
    {
    //
    // Nothing to do as the device is unknown.
    //
    break;
    }
    case STATE_NO_DEVICE:
    {
    //
    // Nothing is currently done in the main loop when the CDC
    // device is not connected.
    //
    break;
    }
    default:
    {
    break;
    }
    }
    sched_yield();
    }

  • Hi Ralph,

    I have a Tiva micro (TM4C129) acting as a host connect to a generic USB device.  I used the same logic in host usb serial demo for my project.

    After I changed the power initialization to use USBHCD_VBUS_AUTO_HIGH as follows:

    USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER);

    The Tiva micro is now detecting an unknown device.  Specifically, the host cannot read the configuration descriptor when it is initializing a request.

    Do you know any reasons that might cause this issue?

    Thanks

    Dennis

  • Hello Dennis,

    Can you offer any details on the USB device connected? Could you try and test via our LaunchPad initially?

    Because the host-device interface isn't easy to see how enumeration is going etc. without the PC involved, I used a USB analyzer in order to sniff all the packets and make sure enumeration was handled correctly.

    Regarding the power issue, that depends on if the device would be self powered or not. What is the power capability on the device? Is it depending on the host for power?

  • Hi Ralph,

    Sorry to bother you again.  I had delved into the code and found that total length of the device configurator is 564 bytes.  So, I increased HCD_MEMORY_SIZE to 640 and now it was able to send a Connect event into the USBHCDEvents call back function.

    1) Is it normal for the device configurator to have such a long length?  The default setting for HCD_MEMORY_SIZE  is 128 bytes.

    2) I am still failing inside the USBHCDEvents function.

    Specifically, it is failing on this line: USBHCDDevProtocol(pEventInfo->ui32Instance, 0) == USB_CDC_PROTOCOL_V25TER

    In my case, USBHCDDevProtocol returns a zero, which meant USB_CDC_PROTOCOL_NONE.

    Why do we need the CDC Protocol to be USB_CDC_PROTOCOL_V25TER?

    Dennis

  • Hello Dennis,

    V.25ter is commonly used for USB CDC. I don't know the exact reasons for why that one is used over others. You can use other protocols as well. In TivaWare we have the following defined:

    #define USB_CDC_PROTOCOL_NONE   0x00
    #define USB_CDC_PROTOCOL_V25TER 0x01
    #define USB_CDC_PROTOCOL_VENDOR 0xFF

    All of that is application specific, so use what fits your application. The idea of the project is to give you a starting point application, you will need to make adjustments like that as works for your project & device. In our case, the usb_dev_cdcserial project that will be released with usb_host_serial uses USB_CDC_PROTOCOL_V25TER and thus we look for that.

  • Hi Ralph,

    Could you tell me the difference among, USB_CDC_PROTOCOL_NONE, USB_CDC_PROTOCOL_V25TER, and USB_CDC_PROTOCOL_VENDOR?

    In my case, when the host is connecting to a generic CDC device, I am getting a connected event, but the USB CDC interface being USB_CDC_PROTOCOL_NONE.  Is this something I can let it go and still able to communicate with the device?

    Dennis

  • Hello Dennis,

    There V.25ter protocol is considered standard for CDC Communication interface. I am not certain the details as to why, I think it is just a general industry standard. So to maintain compatibility with other hosts/devices, that is what is used.

    "Generic COM-port devices and some modems belong to the abstract control model subclass. The protocol is V.25ter, which documents common AT commands. For compatibility with standard host drivers, a generic virtual COM-port device should specify the V.25ter protocol even if the device doesn’t use AT commands." Source: http://janaxelson.com/usb_virtual_com_port.htm

    Conversely, USB_CDC_PROTOCOL_NONE is standard for the CDC Data interface. So it is used for all the data interface descriptors.

    As a device expert who inherited USB library support and did not develop it, I am aware of but not in deeply knowledgeable about the details of why CDC is setup with both communication vs data interfaces and why those protocols are used for each. You may need to do some general reading on that.

    Regarding USB_CDC_PROTOCOL_VENDOR, I've never seen it used. I don't think it's really relevant and just something the initial developer added to possible support proprietary/closed loops applications. I've never seen it used before.

  • Hi Ralph,

    Thanks for your response.  I am trying to figure out why I don't receive any data when the host sends something to the CDC device.

    In tracing into the code, I had noticed that dma transfer is not used.  Specifically, EP_PIPE_USE_UDMA is not configured.  

    For example, the if statement below is always false in my case.

    // Try the DMA transfer should be used for this transfer, so set up
    // the uDMA channel in advance of triggering the IN request.
    //
    if(ui32Pipe & EP_PIPE_USE_UDMA)

    1) How do you setup your demo to uDMA transfer?

    2) Why when using non-dms transer, the byte to send is always limit to the magic number, 64?

    Thanks

    Dennis

  • Hello Dennis,

    We don't have a USB w/ uDMA CDC demonstration available at this time - it is on the to-do list, but I don't have anything to share on that front yet. In the past I have reference the usb_host_msc example as one to look at for how to implement DMA and that seemed to get most in the right direction.

    Yes, 64 bytes is the max to send. USB High Speed increased that to 512, but USB Full Speed has a max packet size of 64 bytes unless doing Isochronous transfers (usually seen with BULK device class) which can go up to 1023 bytes.

  • Hi Ralph,

    Is it possible for us to give you a call?

    Dennis

  • Hello Dennis,

    That is not something we set up through E2E. I'll talk w/ Darren but it looks like he is out until Monday.