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.

C6747 USB0 CPPI DMA

Hi,

I am attempting to get CPPI DMA transfers to work with USB0 in peripheral mode. The USB interface configuration and initialization seems correct: CPU-based transfers (CPU reads/writes the endpoint Fifos) work without problems.

I tried to work through the documentation, but lots of questions remain. Especially the demo code on page 81+ in sprufm9f uses undefined constants and memory regions. Even invalid register definitions are used in this code - at least not compatible with the current CSLR - has this code ever been actually tested? Is any other example code available?

Our example is quite simplistic: a single message should be transmitted via EP1-IN in transparent DMA mode. I therefore configured the CPPI registers, configured the endpoint for DMA,  and set-up a single HPD descriptor. But no output is produced when this descriptor is enqueued. Also the descriptor is not returned in the completion queue. BTW: The same message written to the EP1 fifo by the CPU is transmitted correctly.

Many thanks for your assistance!

Best Regards,

Adolf Klemenz

 

 

#define CPPI_NUM_DESC    32 /**< number of available descriptors for CPPI */                                 

typedef struct CPPIDesc
{
    uint32_t          HPDword0;
    uint32_t          HPDword1;
    uint32_t          HPDword2;
    size_t            HPDword3buffLength;
    void *            HPDword4buffAdd;
    struct CPPIDesc * HPDword5nextHBDptr;
    size_t            HPDword6orgBuffLength;
    void *            HPDword7orgBuffAdd;
} T_CPPIDesc;

#pragma DATA_ALIGN (cppi_desc, 32);
T_CPPIDesc cppi_desc[CPPI_NUM_DESC];  /**< HPD/HBD descriptors */

