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.

some question about TMS320C6747's USB function.

Other Parts Discussed in Thread: TMS320C6747, DA8XX

some questions about TMS320C6747's USB2.0 perpheral. reference document is
"SPRUFM9F".

Q1:AT document P77. It mentioned that CPPI4.1DMA may genernated Interrupt
which indicated that
   1)DMA Tx Completion [3-0]
   2)DMA Rx Completion [3-0]
where are the Interrupt Status Register for these interrupt sources?

Q2:AT document P67. It says the DMA interrupt do not use PDR interrupt handler
, Does that means I can't use INTSRCR, INTMASKEDR...? because in the register'
s reference infos, It mentioned that these registers are all used for PDR
interrupt handler.

Q3:At document P67. It says
"The firmware needs to use queues not reserved by hardware as Completion
Queues, if required for the DMA interrupt to be generated on a completion of
a transfer."
I think this sentence may be wrong. the right expression should be:
".... use queues reserved ...", because only the reserved queue, like 24,25
can generate interrupt. right?

Q4: think of this use case:
   Assumptions:
   1.USB2.0 work in host mode.
   2.linked device's max package size = 64 Bytes.
   3.host initiate a single Tx transfer with packet size = 608 bytes.
Can I set the Host Packet Descriptor's data buffer size to 512?(which is
bigger than max package size of Device)
In document P71, I know a smaller value is acceptable.

  • Hi,

    A1. This is wrong on the User's Guide. Sorry about that. Will correct this. Thank you. Info pertains to the old CPPI DMA. The DMA Completion fields do not exist. Please disregard. As far as DMA Interrupt handling is concerned please see the sections on "Allocation Queues" and "CPPI DMA Transfer Interrupt Handling".

    There exists no DMA Interrupt Flag/Enable/Disable type of Register/Field. Instead there exists dedicated Queues that can be used by the user and when transfer completes, the DMA will post the Descriptor that pertains to the transfer within the Chosen Queue by the user. If this chosen queue is one of the queues that generates interrupt, then interrupt will be generated. This interrupt can only be gated at the CPU Interrupt Handler level if a Queue that generates interrupt is chosen.

    A2. The answer for this question is also present within the answer given above. No DMA Interrupt Flag/Enable/Disable Register exists. Instead, by using dedicated Interrupt generating queues, you can use this option as Interrupt enable/disable functionality. As a supplement to the Interrupt flag you can use the Queue Manager Pending Register.

    A3. You are right this is very ambiguous. The Contest reserved by h/w here was to mean as the submit queues for transmit purposes. You can not use any other queues for Transmit submit purpose. However, completion queue you can use any queue other than the queues reserved for transmit submit queues. From the angle you are looking at it, completion queues are also special queues and can not be used as submit queues and generate interrupt. For this reasons, you can treat it as a reserved queue. Will correct this too. Thank you very much.

    A4. Regardless the role that the core assumes, if you set your max USB packet size, Tx/RxMaxP, with a value corresponding to 64 bytes and the DMA is set to transfer 608 bytes, the DMA and the core will handle the transmission of your 608 bytes packet 64 Bytes at a time. The Host Packet Descriptor is the first packet descriptor and is used for all outgoing DMA packets. The first word has a field that holds the total data to be transmitted. For this example, you program that field with 608 Bytes. Remember that the USB Max Packet Size and the DMA Packet size are not the same. The DMA Packet size refers to the transfer size. If you desire to chop the transfer size (DMA packet size) into 512 USB packet size, then you program the Tx/RxMaxP with a value that program 512 bytes.

    Thank you.

    Best regards, Zegeye

     

  • Hi,Zegeye,thanks a lot for your answers, That is very helpful. But I still have some questions here:
    Q2.1 The interrupt event No.(IEN) of USB0's CPPI DMA is 19, is that right (same as USB0’s common IEN)?
    Q2.2 What the meaning of  "gate" in your answers A1? You mean mask? Or just imply that this interrupt can not be disabled?
    Q2.3 From answer A2, you mentioned a register called queue pending register. The document has very simply infos about these registers. Here is my guess: if this is a transmit queue, then if we push a descriptor into it, then the pending register bit of that queue is set; For complete queue, if a descriptor generated and push in, then the pending register is set. Is that right?
    Q2.4 For answer A4. I think you misunderstood me. What I confused is not the "package size", but Host buffer descriptor's "buffer size". When Tx/RxMaxP is 64bytes. Can buffer size biger than that?Can It smaller than that?
    It has taken me for a week to integrate CPPI DMA function into my project. I am very frustrated. :(

  • Hi,

    A2.1. I believe you are referring to the Interrupt Event # on the CPUs (for ARM it is event #58 and for DSP it is event #19). All USB interrupt generating events are logically ORed to cause the CPU event change. The specific USB event that caused this change will have to be determined by the ISR by reading more of the USB Interrupt related registers. You will need to know the event number so that you can bolt on your interrupt handler. Having said that, you can choose to ignore interrupt being sourced from the USB controller at the CPU level by enabling/disabling the interrupt at the CPU level. Usually, you would want to disable interrupt at the USB core level too, if you desire interrupt not being generated. Remember that you will have to clear some of the interrupt status bits so that you can be able to recognize new status changes. For DMA you will make use other completion queues that would not generate interrupt, that way, you would gate/disable interrupt generation if you desire not to receive one.

    A2.2. Yes, by gating I meant to refer to disabling interrupt.

    A2.3. You are correct with a slight more detail. For Completion, regardless with the direction of the transfer, the Queue Manager will be the one pushing Descriptors address on to the Completion Queue. When this happens the corresponding bit within the PEND register gets set. When you are submitting Transmit and Receive tasks, you will be the one pushing Descriptors Address onto the submit queues and that would set the corresponding bit.

    The Pending bit get set when a Descriptor address is loaded in a queue and the corresponding bit gets cleared when the Descriptor address is offloaded from the queue, by reading it. One way to check if receive or transmit transfer has completed is by checking the bit that corresponds to the desired Completion queue for that particular transfer. If a user is not using the reserved completion queues or have not enabled interrupt at the CPU level (see answer A2.1), a user can make use of this register information to determine a completion event by polling on to the bit field corresponding to that particular queue. Ther is also another way to determine completion by polling. Another polling method is by performing a pop action onto a Completion queue. Since you start out with an empty Completion queue, when you perform a pop, unless a transfer has completed, you will be reading a ZERO address from the Completion queue. When the transfer completes, the Queue Manager will push the Descriptoror Address onto the Completion Queue; then after, when you perform a pop action after the completion has taken place, then you will be reading a Descriptor address instead of a ZERO address. Note that a read on to a queue performs a poping action and succssive read will result a Zero value to be read.

    A2.4. Remember that Descriptors are nothing but a set of information describing buffers with some control and status information. You start up with selecting the type of transfer you would desire to use, see CTRLR and MODE registers descriptions. The DMA will use the transfer type selected here and will perform the transfer accordingly. The DMA and the USB core will handle the right packet size to use based on your Tx/RxMaxP register entered.

    Suppose you want to transfer 130 bytes of data and you have selected a Tx/RxMaxP settings for 64 Bytes. Suppose you want to transfer this data in RNDIS mode. This means that you would will be seeing 3 USB packets on the bus where 2 of the USB packets would have the size of 64 Bytes each and the last short packet would have a size of 2 bytes in length.

    You are the transmitter and this means that you would know the total size of data to be transferred. This means that you would require a Packet Descriptor as your 1st Descriptor. If this Packet Descriptor does not define a data buffer long enough, then you would require additional Descriptors (Buffer Descriptors). You should also insure that these Descriptors are all chained properly. However, if you happen to be a Receiver, you would not know the size of the data to be transferred, and all you will have is Buffer Descriptors.

    Going to the example, your 1st Descriptor should be a Packet Descriptor since you will have to communicate with the DMA the transfer size and WORD0 will have the total transfer size which in this case would be 130 bytes. However, the data buffer that this Packet Descriptor defines can be of any size; it is up to you. Let us assume it is referenceing 32 bytes. Then you will need additional Descriptors to reference the remaining 130-32=98 bytes. In order to reference the remaining data buffers, you will need Buffer (not Packet) descriptors. If the next Buffer Descriptor you are defining is describing data buffer less than 98 bytes, then you will need additional Buffer Descriptor to define the remaining bytes. Of-course, you will need to chain them up (by linking one descriptor with the other).

    As you can see, the data buffer can be less, equal, or greater. It is up to you. The DMA will know how many Descriptors to use based on the Transfer Size you entered on WORD0 of the 1st Packet Descriptor. If the data buffer defined on the 1st Packet Descriptor is not long enough, then it would expect to get the remaining data buffer information from a following Buffer Descriptor. It would identify this following buffer descriptor from the "Next Buffer Descriptor" field.

    To simplify your development effort, start with using a single Descriptor. Allocate more data buffer area than you need to be defined by the 1st Descriptor. For the above example allocate, a data buffer location that is greater than 130 Bytes to be referenced by the single (1st Descriptor). Zero out your Next Buffer Descriptor address since you require no additional data buffer. Once you get this working, then you modify your code to use multiple Descriptors, i.e., if scatter/gatther capability is desired (this is the case where the data you are transfferring is not residing in contiguous manner).

    Please try to understand each of the sample code initialization part of the task and let me know which part you do not understand and I will help you fix your problem. There is not much with the CPPI DMA. Really, it is not that difficult. However, it looks complicated and complex for the 1st time. Just understand the initialization part of the code and the part that you need to create Descriptors and you should be good to go. Send me a high level transfer requirement and I will help you set up your code.

    Hope this helps.

    Best regards, Zegeye

     

     

  • Hi again,

    I did see your question better now.

    A2.1. Yes. When you use the Completion Queues that generate interrupts, the interrupt from the USB gets to the CPU through Event #19 on the DSP.

    Best regards, Zegeye


  • /*alloc descriptor*/
    //----------------------------------------------------------------------------
    int InitSingleHPDorHBD(U16 descNum, DATA_DIR dir, DESC_TYPE desc,
      U16 returnQueue, CPPI_DMA_MODE cppiDmaMode, char ep, U8 **buf, U32 *bufLen)
    {
       int theOldBufLen = *bufLen;
      
       if(0 == *bufLen) return 0;
       if(*bufLen > sSinglePktLength) *bufLen = sSinglePktLength;
      
       if((desc==PACKET_DESC) && (dir==TRANSMIT))
       {
          //This value is always fixed. For Packet Type Decriptors=16
          sRegion0DescriptorSpace[descNum].HPDword0.HostPktType=16;
       }
       else
       {
          //Word0, Word1, and Half of Word2 are Reserved for Buffer Descriptors.
          sRegion0DescriptorSpace[descNum].HPDword0.HostPktType=0;
       }
         
       sRegion0DescriptorSpace[descNum].HPDword0.ProtSize=0;
      
       if ((dir==TRANSMIT) && (desc==PACKET_DESC))
       {
          if (cppiDmaMode==TRANSPARENT)
          {
             //Packet Length (For Transparent Mode this is <= Tx/RxMaxP Value. For
             //RNDIS or like it is = Tx/RxMaxP Value).
             if(*bufLen > sSinglePktLength)
             {
                sRegion0DescriptorSpace[descNum].HPDword0.PktLength =
                   sSinglePktLength;
             }
             else
             {
                sRegion0DescriptorSpace[descNum].HPDword0.PktLength = *bufLen;
             }
          }
          else
          {
             //Actual Packet Length: This is the size of the Packet noted at
             //descriptor level to be Transmitted.
             //This is different from the USB Max Packet Size. This is the total
             //data length.
             sRegion0DescriptorSpace[descNum].HPDword0.PktLength = *bufLen;
          }
       }
       else // This and other Packet related info will be updated by the PORT for
         //Receive and can be any value.
       {  
          // This is actual Packet Length. It will be populated by the Rx Port of
          // the CPPI DMA
          sRegion0DescriptorSpace[descNum].HPDword0.PktLength=0;
       } 
      
       //Always programmed to ZERO.
       sRegion0DescriptorSpace[descNum].HPDword1.DstTag=0;
       //Always programmed to ZERO.
       sRegion0DescriptorSpace[descNum].HPDword1.SrcSubChNum=0;
       //Always programmed to ZERO.
       sRegion0DescriptorSpace[descNum].HPDword1.SrcChNum=0;
       if(desc==BUFFER_DESC)
          //Word1 is Reserved for Buffer DESC.
          sRegion0DescriptorSpace[descNum].HPDword1.SrcPrtNum=0;
       else
          //Ports[1,2,3,4] is associated with Endpoints[1,2,3,4] respectively.
          sRegion0DescriptorSpace[descNum].HPDword1.SrcPrtNum=ep;
         
       //24 and 25 forTx - 26 and 27 for Rx Completion
       sRegion0DescriptorSpace[descNum].HPDword2.PktRetQueue=returnQueue;
       sRegion0DescriptorSpace[descNum].HPDword2.PktRetQM=0;
       //Descriptor is located beyond On-Chip
       sRegion0DescriptorSpace[descNum].HPDword2.OnChip=0;
       sRegion0DescriptorSpace[descNum].HPDword2.RetPolicy=0;
       sRegion0DescriptorSpace[descNum].HPDword2.ProtoSpecific=0;
       sRegion0DescriptorSpace[descNum].HPDword2.Rsv=0;
       if(desc==BUFFER_DESC)
          // Half of Word 3 is Reserved for Buffer DESC.
          sRegion0DescriptorSpace[descNum].HPDword2.PktType=0;
       else
          // USB Packet ID is 5
          sRegion0DescriptorSpace[descNum].HPDword2.PktType=5;
       sRegion0DescriptorSpace[descNum].HPDword2.PktErr=0;

       //single descriptor mode
       sRegion0DescriptorSpace[descNum].HPDword3buffLength=
         sRegion0DescriptorSpace[descNum].HPDword0.PktLength;
       if(0 == sRegion0DescriptorSpace[descNum].HPDword3buffLength)
       {
          sRegion0DescriptorSpace[descNum].HPDword3buffLength = sSinglePktLength;
       }
         
       sRegion0DescriptorSpace[descNum].HPDword4buffAdd=(U32)*buf;

       sRegion0DescriptorSpace[descNum].HPDword5nextHBDptr=0; //Current Descriptor
         //is the Last Descriptor: Null Value is used as the Next Buffer
         //Descriptor Address
       sRegion0DescriptorSpace[descNum].HPDword6orgBuffLength=
         sRegion0DescriptorSpace[descNum].HPDword3buffLength;
       sRegion0DescriptorSpace[descNum].HPDword7orgBuffAdd=
         sRegion0DescriptorSpace[descNum].HPDword4buffAdd;
        
        
       //return value
       *buf += sRegion0DescriptorSpace[descNum].HPDword0.PktLength;
       *bufLen = theOldBufLen;
       *bufLen -= sRegion0DescriptorSpace[descNum].HPDword0.PktLength;
       return *bufLen;
    }

    //----------------------------------------------------------------------------
    void QDesc2SubmitQ(U16 queueNum, U16 hpdDescriptorNum)
    {
       USB0_CTRLD(queueNum) = ((U32)&sRegion0DescriptorSpace[hpdDescriptorNum])
         | 0x2; // bits[4:0]=dec_size=[0-31]=[24,28,32,...,148]
    }

    //----------------------------------------------------------------------------
    void EnableCoreTxDMA(U16 endPoint)
    {
       U16 index_save;
       index_save=USB0_INDEX;
       USB0_INDEX=endPoint;
       USB0_HOST_TXCSR&=0x7FFF; // Clear AUTOSET
       USB0_HOST_TXCSR|=0x1400; // Set DMAReqEnab & DMAReqMode
       USB0_HOST_TXCSR|=(1<<3); // Flush OUT FIFO
       USB0_INDEX=index_save;
    }

    //----------------------------------------------------------------------------
    void EnableCoreRxDMA(U16 endPoint)
    {
       U16 index_save;
       index_save=USB0_INDEX;
       USB0_INDEX=endPoint;
       USB0_HOST_RXCSR&=0x77FF; // Clear AUTOCLEAR and DMAReqMode
       USB0_HOST_RXCSR|=0x2000; // Set DMAReqEnab
       USB0_INDEX=index_save;
    }

    //----------------------------------------------------------------------------
    U32 ReadCompletionQueue(U16 queueNum)
    {
       U32 DescAddress;
       DescAddress=(U32)USB0_CTRLD(queueNum);
       DescAddress&=0xFFFFFFE0;
       return(DescAddress);
    }

    //----------------------------------------------------------------------------
    void DisableCoreRxDMA(U16 endPoint)
    {
       U16 index_save;
       index_save=USB0_INDEX;
       USB0_INDEX=endPoint;
       USB0_HOST_RXCSR &= 0xDFFF; // Clear DMAReqEnab
       USB0_INDEX=index_save;
    }

    //----------------------------------------------------------------------------
    void DisableCoreTxDMA(U16 endPoint)
    {
       U16 index_save;
       index_save=USB0_INDEX;
       USB0_INDEX=endPoint;
       USB0_HOST_TXCSR&=0x7FFF; // Clear AUTOSET
       USB0_HOST_TXCSR&=0xEBFF; // Clear DMAReqEnab & DMAReqMode
       USB0_INDEX=index_save;
    }

    //----------------------------------------------------------------------------
    int USB_DMAReadStart(void *buf, U32 len, char ep)
    {
       U8 *theBuf = (U8*)buf;
      
       //generate recv descriptor
       InitSingleHPDorHBD(READ_DESC_IDX_HEAD, RECEIVE, BUFFER_DESC,
         UDQ_RX_COMPLETE, GENERIC_RNDIS, ep, &theBuf, &len);
       //push it into rx submit queue
       QDesc2SubmitQ(UDQ_RX_SUBMIT, READ_DESC_IDX_HEAD);
       //start rx DMA.
       EnableCoreRxDMA(ep);
      
       USB_BeginBulkIn(ep); //send In token
       return len;
    }

    //----------------------------------------------------------------------------
    int USB_DMAWriteStart(void *buf, U32 len, char ep)
    {
       U8 *theBuf = (U8*)buf;
       U16 idxQueue;
         
       //generate transmit descriptor
       InitSingleHPDorHBD(WRITE_DESC_IDX_HEAD, TRANSMIT, PACKET_DESC,
         UDQ_TX_COMPLETE, GENERIC_RNDIS, ep, &theBuf, &len);
       //push it into rx submit queue

       switch(ep)
       {
          case 1: idxQueue = 16; break;
          case 2: idxQueue = 18; break;
          case 3: idxQueue = 20; break;
          case 4: idxQueue = 22; break;
       }
       QDesc2SubmitQ(idxQueue, WRITE_DESC_IDX_HEAD);
       printf("Pend(0) = %x\n", USB0_PEND(0));
       //start rx DMA.
       EnableCoreTxDMA(ep);
      
       return len;
    }

    //----------------------------------------------------------------------------
    int SCalcRegionSizeId(int regionSizeInByte)
    {
       int size = 0;
       int i = regionSizeInByte;
      
       while(i>32)
       {
          size++;
          i>>=1;
       }
       return size;
    }

  • Hi, Zegeye, still doesn't work. I put my code seg here, please take a look:

    NOTE:
    1) USB worked in host mode;
    2) DMA transfer method is GENERIC_RNDIS with PackageSize = epMaxP;
    3) Communication process, in brief, list below(the device is a kind of MSC):
          Step 1)send CBW(31Bytes)(using ep2),
          Step 2)DATA IO(512*N Bytes)(using ep2(out) or ep1(in))
          Step 3)recv CSW(13Bytes)(using ep1)

    unfortunately, the first Step failed yet.
    I have test all codes without DMA, everything is OK.


    BTW, when I send package out. I can recv Interrupt with correct transmit
    complete queue 's PEND.bit is set. But the Device seemed that It haven't recv
    the first CBW package.(when correct package recved, the LED will light). There
    must be something wrong.
                                             
    waiting your reply.

    //////////////////////////////////////////////////////////////////////////////
    // define and ref //
    ////////////////////
    #define PACKET_SPACE_SIZE 32

    int SCalcRegionSizeId(int regionSizeInByte);

    #pragma DATA_ALIGN(sRegion0DescriptorSpace, 32);
    #pragma DATA_SECTION(sRegion0DescriptorSpace,".usb")
    HostPacketDesc //static
      sRegion0DescriptorSpace[PACKET_SPACE_SIZE]; //Region0

    static U32
      sLinkingRAM0[PACKET_SPACE_SIZE]; //LinkingRam0

    U32 sSinglePktLength = 0; //maxP of device ep

    /*Dma Init*/
    //----------------------------------------------------------------------------
    void USB_CppiDmaInit(EUSB_TYPE usbType, CPPI_DMA_MODE dmaMode, PU_DISK uDisk)
    {
       U32   chIdx[4];
       U8    chCnt;
       U32   ch;
       int   i;

    /*****************************************************************************
     * Step0. set variable value
     */
       chIdx[0] = uDisk->host_epIn-1; //ep No. to channel No.
       chIdx[1] = uDisk->host_epOut-1;
       chCnt = 2;
       sSinglePktLength = (uDisk->device_maxPackageSizeIn>uDisk->device_maxPackageSizeOut) ?
         uDisk->device_maxPackageSizeOut : uDisk->device_maxPackageSizeIn;


    /*****************************************************************************
     * Step1.set cppi dma working mode
     */
       USB0_CTRL &= ~0x00000010; // Disable RNDIS from Global Level
       for(i = 0; i<chCnt; i++)
       {
          ch = chIdx[i];
          switch (dmaMode)
          {
             case RNDIS:
             {
                SET_BIT(USB0_MODE, ch*4, 2, 1); //tx
                SET_BIT(USB0_MODE, 16+ch*4, 2, 1); //rx
                break;
             }
             case GENERIC_RNDIS:
             {
                SET_BIT(USB0_MODE, ch*4, 2, 3); //tx
                SET_BIT(USB0_MODE, 16+ch*4, 2, 3); //rx
                USB0_GENRNDISSZ(ch) = sSinglePktLength; //descPacketLength
                break;
             }
             case LINUX_CDC:
             {
                SET_BIT(USB0_MODE, ch*4, 2, 2); //tx
                SET_BIT(USB0_MODE, 16+ch*4, 2, 2); //rx
                break;
             }
             case TRANSPARENT:
             {
                SET_BIT(USB0_MODE, ch*4, 2, 0); //tx
                SET_BIT(USB0_MODE, 16+ch*4, 2, 0); //rx
                break;
             }
             //do default.
          }
       }

    /*****************************************************************************
     * Step2.autoreq
     */
       for(i = 0; i<chCnt; i++)
       {
          ch = chIdx[i];
          if(usbType != USB_DEVICE) // If Controller is assuming Host Role
          {
             if(TRANSPARENT == dmaMode)
                // No Auto Req
                SET_BIT(USB0_AUTOREQ, ch*2, 2, 0);
             else
                // Auto Req on all but EOP
                SET_BIT(USB0_AUTOREQ, ch*2, 2, 1);
          }
       }

    /*****************************************************************************
     * Step3.LinkingRAM
     */
       USB0_LRAM0BASE = (U32)sLinkingRAM0;
       USB0_LRAM0SIZE = PACKET_SPACE_SIZE;
       USB0_LRAM1BASE = 0;

    /*****************************************************************************
     * Step4.Region0
     */
       USB0_QMEMRBASE(0) = (U32)sRegion0DescriptorSpace;
       USB0_QMEMRCTRL(0) = (0<<16) | //base index = 0
                           (0<<8) | //descriptor size = 32
                           SCalcRegionSizeId(PACKET_SPACE_SIZE); //Region item cnt.
      
    /*****************************************************************************
     * Step5.Configure the Scheduler,
     */
       USB0_WORD(0) = 0x80818283; //rx
       USB0_WORD(1) = 0x00010203; //tx
       USB0_DMA_SHED_CTRL = 0x80000007; //Enable Scheduler
      
    /*****************************************************************************
     * Step6.Others work, enable dma channel
     */
       for(i = 0; i<chCnt; i++)
       {
          ch = chIdx[i];
          USB0_RXHPCRA(ch) = (UDQ_RX_SUBMIT<<16) | UDQ_RX_SUBMIT;
          USB0_RXHPCRB(ch) = (UDQ_RX_SUBMIT<<16) | UDQ_RX_SUBMIT;
          USB0_RXGCR(ch) = 0x81004000 | UDQ_RX_COMPLETE;
          USB0_TXGCR(ch) = 0x80000000 | UDQ_TX_COMPLETE;
       }

    /****************************************************************************
     * Step7.stop all ep's dma function
     */
       for(i = 1; i<=4; i++)
       {
          DisableCoreTxDMA(i);
          DisableCoreRxDMA(i);
       }
    }

  • Feng,

    Could you not use the BIOSUSB stack and develop your application on top of it?

    regards

    swami

  • Hi,

    Sorry to hear that it is still not working.

    Btw, what are you seeing on the Bus.

    You are still being very vague on your information.

    I do not have the bandwidth to understand every customer code. That is impossible. You will have to tell me what exactly you have programmed. You could have address alignment issue and that will mess everything up and will be imposible to catch from your code. I have asked for you to tell me what you are observing from the CCS window not your code. I do not know the details of your macro and even if I did, I can not trust  the macro until I verify its operation. And this I can not do. So, please work from CCS watch window or memory window for Descriptor Setup case. Do not use CCS Memory window to access core registers, use watch window.

    The only thing I can suggest is that, insure address alignment is inforced.

    Reduce your setup to perform a simple DMA transfer in stead of implementing a class driver.

    Insure your Region Address, Linking RAM Address, etc are aligned as apporopriate.

    Capture your settings from the Memory window for your Descriptor setup; both Address and Content of Memory. 

    Best regards, Zegeye

  • the main problem has been fixed. I can send & recv package, now.

     

    But when recving package, sometimes the transmition may hang up.

    When It happens, I checked the HOST_RXCSR register(for in ep), which value is equal to "0x2220".  It seemed that the InToken has trasmit correctly. So What condition can cause such problem?(Q3.1)

    Can CPPI DMA deal with the NAK properly?(Q3.2)

    When worked at DMA mode, whether all ep interrupt have been captured?(Q3.3)

     

    thanks for your patient.

     

  • When I insert a 2~3us delay before startting next continuous BulkIn op, CPPI DMA worked well.

    So, Here is my last question:

    If USB worked in host mode. and he want recv sth:

           First, he push a descriptor into submit queue(which is also a recv waiting queue).

          Then,he send out a IN TOKEN.

    But what if the device returned NAK?

    Can CPPI DMA re-send IN TOKEN again? If he could not do such things, what shall I do?

  • Hi,

    Yes, you are correct. The H/W, in this case the Controller not the DMA, will do a repeated request if NAK is received. Question is what type of transfer are you performing, is it ISO?

    As you have observed, the first NAK is received because the h/w has requested for a packet, sent IN Token. This tells me that both the DMA and the Controller are working properly. If it is a BULK transfer, it should perform another request unless there is another transfer pending, which I don't think in this case is happening. See also RXINTERVAL register us; Usage depends on the type of transfer. Most hosts usually perform 3 attempts before giving up. If the controller does reach this state, it will set the error bit within RXCSR register.

    What I suggest is to be sure that you have received a NAK. If you are sure you received a NAK and no other transaction is scheduled or no other channel is enabled in the schedule entry, you should see another IN request going out.

    Best regards, Zegeye

  • Hello there,i'v got some questions about OMAPL137 USB 2.0 OTG port!

    Now,I'm spending some time on writing the firmware,but stuck at bus enumeration,my reference is TMS320C674x/OMAP-L1x Processor
    Universal Serial Bus 2.0 (USB2.0) Controller User's Guide

    My puzzle is:

    Q1 Is there some detailed information on how to read and write FIFO,I do know there are some registers ,such as FIFO0,but how can I operate with it?

    I can't find anything about it in the User Guide.

    Q2 Should I enable DSP's globle interrupt to handle USB Controllers's interrupt,I mean should I add a interrupt vector to my project and write an ISR for USB dispatcher?

    PS:I am developing OMAP137 USB 2.0 Firmware on DSP side,and i fail to enumerate device?Does TI provice some user cases,I do find some in the User Guide ,but it does

    nothing to bus enumeration! Any suggestions?

    Best Regards

    Calm

  • Hello there,i'v got some questions about OMAPL137 USB 2.0 OTG port!

    Now,I'm spending some time on writing the firmware,but stuck at bus enumeration,my reference is TMS320C674x/OMAP-L1x Processor
    Universal Serial Bus 2.0 (USB2.0) Controller User's Guide

    My puzzle is:

    Q1 Is there some detailed information on how to read and write FIFO,I do know there are some registers ,such as FIFO0,but how can I operate with it?

    I can't find anything about it in the User Guide.

    Q2 Should I enable DSP's globle interrupt to handle USB Controllers's interrupt,I mean should I add a interrupt vector to my project and write an ISR for USB dispatcher?

    PS:I am developing OMAP137 USB 2.0 Firmware on DSP side,and i fail to enumerate device?Does TI provice some user cases,I do find some in the User Guide ,but it does

    nothing to bus enumeration! Any suggestions?

    Best Regards

    Calm

  • Calm,

    Pl. refer to the Linux MUSB  driver for the init sequences (drivers/usb/musb/musb_core.c, da8xx.c) or the u-boot musb driver (no DMA support().

    Is there any reason why you are ot looking at BIOSUSB stack on DSP side?

    regards

    swami

  • Hi,

    Q1. Section 2.7 of the User's Guide has the information you are looking for. Please consult this section closely.

            Enumeration is always handled via CPU, i.e. can not be handled by the DMA.

            Endpoint 0 resources are allocated (user do not have to allocate FIFO-RAM for EP0) and the first 64 bytes of the FIFO is RAM is allocated for its use. Like you mentioned, you access this FIFO RAM via FIFO0 register. You can perform byte, 16-bits, or 32-bit read/write accesses.

    Q2. Refer to DSP Megamodule Reference Guide, Section 7. http://focus.ti.com/lit/ug/sprufk5a/sprufk5a.pdf

    The initialization use case is applicable for all types of transfers. The other use cases are mostly emphasizing on the use of the DMA. Section 2.7 of the USB User's guide goes into detail as to how to handle Control Transfers. Control Transfer uses standard requests and this is covered within the USB 2.0 Specification, Section 9.3 "Standard Device Requests".

    Best regards, Zegeye