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.

USB bulk with speed higher than 64 KB/s with LM4F

Hi,

I'm new to USB and I'm trying to get more than 64 KB/s (more than 1 packet per frame) using bulk transfer.

I'm using the usb_dev_bulk example to which I already have made some modifications: increased the size read on the PC side and increased BULK_BUFFER_SIZE on the LM4F side.

I currently have 408 kbps of data (64 KB/s - 13 KB/s for the header) and I can see that I'm getting a packet every 1ms (highest speed with full speed).

I noticed that the LM4F is sending an empty packet after every packet in order to finish the transfer. I need to be able to send other packets before this empty packet.

Does anyone have any idea on how to do that?

  • For higher speeds, full packets (64 bytes) must be used. If less than 64 bytes in packet are transferred, system (Win driver for example) will not send more than 1 packet per frame.


    With MSP430F5xx, I have 1 MB/s for generic bulk transfer, and over 800 KB/s for CDC, so I believe that is possible to have the same (or higher) rate with LM4F.

  • I'm aware of that. I'm sending the data of the CAN bus (1 Mbps) over the USB. When debugging it, I can see that I'm losing big chunks of data when the USB Tx buffer is full which I've increased to 4096 bytes (so big enough). Furthermore, the USBBufferWrite function returns me 0 meaning it has no more space left. I'm guessing that I missed one buffer size to increase or something like that but right now no idea.

  • I am not using TI USB stack for MSP430, and never seen LM4F USB stack source code.

    From your description, it seems like only one endpoint buffer is used. Data are storing in endpoint buffer, and after/during sending (flush), it is not able to receive/prepare/store new data to USB buffer. Or sometimes not-full (endpoint) packet are sent, and this limits transfer rate.

    When you are working with USB, where data (that will be sent over USB) coming in constant time interval (like from your CAN bus 1Mbps), data for sending must be stored in buffer, and there must be always free space in buffer. Best way is to store data directly to USB EP buffer memory, and just change EP pointer before sending. For me it is better to do this without XY double buffering, because XY will make more complicated (slower) code.

    BTW, I made MSP430F5xx based USB-Uart bridge (not based on TI USB stack), that is able to work at +2 Mbps, so 1 Mbps with LM4F can't be problem.

  • Only one endpoint is used indeed. I've been playing a bit with the usblib given for the lm4f and it seems that it is indeed a problem of USB buffer being not ready or something like that. They calculate the contiguous data in the USB ring buffer and somehow it returns 0 after sending one packet leading to a stop in the transmission. If I trick this value to be non 0, I have a speed of around 2 Mbps with the USB. Still unsure of what I'm doing wrong there or if this is a yet not fully tested code...

    I don't know if anyone has already being using the stellarisware libraries with USB and with full speed.

  • TI (USB) source code is good starting point, but for the real thing, you must do your own code. Your project can be done for sure (because I done almost the same thing on 24 MHz MSP430F5xx), but it is not simple at all. Problem is that system must be ready to receive data form CAN anytime, and send it (in parallel without disturb receiving) over USB when EP buffer is full (N*64) or in case of timeout (flush it).

    Here is topic about my MSP430F5xx USB-Uart bridge: http://forum.43oh.com/topic/3350-msp430f550x-based-usb-uart-bridge/

  • I'll have to take a look at this. Unless you've called USBBufferZeroLengthPacketInsert(), the USB buffer should never insert any zero length packet into the stream, even if the transmit buffer is empty when the previous packet is sent. If you are seeing these packets sent all the time, either there's a bug in the buffer code or the data is being provided to the transmit buffer slowly enough that there is never more than 64 bytes present at a time.

    Could you provide a bit more information on how you have the USB bulk device structures configured and what your PC-side code is doing so that I can set up a similar device to test this out?

  • I had a quick look in the code and it shouldn't insert any ZLP. I'm using Logman to trace the USB information but I'm guessing it is not reliable as it tells me there is a ZLP after each data and it always says that I receive only one packet with 32 bytes of data at a time (and I'm now capable of sending multiple packets). I would therefore not trust this tool.

    The issue I'm having seems to be linked to interruptions from the CAN bus. I'm now first filling the buffer and then requesting it to be sent. If I do the request in the CAN interruption, I'm roughly around 400 kbps but if I do the request in the main loop, I'm roughly around 1400 kbps.

    I'm still not fully understanding this but at least I'm now able to get 19 packets per frame. The issue I'm now having is that it is not quick enough (only sending a frame every 6ms) meaning that I will need to optimise things.

  • I'm glad things are looking better for you. I still need to look into this and possibly update our example application (which is based on sending user-entered strings and is, therefore, dealing with very low data rates). Several people have reported problems transferring more than 1 packet per frame so it would be good to have an example that achieved something close to the maximum throughput of the USB.

  • The thing I did was to take the usb_dev_bulk code and merge it with the can_fifo code. I did some modifications but the configuration of the USB stayed the same. In order to increase the throughput, I changed the BULK_BUFFER_SIZE on the LM4F side and the ECHO_PACKET_SIZE (to 1216) in the usb_bulk_example (PC side). A part from the ECHO_PACKET_SIZE, the software on the PC side is the same (run with -e mode).

    For sending the data over the USB, I had issues with the USBBufferWrite function (maybe because of interruptions) so I used the ring buffer (gotten via USBBufferInfoGet) to write data (via USBRingBufWrite) directly in the CAN interruption and in the main loop, I sent the data over the USB (via USBBufferDataWritten).

    This is the general idea of what I did.

  • johan marx said:

    The issue I'm having seems to be linked to interruptions from the CAN bus. I'm now first filling the buffer and then requesting it to be sent. If I do the request in the CAN interruption, I'm roughly around 400 kbps but if I do the request in the main loop, I'm roughly around 1400 kbps.

    I'm still not fully understanding this but at least I'm now able to get 19 packets per frame. The issue I'm now having is that it is not quick enough (only sending a frame every 6ms) meaning that I will need to optimise things.

    Storing data to EP buffer must be triggered by CAN interrupt. Sending data from LM4F to PC (flushing EP buffer) is not completely related to CAN interrupt. Sending must be triggered if EP buffer is full (CAN interrupt), or in case of timeout (no new data from CAN and EP buffer is not full) using timer interrupt. Sending must go completely in parallel without disturbing arriving new data from CAN. It can be done by using X/Y double buffering or by toggling pointers to EP buffer without double buffering.