uint32_t cppi_linkram[CPPI_NUM_DESC] = {0}; /**< reserve memory for linking ram */

  /***************************************************************//**
    configure transparent DMA transfers
  *******************************************************************/
   usb_otgRegs->CTRLR &= ~0x00000010;  // Global RNDIS disable
   usb_otgRegs->MODE = 0;  // all endpoints in transparent DMA mode

  /***************************************************************//**
    configure Queue Manager and Linking RAM
  *******************************************************************/

  usb_otgRegs->QMEMREGION[0].QMEMRBASE = (uint32_t)cppi_desc;
  usb_otgRegs->QMEMREGION[0].QMEMRCTRL = 0;  /**< 32 descriptors, size = 32 bytes, index = 0 */
  usb_otgRegs->QMGR.LRAM0BASE = (uint32_t)cppi_linkram;
  usb_otgRegs->QMGR.LRAM0SIZE = CPPI_NUM_DESC;           

  /***************************************************************//**
    enable DMA for transmit endpoint 1, use queue 24 for completion
  *******************************************************************/
  usb_otgRegs->DMA_CTRL[0].TXGCR=(0x80000000 | 24);  

  /***************************************************************//**
    configure the CPPI scheduler: only one Tx EP is used (EP1-IN)
    enable scheduler
  *******************************************************************/
  usb_otgRegs->DMA_SCHED.ENTRY[0] = 0x01;  // endpoint 1 transmit: 1 credit
  usb_otgRegs->DMA_SCHED.DMA_SCHED_CTRL = 0x80000000;

  /***************************************************************//**
    setup HPD for a single transfer
    @note: strlen(usb_msg) <= max_packet_size
  *******************************************************************/
  cppi_desc[0].HPDword0 = 0x80000000 | strlen(usbtx_msg);
  cppi_desc[0].HPDword1 = 0x08000000;      // source = EP1
  cppi_desc[0].HPDword2 = 0x14004000 | 24; // 24 = completion queue
  cppi_desc[0].HPDword3buffLength =
  cppi_desc[0].HPDword6orgBuffLength = strlen(usbtx_msg);
  cppi_desc[0].HPDword4buffAdd =
  cppi_desc[0].HPDword7orgBuffAdd = usbtx_msg;
  cppi_desc[0].HPDword5nextHBDptr = NULL;

  /***************************************************************//**
    configure endpoint for DMA and enqueue HPD
  *******************************************************************/
  usb_otgRegs->INDEX = 1;
  usb_otgRegs->TXCSR.PERI_TXCSR &= 0x7FFF;
  usb_otgRegs->TXCSR.PERI_TXCSR |= 0x1400;

     usb_otgRegs->QCTRL[16].CTRLD=(uint32_t)&cppi_desc[0] | 2;

 

  • Follow-Up:

    I found an error in the documentation

    in sprufm9f, pg. 90, the sample program defines a function to enable CPPI-DMA for an endpoint:

    void enableCoreTxDMA(Uint16 endPoint)
    {
      Uint16 index_save;
      index_save=usbRegs->INDEX;
      usbRegs->INDEX=endPoint;
      usbRegs->TXCSR.PERI_TXCSR&=0x7FFF; // Clear AUTOSET
      usbRegs->TXCSR.PERI_TXCSR|=0x1400; // Set DMAReqEnab & DMAReqMode
      usbRegs->INDEX=index_save;
    }

    This is a bug: according to the PERI_TXCSR documentation on pg. 126 AUTOSET must be set for DMA mode.

    After setting AUTOSET in my program, DMA transfers now work:

      /***************************************************************//**
        configure endpoint for DMA and enqueue HPD
      *******************************************************************/
      usb_otgRegs->INDEX = 1;
      usb_otgRegs->TXCSR.PERI_TXCSR |= 0x9400;

         usb_otgRegs->QCTRL[16].CTRLD=(uint32_t)&cppi_desc[0] | 2;


  • W.r.t CPPI DMA implementation Autoset and Autoclear feature should not be used.  CPPI DMA engine manages that.  The spec is correct.  For further reference pl. refer to the linux usb driver found under "drivers/usb/musb" directory in the Linux kernel package that accompany the OOMAPL13x release.

    regards

    swami

  • Dear Swami

    many thanks for  your reply. 

    Which spec is correct? The sample program clears AUTOSET, and the register description claims  the CPU must set AUTOSET before DMA is used - all within the same document. Furthermore, with AUTOSET cleared no data is transmitted in my test program - why? Is anything else wrong in my setup?

    This part of the documentation *definitely* needs clarification.

    Please also understand that I am not in the mood to work myself through Linux driver code. I expect a consistent and meaningful documentation in the User's Guides - after all this device has been available for more than one year, and the USB documentation meanwhile is revision "F".

    Best Regards,

    Adolf Klemenz

     

  • Adolf,

    The intent on my part for pointing out to the Linux Driver source code is for enabling you with a working reference that is well tested and one that other customers are using today.

    Agreed there are inconsistancies in the documentation that need to be corrected.  We will focus on the same at the earliest.  My response on the Autoset/Autoclear is still correct.  These bits should be left cleared.  The reference to these bits need to be set is based on Mentor original spec (when using Mentor DMA).  On TI platforms we use CPPI DMA and that recommendation does not apply.

    Appreciate your feedback.

    regards

    swami

  • Dear swami,

    finally I was able to get a working example with both transparent and RNDIS DMA mode. You are correct: AUTOSET needs to be cleared. The problem was caused by another misleading part of the documentation: The example on page 73 of sprufm9f states: "It then adds (pushes) the PPD and the two PBDs to the TXSQ". This is also shown in the diagram on page 72.

    If I follow these instructions, the transmission halts after a few packets in transparent mode, unless AUTOSET is '1'. I then figured out that it is not necessary to push the PBDs onto the Tx-queue, it is sufficient to enqueue the packet descriptor only.  After all this makes sense, since the packet descriptor already contains the link information to the next buffer descriptor. After changing this and enqueing the PPD only everything worked well with AUTOSET = '0'.

    Another issue: according to page 69: "RNDIS mode DMA is used for large transfers (i.e., total data size to be transferred is greater than USB MaxPktSize where the MzxPktSize is a multiple of 64 bytes) that requires multiple USB packets". This leads to the assumption RNDIS cannot be used for data transfers < MaxPktSize. However, I could not detect any problem with RNDIS for small data sizes.

    Many thanks and Regards,

    Adolf Klemenz

     

     

  • Adolf,

     

    I am required to develop our own C674x USB driver. Our requirements are simple: Single bulk-IN and single bulk-OUT.

    May I ask what is your status? Is there an option to cooperate regarding this issue?

     

    Best regards,

    Uri

     

    Please feel free to contact me directly at:      uri at zoro-sw dot com

     

     

  • Dear swami-san

    I'd like to ask you a favor.

    I've read this forum and I think there are a  lot of misprint in the USB document SPRUFM9.

    So, could you please revise and release it A.S.A.P. or summarize the misprint somewhere in TI web?

     My Customer said "It's difficult to development our product using this document!!!".

    Thanks in advance for your cooperation.

    Best regards,

    j-breeze