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.

TM4C1290NCZAD: Problems with USB transmit buffer size, general USBBufferWrite

Part Number: TM4C1290NCZAD

Hello. I am trying to setup a data transfer for my device over USB. I have this functional, and transmitting to a Labwindow CVI GUI.

It is timer based, and set to 600 Hz. Before each call to USBBufferWrite I set a flag to block any other transmits from the timer. Then upon USB_EVENT_TX_COMPLETE event in my tx handler, I clear the flag. In this way I have setup a blocking transmit (though blocking may not be the right word, it will not allow multiple transmits at the same time in the buffer). I am sending a struct of my data and so I know the exact size of it (310 Bytes).

Setting my tx buffer size to the exact size of the struct was not enough, however, as the last few bytes were not making it to the USB host (the computer/GUI in this case) (only 309 bytes seen). This was fine with me, as I simply increased the buffer size to the next power of two (512) and transmitting data worked (at least singluarly, not 600Hz yet). Though, if anyone has a answer to why this didn't work, I would love to hear it.

I then experimented with increasing the speed to 600 Hz, and occasionally it became out of sync and not sending the full number of bytes from USBBufferWrite. This does not make sense to me as it should be blocking, and the tx buffer should therefore be enough to fit 310 bytes each time right?

Note, the only place the flag is cleared is in USB_EVENT_TX_COMPLETE, and the only place that USBBufferWrite is called is from that timer.

  • Hi Alexander,

      I will pass your question to our USB expert. He is currently on travel so please expect some delay in his response. 

      At full speed (12Mb/s or 1.5MB/s) the maximum bytes per milliseconds is 1216 taking into account the associated overheads during the transfers. I took the 1216 bytes from Jan Axelson's USB Complete book. You are trying to transfer 512bytes (based on your buffer size) at 600Hz rate and  that will translate to about 320 bytes per millisecond or 320 bytes per frame. I think it is within the theoretical limit. However, I'm not surprised there are other latency introduced in the MCU such as latency due to buffer management or interrupt. I think the PC USB host may also reserve some bandwidth for other transfers. Not sure if you have an USB analyzer to tell where the bottle neck could be. That will greatly identify the problem. If you don't have the USB analyzer, will you be able to tell at what frequency (500Hz or whatever?) the transfers can be reliably carried out. This will provide valuable information for our expert to analyze.  

  • I removed most everything from my code (other interrupts that could be interfering). Like this it ran for 16 hours at 600 Hz, on the GUI end it had 10 re-syncs (meaning it missed some of the 4 bytes of Sync Words at the start of each of the messages). But on the Firmware side it always wrote the full amount of bytes with USBBufferWrite. Can I be sure that when I use USBBufferWrite and it passes that number of bytes to the USB Controller, that it gets passed along to the host with no issue?. 

  • Hi Alexander,

      Glad that you made some progress. It looks like it is working mostly except the occasional re-sync. It seems to me that the re-sync issue is not directly related the USBBufferWrite but rather a hardware issue to investigate. The synchronization between the host and the device will be managed by the hardware. Can you repeat the same re-sync issue on the LaunchPad with the same program you have? Can you repeat the same issue on a different board you have? What if you change the USB cable?

      I'm also not sure if you are operating in full speed or high speed mode. You said 4 bytes of sync field. For full speed it is one byte only. Please see below full speed sync field which is a KJKJKJKK. 4 bytes sync is for high speed USB. If you have a high speed USB then you must be using an external USB PHY as the internal PHY inside the MCU does not support high speed. If this is the case, you will need to check your external PHY and hopefully seek some support from the vendor of which on the de-sync issue you are seeing. Is this a correct understanding of your operating condition? 

  • The synchronization I am referring to is a packet header of my own creation which has 4 sync words at the start. The GUI reads in the packet and looks at the first 4 bytes to see if they are Sync_words. I am using the internal USB controler, I have no external PHY.

    My setup:

    I have a composite DFU/CDC device. The CDC is setup for 

      Note: Baud=3686400

    Then each message I generate has a msg_header at the start.

    Currently unable to test on Launchpad, other board, or other cord. I can try this Tomorrow.

  • Alexander Wardlow said:
    Note, the only place the flag is cleared is in USB_EVENT_TX_COMPLETE, and the only place that USBBufferWrite is called is from that timer

     I tried perhaps the same basic flow control with even larger buffer (4096KB) via Boolean switch clear/set. It worked for a few transmits (UBS write buffer) then crashed every time. It made no logical sense why the Boolean switch would not work from the event message call back. Seemingly the host/client end point 0 control is asynchronous. The TX complete is said to serve no other USB protocol purpose, no kidding!

  • I have tried it on other boards to the same result. The main issue here seems to be that for some reason my Boolean/switch that should keep all transmits from happening at the same time, does not seem to be functional. Thanks to BP101 to testing this as well. 

    I have paused the board on a transmit and inspected the buffer. It begins with part of an end of a frame, then another frame, and most of a third. I do not understand how this buffer could ever have more than 1 frame, yet it does.

  • Hello Alexander,

    Alexander Wardlow said:
    Can I be sure that when I use USBBufferWrite and it passes that number of bytes to the USB Controller, that it gets passed along to the host with no issue?.

    That may depend on the size of the transaction. We've discovered not long ago about how the usblib has a quirk where due to the application not being able to tell the usblib beforehand how many bytes are being transmitted in the packet, that occasionally a zero-length packet is sent out incorrectly as the library believes it finished transferring data. This is because if the last packet was a max sized packet, a zero-length packet is supposed to be sent per USB standard. But if the data is loaded in too slow, then the usblib fires one out early as it doesn't know when the transfers are actually supposed to be finished.

    This hasn't seemed to cause any real issues though, a few other customers had seen the behavior in the past but we never understood why until recently and it never impacted their applications negatively.

    Perhaps that is the behavior that is causing the re-syncs you are observing.

    If you are using USBBufferWrite, you should be able to avoid these ZLP's from occurring by placing this call in front of your USBBufferWrite API.

            while (USBDCDCTxPacketAvailable(txBuffer.pvCBData) == 0);

    See if that solves the re-sync issue.