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.

C674x USB0 CPPI DMA problem

I have managed to get the USB to work, enumerating and successfully transferring data to and from the DSP using interrupts to (un)load the FIFO. I have managed to achieve a good throughput of 30MB/s using a CDC-ACM device profile on Windows with a custom CDC-ACM driver, but naturally wish to take advantage of the DMA to reduce the load on the CPU.

To do this I have taken advice TI has given to develop slowly, so I have replaced the interrupt based DSP-to-Host communications with DMA based code, using RNDIS. The code utilises only a single host packet descriptor, and pushes it onto the dedicated transmit queue (16) and is set such that it is returned on the dedicated tx completion queue (24). This causes an interrupt on completion where I check the completion queue and when the/a descriptor is able to be popped then the next packet to be sent is processed, thus there is only one packet in the DMA at a time. This works well in simple circumstances, such as sending one to three packets consecutively. In these case the packets are received at the host in the right order and the DMA does not 'lock up'. However, if I attempt to send more consecutive packets back-to-back, I experience two problems.

1) The first is that after about packet 4 or 5 the packets can be received out of order, for example I am sending a sequence of packets 1, 2, 3, 4.... e.t.c. and from packet 4 onwards the packets are occasionally swapped, for example I might receive packets ....6, 8, 7, 9, 11, 10, 12, 13, 15, 14.....   I have managed to insert a delay between transmissions, which prevented this behaviour with smaller packets, but eventually I am resorting to waiting until the PERI_TXCSR registers FIFONOTEMPTY bit is cleared. This fixes this problem, but is not ideal as it is a busy-wait behaviour inside an interrupt which is fine whilst testing, but not in production code. It also makes me question what is the correct behaviour should be with respect to the handling of the descriptors when returned from queues?

2) The second is that I also intermittently see the DMA not returning the host packet descriptor. For example I will push the descriptor to the tx queue and it is never returned on the completion queue. Since my device is running as a virtual com port I am able to open various terminal programs allowing for the DSP to Tx the data to the host, but no data arrives and neither does the descriptor on the DSP. I have used PC based USB sniffer to look at the transfers when this occurs, and I think it has always shown the all data to have been transferred and received by the host.


I am most welcome to try out ideas and to provide more information, but I am currently at a loss.

 

Peter

 

Ps. I am aware of the GRNDIS bug, which is why I am using the RNDIS mode.

PPs. I have tried toggling the queue the packet is placed onto, but both problems persist.

PPPs. I have tried testing the queue pend bit to see if a packet descriptor arrives, but is miss-read, and the QSTATA entries count in a similar vane, but with no success.

 

Normal 0 false false false EN-GB X-NONE X-NONE MicrosoftInternetExplorer4


Tel: +44 (0)23 8076 7808 Fax: +44 (0)23 8076 0602
Web: http://www.macltd.com/  Email: peter.myerscough-jackopson@macltd.com
MULTIPLE ACCESS COMMUNICATIONS LIMITED is a company registered in
England at Delta House, The University of Southampton Science Park,
Southampton, SO16 7NS, United Kingdom with Company Number 1979185 and
VAT Number GB 411942866

  • To add to detail to the second issue, when I stop receiving data I am also seeing an error on the USB bus of 0xC0000012, which is a "Babble Detected" error, meaning that the USB is sending more data than the Host is expecting. This error is instantly triggerable if I try to send a packet with more than 512 bytes. I am currently setting up the TXMAXP register to be 512, and I set the packet descriptor as follows:

    -----------------------

      *(uint32_t*)(&packetDesc->HPDword0) = 0x80000000 | bytes;
      *(uint32_t*)(&packetDesc->HPDword1) = 0x08000000; // source = EP1
      *(uint32_t*)(&packetDesc->HPDword2) = 0x14000000 | 24; // 24 = completion queue, packet type = 5 = 0x14000000
      packetDesc->HPDword3buffLength =
      packetDesc->HPDword6orgBuffLength = bytes;
      packetDesc->HPDword4buffAdd =
      *(uint32_t*)(&packetDesc->HPDword7orgBuffAdd) = (uint32_t)buffer;
      packetDesc->HPDword5nextHBDptr = NULL;

    where "bytes" is the number of bytes in the buffer and "buffer" is a pointer to a buffer containing data I wish to send.

    -----------------------

    This sends packet on endpoint 1 correctly as long as the packet size is less than 512.

    (I am using the structure as given in the example use cases in the USB guide document.)

     

    Hope this can trigger some idea of what I may be doing wrong,

     

    Peter

     

     

  • Peter,

    A good reference is the linux usb driver.  Pl. refer to the drivers/usb/musb/cppi41_dma.c/.h for the actual imlementation.

    regards

    swami

  • Swami Thanks for pointing me to this reference I had been looking at a cppi_dma[.c|.h] in the linux source as reference and was unaware of the separate cppi41 version. I note that the CPPI41 version uses the Generic RNDIS method, which the errata for the C6748 states that mode has some issues, so I have been avoiding it, so I am left with the transparaent mode. I have therefore given up with using DMA on the chip, but thank you for your assistance.

    Peter

  • GRNDIS mode has an errata against it when operating in device mode.  In host mode GRNDIS is the prefferred mode.

    In the L138 linux reference we use Transparent mode when in Device mode.  But depending upon your app needs you could ideally use GRNDIS mode even in device role.  If your IO size does not change then GRNDIS mode can be used.

    regards

    swami