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.

EK-TM4C123GXL: How does the USB-UART work?

Part Number: EK-TM4C123GXL


I have several problems associated with getting a UART to work over USB. I've not done anything with USB before. I've been trying to adapt the Tiva examples. The things I don't understand are:

1. In the Tiva examples there doesn't appear to be any code that sets up the USB, so how does the USB port get initialised? I also can't see anything that appears to link the UART to the USB. How is this routing achieved?

2. Although I can get data sent from the Tiva board to CoolTerm on my mac by using UARTwrite, there isn't a UARTread function in the library. How do I get data to pass in the other direction?

FYI I'm using the Tiva C launchpad board and the Tiva driver library 2.1.4.178.

  • Which examples are you looking at? Is it C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c123gxl\usb_dev_serial ?

  • Yes, that one and I also looked at usb_dev_bulk and usb_dev_gamepad.

  • For the usb_dev_serial project the initialization of the USB is handled by lines 1123 through 1138 of usb_dev_serial.c in the main() function.

        //
        // Initialize the transmit and receive buffers.
        //
        USBBufferInit(&g_sTxBuffer);
        USBBufferInit(&g_sRxBuffer);
    
        //
        // Set the USB stack mode to Device mode with VBUS monitoring.
        //
        USBStackModeSet(0, eUSBModeForceDevice, 0);
    
        //
        // Pass our device information to the USB library and place the device
        // on the bus.
        //
        USBDCDCInit(0, &g_sCDCDevice);
    

    Documentation for the TivaWare USBDCDCInit() function can be found on page 57 of the TivaWare USB Library User's Guide.

    https://www.ti.com/lit/ug/spmu297e/spmu297e.pdf

    or C:\ti\TivaWare_C_Series-2.1.4.178\docs\SW-TM4C-USBL-UG-2.1.4.178.pdf

    The static function ReadUARTData() reads from characters from UART0 and sends them out the USB virtual serial port. The static fuction USBUARTPrimeTransmit() takes characters from the USB virtual serial port and transmits them out UART0.

  • That function just seems hugely complicated. Is there not a simpler way?

    I took the parts of the gamepad code and put it iinto my project and I got messages out to the host computer by calling UARTwrite. This code doesn't call USBDCDCInit nor do the gamepad or bulk example projects. All I need to do is receive a packet of about 5 bytes in the simplest way possible.

  • Hello Andy,

    The code is broken up into fairly compact functions but if you are talking about the size of the whole program, that is so the USB interface is robustly handled. You don't necessarily need all of that for a simple demonstration. That said, there is a big difference here with the USB interfaces. CDC and HID are very different implementations.

    The USBDCDCInit is for CDC only. Note the USBDCDCInit. For HID, you would have a device specific one, so in the case of Gamepad it is:

        //
        // Pass the device information to the USB library and place the device
        // on the bus.
        //
        USBDHIDGamepadInit(0, &g_sGamepadDevice);

    What I don't understand right now is why are you wanting to use the gamepad for this and not a standard CDC serial port which is the usual interface for UART to USB? HID devices are very specific interfaces to control peripheral devices like mouse, keyboard, gamepad etc. I am not clear how trying to interface with one of those devices then needs the UART involved as you are trying to do.

    Can you explain what you are trying to achieve here? That would allow me to better guide you on where to start and what to leverage.

  • Hi Ralph,

    maybe I wasn't very clear on what I'm trying to do. I am not trying to implement a physical UART but rather a virtual UART, which is why I wasn't using the dev_serial example. It looked to me as this was trying to use the launchpad board to create a USB to RS232 converter, which is not what I'm trying to do.

    Put simply, what I'm trying to achieve is to respond to a command from host machine to read data values and I will send these out using printf or something of that ilk. As I mentioned before I have found that UARTwrite will send data to my computer, but I can't get data in from the host.

    Andy

  • Hello Andy,

    Andy Worsley89 said:
    It looked to me as this was trying to use the launchpad board to create a USB to RS232 converter, which is not what I'm trying to do.

    Well, if you want to connect your PC to the TM4C UART, you do need that piece in some manner. That said, if your goal is to connect the USB port from your PC to the UART port of the TM4C LaunchPad, then you don't need the USB peripheral on the device if you use a conversion cable like these: https://www.ftdichip.com/Products/Cables/USBRS232.htm or with your LaunchPad, you just can use the ICDI which handles that for you already. The USB port on the LaunchPad for "Debug" basically does the conversion for you, so you can connect straight to your PC through UART. You don't need any USB handling for this, but would need the converter then for a custom board.

    Also if you are using something like that, then you would be needing the UART piece only, then you'd want to use an example like uart_echo. This will show you how the ICDI works to provide that UART backchannel.

    Not receiving data might be an issue with the wrong ports being set or issues with baud rate.

    If I am not understanding right, maybe explain how the UART and USB are supposed to interface that is different from usb_dev_serial and how you want to use the USB hardware on the TM4C for this application - because from your description I don't think you need the TM4C USB interface.

  • I think the PC will be looking for something that looks like a UART to communicate with. I'm not working on the PC end, only the device end. I'm using CoolTerm on my mac to simulate what will happen on the PC end.

    I believe what is wanted is the comms to go through the 'device' USB connection (not the debug). All I want to do is send and receive data between the launchpad and the PC. How it gets there, frankly, I don't care, but it has to pass through a USB cable on the 'device' connection.

    I have just discoved that the message sends I was seeing with the UARTwrite function were going through the debug port, which means I'm even less far on than I thought I was.

    Andy

  • Hello Andy,

    Okay now I am on the same page as you in terms of what you are expecting to see, so hopefully I can clear this up a lot.

    Andy Worsley89 said:
    I think the PC will be looking for something that looks like a UART to communicate with. I'm not working on the PC end, only the device end. I'm using CoolTerm on my mac to simulate what will happen on the PC end.

    Your PC will be looking for a Virtual Serial Port or a COM port. TermTerm, DockLight, CoolTerm etc. all look for the same thing. This 'virtual serial port' is created by having a USB to UART bridge at a hardware level.

    What the EK-TM4C123GXL LaunchPad offers here is that the Stellaris ICDI interface which is used to program the device ALSO acts as this USB to UART bridge. So when you connect your Terminal software to the Debug port of the LaunchPad, you are getting exactly what you are looking for. Your CoolTerm program is talking directly with your EK-TM4C123GXL LaunchPad over UART.

    If you make custom hardware, you will need a translator chip or a cable like what I had linked before to provide this interface.

    Andy Worsley89 said:
    I believe what is wanted is the comms to go through the 'device' USB connection (not the debug).
    How it gets there, frankly, I don't care, but it has to pass through a USB cable on the 'device' connection.

    No, you don't want to use the Device USB Connection. That is not for UART. That is for USB communication with the USB peripheral. You wouldn't be connecting to CoolTerm with that port. You'd be connecting directly into your OS (Mac in this case) to communicate with USB drivers etc.

    Andy Worsley89 said:
    All I want to do is send and receive data between the launchpad and the PC.

    You want to use the uart_echo TivaWare project then. That project does exactly what you want. You will send a message to the device, and it will echo it back to you. Then from there you can add intelligence. You can modify the program in a simple manner to check what you receive and then send data back. For exampe, you could adjust the application to that when you send it a message 'X', and the application reads the 'X', then it sends back 'Y'. And you can continue to build from there.

  • Hi Ralph,

    thank you for that. It's a lot clearer in my mind now. I was confused in thinking that the UART and USB were somehow internally linked together.

    I am going to have to have a conversation with my client to tell him that it will need additional hardware that has not been planned for.

    Just as a final point. If it is decided that we do want to use the 'device' USB port and talk to the host directly. Is there any kind of example project that does something like this, presumably using the USB library? Also are you aware of any application on a PC or mac that could do the host end?

    Thanks for all your help. I really appreciate it. I have done a ton of stuff with CAN, SPI and I2C, but USB was something of a black box to me.

    Regards

    Andy

  • Hello Andy,

    The usb_dev_serial example does actually show that piece, but with the added UART element. There were a couple ways to do the example for the USB communication. One would be to do it like a USB echo chamber where it would mimic uart_echo and you just bounce back the packet received.

    But since we had access to the USB interface, but also could use the Debug port for UART backchannel, the idea of using those to make a channel was more compelling. I can see how in your case it got confusing.

    That example hardware wise is:

    Debug Port Connection, UART Channel:

    Terminal Software (UART) -> USB Port -> USB Translator to UART via ICDI interface -> UART Peripheral on Device

    Device Port Connection, USB Channel:

    Terminal Software (USB) -> USB Port -> USB Peripheral

    Then what happens is the following.

    If you type a sentence into "Terminal Software (UART)" which is the Debug Port, it transfers to the UART peripheral on the device. The UART peripheral interrupts allow it to get the data, and it turns around and sends over the USB CDC (so writing to PC Host via USB). So at the end of this process, the sentence shows up as received on the "Terminal Software (USB)" which is connected to the Device Port.

    Then when you type a sentence into "Terminal Software (USB)", it sends over USB CDC to the device (so receiving/reading data from PC Host via USB), and again interrupt alert that data is received - this time for USB - and from there it takes that data and sends it over UART which goes through the Debug Port to the "Terminal Software (UART)".

    So the example as a whole does handle both TX and RX with USB CDC. It just adds an extra layer to the process with the UART piece.

    If you didn't want the UART interface, you would just replace all the UART stuff with handling to say 'when packet X is received, reply with data' etc.

    It's just not as compelling of a demo to have USB echo to itself when you can show the channel working as I described. :)

    Hopefully that helped demystify the hardware and how the channels were run.

  • Hi Ralph,

    Thanks for that. It helps a lot.

    Sorry, just one more question. You mentioned that the debug circuit provides not only the debug interface but the USB to UART bridge as well. I presume it is possible to divorce these two functions and just have a simple chip to do the bridge and have the debug interface off the board?

    Regards

    Andy

  • Hello Andy,

    Yes it is, the Stellaris ICDI debug interface is fairly unique. We use another TM4C MCU to run code to handle providing Debug + Programming + USB-UART Bridge in order to provide our LaunchPad's cheap without needing external tools for debug.

    In a typical application you would have an IC dedicated to USB to UART bridging and then use a JTAG programmer like XDS200.

  • As this project is extremely cost sensitive I don't think the client would go for the XDS200. Could an XDS100 do the job?

  • Hi Andy,

    Yeah! We recommend the XDS200 as it is newer and more feature rich but XDS100 works well too. You can review our JTAG guide for details. https://www.ti.com/lit/pdf/spma075

  • That's great! Thanks very much.

    Regards

    Andy