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.

UDB bulk transfer issue



Hi,

I am using TIVA4c123 to communicate through USB with an application in my laptop (that uses libusb).
The laptop is the HOST.

I have defined a number of transfers so the HOST asks/sends data to my device.

I am using TIVAware libraries and the USB communication is bulk.

Everything works really fine, I have all the check for errors and I never have errors in both sides(HOST/DEVICE).
There are 2 main transfers:

1) the HOST continuously request a specific data to the device (18bytes)

2) the HOST send asynchronously a command to the device to activate some functions

My problem is that sometimes when I send the transfer 2) I receive the COMPLETION of the transfer 1) with the data buffer of the transfer 2  + I receive the COMPLETION of the transfer 2 but with wrong date in the buffer. It does not happen always but let me say....every 5-10 times I send the transfer 2). This happens without any errors.

I spent a lot of time on the SW (laptop side) to make sure the transfer 1 and 2 can't be requested at the same time....so transfer1 can be done only if tranfer2 is completed and vice versa.

Looking at the local buffer used on TIVA side, the data are always sent correctly...so..something happens a lower level in the Tiva USB driver...somehow the 2 transfers are mixed. I use USBBufferFlush for the TX buffer before to use it and for the RX buffer after buffer has been read. I use USBBufferRead/USBBufferWrite to read/write the buffers...

If somebody has experienced a similar issue or has suggestions...I am running out of ideas...

These are the libraries I am using:

#include "driverlib/usb.h"
#include "usblib/usblib.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdbulk.h"
#include "usb_bulk_structs.h"


here below and ide of what happens HD (host->device) DH (devce->host). This is while I ma monitoring transfer #2.

HD-----> "1" "0" "1" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "1" "0" "1" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"

HD-----> "1" "0" "0" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "1" "0" "0" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"

HD-----> "1" "0" "1" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "1" "0" "1" "1" "0" "40" "39" "4" "5" "0" "4" "0" "0" "0" "0" "0" "0" "0" "0"

HD-----> "2" "0" "1" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "2" "0" "1" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"

HD-----> "2" "0" "0" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "2" "0" "0" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"

HD-----> "2" "0" "1" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----> "2" "0" "1" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0"          <------- this is tranfer #1 length and tranfer #2 data
DH<----- "0" "0" "0" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"     <------- this is tranfer #2 with wrong data (it should match the HD).

HD-----> "2" "0" "0" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"
DH<----- "2" "0" "0" "1" "3" "40" "11" "12" "5" "0" "8" "0" "0" "0" "0" "0" "0" "0" "0"

  • Gianluca Allegretto said:
    I use USBBufferFlush for the TX buffer before to use it and for the RX buffer after buffer has been read.

    Sound like USBBufferFlush() causes unexpected result.
    Usually without this API call, the things should work well.

    You may add another set of bulk IN/OUT endpoints to the device.
    Assign job 2) to the new endpoint set.
    And then, you wouldn't need to separate two jobs from the original single stream.
    It should make your control logic much simpler, in both sides (host and device).

    Tsuneo

  • Thanks , I will try that.
    I have a question, what happen if the HOST asks a bulk transfer before the previous has completed? It is not the case has I said I made sure that won't happen, but I was just wondering how this would be managed. Thanks
  • communicate through USB with an application in my laptop (that uses libusb)...
    I have a question, what happen if the HOST asks a bulk transfer before the previous has completed?


    On the host side,
    Synchronous call
    • libusb 1.0 - libusb_bulk_transfer()
    • libusb 0.1 - usb_bulk_write()

    Synchronous call doesn't return until the device gives "ACK" to the (last) transaction.
    And then, PC app can't send another call before the last call completes.

    Asynchronous call
    • libusb 1.0 - libusb_fill_bulk_transfer() - libusb_submit_transfer()
    • libusb 0.1 - usb_bulk_setup_async() - usb_submit_async()

    The second (and latter) transfer is kept in the PC driver's queue, until the last transfer finishes.

    On the device USB engine,
    When a bulk OUT transaction comes from host, and when the endpoint buffer is empty (primed), the USB engine gives ACK to the transaction (transaction complete).
    If the endpoint buffer is still occupied by the last transaction, the USB engine returns NAK to the host (ie. flow control). The host controller (hardware) repeats the last transaction until it gets ACK from device.

    On TivaWare's USB stack,
    USBDBulkPacketRead() reads out data from the OUT endpoint. When the ring buffer has enough empty space, this routine reads out the entire packet, and it primes the OUT endpoint for the next transaction. But when the space is less than the packet size, this routine partially reads out upto buffer full. The endpoint is kept in "occupied", until the consumer of the ring buffer would make the space for the rest data.

    Together with NAK flow control, in this way, TivaWare shouldn't drop any data from host (unless you would call USBBufferFlush ;-).

    Tsuneo
  • Thanks this is very useful, I am working on an improved design. Really appreciate the help.

    ...So, I have fixed the issue, I do not have issues with buffer data...very good.


    Now I have another kind of problem, I am driving an LED on the device to check(with the oscilloscope) the max speed I can send 18bytes from Host to device and receive them back.

    I see that I can't go lower that 1ms (H-D-H). THis is like 10 times slower that what I need. I am trying to understand if Host or device SW routines can be optimized to reduce that time..but to me it looks that most of that 1ms are due to the USB communication itself..I send and receive 18bytes data buffer ...and the data process  is really few lines of code (I tried to remove them and keep only the USB communication and I still have 1ms).

    I need to find a way to speed up. Any suggestions? I can pack the data in larger buffers...but this is not really what I would like implement as strategy.

    Thanks a lot for the support.

    G.