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 dev: additional isochronous endpoints (TIVA C launchpad/tm4c123g)

Question

Is it possible that when using USBlib to handle bus enumeration, device setup and providing an endpoint for application logic, to have another endpoint in isochronous mode employing DMA and automatic packet sending?

Proposed architecture

Will it work if I do the following:

  1. Use tivaware usblib to generate a bulk device, handle endpoints 0, and have endpoints 1 managed to have an easy-to-use communication interface
  2. Register endpoint 2 in isochronous mode via driverlib's usb interface
  3. Set up DMA to transfer data from ADC sequencer FIFO to endpoint 2 Transmit FIFO

Background

I have built an ADC application around USBlib bulk device methods. A timer triggers the ADC sequencer every 1600 cycles (the processor running at 100MHz), and after the sequence has finished, the ADC interrupt routine empties the sample FIFO, writes that into a ring buffer.

Simultaneously, the main loop polls the sample count, and if that threshold passes 32, I notify USBlib that 64byte have been written to the ringbuffer, triggering the sending of a packet.

However, when using sequence triggering more often than every 1.6ms (62.5kSam/s), I encounter sporadic ADC FIFO overflows. I assume it is because to the software-based data shuffling that takes place when a transfer is about to happen, happening so that ADC interrupt handling is disabled for the meantime, leading to 2 missed interrupts and a FIFO overflow in the consequence (sequence is 4 samples deep, FIFO is of length 8).

In an attempt to solve this, I'd like to use the DMA engine to automatically get 4x 16bit from the ADC FIFO register and store it in the USB endpoint transmit FIFO; the driverlib usb functionality documentation says the DMA controller is able to do exactly that and that would be much better than the software-buffer driven approach I employ now.

Furthermore, since this is the nature of my application, isochronous mode should be used.

Anyway, I'm afraid that the Driverlib's USB interrupt handler will mix up USB interface and DMA-generated interrupts.

Bonus question

How to make the device appear as USB2.0? Although the tm4c123g datasheet claims USB2 compliance, but to the host it registers as bcdUSB = 1.0 .

  • However, when using sequence triggering more often than every 1.6ms (62.5kSam/s), I encounter sporadic ADC FIFO overflows.


    The problem lies in the host side.
    Does your PC application read the bulk IN pipe with a 64-bytes buffer synchronously?
    Then, it’ll choke up the bulk transfer speed.

    On your PC app,
    a) Claim more transfer size (for example, 1024 bytes) for the single "read" call.
    OR
    b) Put another "read" call(s) asynchronously, without waiting the completion of the last call.

    And then, you’ll get much better bulk transfer performance, without any change on your firmware.

    PC host controller (HC: hardware) defers transfer completion interrupt until the next SOF timing.
    - When your PC app puts just a 64-bytes read calls, your app should wait for the next SOF, to send another call.
    - When your app puts a read call of greater size, PC HC splits the transfer into 64 bytes transactions, and HC passes the transactions to your device. In this way, your device gets more 64-bytes transactions in single USB frame. When HC gets the entire transfer, it returns received transfer to your app.

    Tsuneo

  • Claim more transfer size (for example, 1024 bytes) for the single "read" call.

    Already doing that, and increasing read size does not help.

    I do check for ADC overflows and they happen, my ringbuffer never overflows, so it's not that my data is received too slowly by the host.

    Also, I really want to use the DMA engine since it's there and if it works as documented would completely offload the sample copying off my CPU, which is very desirable since I originally intended to do more with my cortex than just copying uint16's from FIFO a to FIFO b  ;)