1 2 Previous Next 17 Replies Latest reply on Nov 15, 2018 12:48 PM by user_246598725

    USB_FS with Auto-DMA / API handling: HowTo?

    user_246598725

      Hi,

       

      is there anything special to do when using USB_FS component with auto-DMA mode? I've seen some threads mentioning that the EPx_ISR entry/exit callbacks are needed because they inform about a finished DMA transfer. But I couldn't find any example code about it. The only thing is AN56377, which uses an ISOC IN endpoint, but it seems that there isn't anything special with the ISRs and/or callbacks. My code is based on USB_FS component datasheet and the example #1 of AN56377, modified for DMA auto mode.

       

      Currently I'm using an IN/OUT endpoint pair, where the packet received from the OUT endpoint should be looped back by the IN endpoint:

       

      //global buffers

      uint8 Interrupt_IN_Buffer[64], EP1_Count;

      uint8 Interrupt_OUT_Buffer[64], EP2_Count;

      uint8 App_Interrupt_OUT_Buffer[64];

       

      //init USB DMA buffers (called in main() function)

      USBFS_LoadInEP(EP1, Interrupt_IN_Buffer, 64);

      USBFS_ReadOutEP(EP2, Interrupt_OUT_Buffer, 64);

       

      //USB endpoint handling, should simply loop back

      if(USBFS_GetEPState(EP2) == USBFS_OUT_BUFFER_FULL) {

          /* Determine the number of bytes received */

          EP2_Count = USBFS_GetEPCount(EP2);

       

          memcpy(&App_Interrupt_OUT_Buffer, &Interrupt_OUT_Buffer, EP2_Count);    //uses application buffer as intermediate memory

       

          /* Create loopback by reloading data received into IN endpoint */

          while(USBFS_IN_BUFFER_EMPTY != USBFS_GetEPState(EP1));

       

          memcpy(&Interrupt_IN_Buffer, &App_Interrupt_OUT_Buffer, EP2_Count);    //uses application buffer as intermediate memory

       

          USBFS_LoadInEP(EP1, NULL, EP2_Count);

       

          /* Re-arm the Out Endpoint */

          USBFS_EnableOutEP(EP2);

      }

       

      What am I missing?

       

      Regards

        • 1. Re: USB_FS with Auto-DMA / API handling: HowTo?
          anks

          Hi,

           

          Where have you seen that EPx_ISR entry/exit callbacks are needed because they inform about a finished DMA transfer?

          There are ISRs for each endpoints inside the file USBFS_episr.c. For eg: You can add your code in the OUT EP. When host is sending data to device OUT EP ISR will be triggered.

           

          Please refer to this doc  :

          http://www.cypress.com/file/105231/download

          Presently, the code is not publicly available associated with the above mentioned document.

           

          In the doc following is mentioned which will be helpful for you:

          If certain data suppose 64 bytes is sent to the PSoC 3 / PSoC 5 (that is, the Out endpoint (suppose it is EP2) in PSoC 3 / PSoC 5 receives this data). This operation triggers out endpoint interrupt inside the PSoC 3 / PSoC 5 device. This interrupt routes the program to CY_ISR(USBFS_EP_2_lSR) inside the USBFS_episr.c file.

          In the ISR:

          1. A flag to indicate the occurrence of interrupt is set (USB_interruptFlag)

          2. In the main code, when this flag is set, a  function  can be called

           

           

          3. The function will do the following:

          a. Reads how many bytes have been sent to the Out endpoint

          b. Reads the bytes sent to the Out endpoint and stores to a local buffer

          c. Increments the received data

          d. Puts the incremented data to the In endpoint buffer so that when the Read button is clicked in the GUI, the data from the In endpoint buffer is sent to PC

           

          Please refer to this doc which can give you an idea how to do loopback :

          http://www.cypress.com/file/105231/download

          • 2. Re: USB_FS with Auto-DMA / API handling: HowTo?
            user_246598725

            Hi anks,

             

            >>> Where have you seen that EPx_ISR entry/exit callbacks are needed because they inform about a finished DMA transfer?

             

            Hima mentioned it here: USB DMA with Automatic Memory Management

             

            But he didn't explain how it should be done.

             

            Thank you for the document, I'll go through it. What I try to figure out is if it's needed to hook up to the ISRs when using DMA auto mode. None of the examples provided seems to use them (e.g. AN56377 uses DMA auto mode, but the ISRs are not touched).

             

            When I debug my code above, it seems that the firmware is permanently handling DMA part of the USB API, which causes my application to hang. That's why I asked if anything must be done with the IRQs (e.g. clear DMA complete interrupt flags).

             

            Regards

            • 3. Re: USB_FS with Auto-DMA / API handling: HowTo?
              anks

              Hi,

               

              Hima is correct in her explanation.

              You can use EP's  ISR as needed in application.

              As said by Hima "The ISR will get triggered only when data is loaded into SRAM, in case of OUT transfer."

              DMA interrupt's are internal to USB component .Please go through USBFS datasheet for proper understanding.

              User can edit EP ISR in callback areas in USBFS_episr as indicated as for eg:

              "/* `#START EP1_USER_CODE` Place your code here */

              /* `#END` */"

              • 4. Re: USB_FS with Auto-DMA / API handling: HowTo?
                user_246598725

                Hi anks,

                 

                Hima itself didn't mention DMA mode, that's true. But the topic starter asked about DMA auto mode, that's why I assumed it's needed for DMA. From your answers I understand that I don't need to use the callbacks.

                 

                So, the question is why my above code isn't working. It should be a simple loop back with DMA auto mode.

                 

                Regards

                • 5. Re: USB_FS with Auto-DMA / API handling: HowTo?
                  anks

                  Hi,

                   

                  I think you need to use callbacks that is what I mentioned in my previous interactions and the doc suggested the same.

                   

                   

                  By mistake, I given the same link both times in first interaction, please find this doc:

                  http://www.cypress.com/file/105261/download

                   

                  So I suggest you to go through the documents previously suggested and the USBFS datasheet for choosing correct method.

                  • 6. Re: USB_FS with Auto-DMA / API handling: HowTo?
                    anks

                    Hi Ralf,

                     

                    As far as for code snippet posted by you:

                    "USBFS_LoadInEP(EP1, Interrupt_IN_Buffer, 64);

                    USBFS_ReadOutEP(EP2, Interrupt_OUT_Buffer, 64);"

                     

                    These API's should be used only after checking the particular EPs state.

                    They cannot be used as such directly without any check.

                    • 7. Re: USB_FS with Auto-DMA / API handling: HowTo?
                      user_246598725

                      Hi anks,

                       

                      those APIs are only used once with 2nd argument as buffer pointer in initialization (please see the code comments).

                       

                      The main loop itself doesn't use ReadOutEP() after initialization - from my understanding of the USBFS API, this isn't needed when using DMA auto mode.

                      GetEPState() is used for both endpoints. For the IN endpoint, LoadInEP(EP1, NULL, EP2_Count) is used. After that, EnableOutEP(EP2) is called to get ready for next out packet.

                       

                      Regards

                      • 8. Re: USB_FS with Auto-DMA / API handling: HowTo?
                        anks

                        Hi,

                         

                        For using ReadOutEP API you should do something which as follows, for initialization part which is not part of main loop:

                         

                        /* Get the active interface number and reinitalize DMA */

                        AltSettingNumber = USBFS_GetInterfaceSetting(0);

                         

                        #define ALT_SETTING_ZERO_BANDWIDTH              0

                        if (AltSettingNumber != ALT_SETTING_ZERO_BANDWIDTH)          

                                {

                                    /* Init DMA configurations for  OUT EP */

                                    USBFS_ReadOutEP(EP2, Interrupt_OUT_Buffer, 64);

                                    USBFS_EnableOutEP(EP2); 

                        }

                        • 9. Re: USB_FS with Auto-DMA / API handling: HowTo?
                          user_246598725

                          Hi anks,

                           

                          I'm doing all those things in my code. I'm sorry if my example code above isn't clear, so I try to clarify:

                           

                          //init USB DMA buffers (called in main() function)

                          USBFS_LoadInEP(EP1, Interrupt_IN_Buffer, 64);

                          USBFS_ReadOutEP(EP2, Interrupt_OUT_Buffer, 64);

                           

                          //USB endpoint handling, should simply loop back

                          if(USBFS_GetEPState(EP2) == USBFS_OUT_BUFFER_FULL) {

                              /* Determine the number of bytes received */

                              EP2_Count = USBFS_GetEPCount(EP2);

                           

                              memcpy(&App_Interrupt_OUT_Buffer, &Interrupt_OUT_Buffer, EP2_Count);    //uses application buffer as intermediate memory

                           

                              /* Create loopback by reloading data received into IN endpoint */

                              while(USBFS_IN_BUFFER_EMPTY != USBFS_GetEPState(EP1));

                           

                              memcpy(&Interrupt_IN_Buffer, &App_Interrupt_OUT_Buffer, EP2_Count);    //uses application buffer as intermediate memory

                           

                              USBFS_LoadInEP(EP1, NULL, EP2_Count);

                           

                              /* Re-arm the Out Endpoint */

                              USBFS_EnableOutEP(EP2);

                          }

                           

                          The endpoint handling is based on AN56377 with modifications for DMA auto handling (as far as I understood the DMA auto handling). Is there anything else which must be done to get it to work?

                           

                          Regards

                          • 10. Re: USB_FS with Auto-DMA / API handling: HowTo?
                            anks

                            Please share your main.c file.

                            You need to use EP ISRs Callbacks functions,   For more information regarding Macro callbacks, refer to the Macro Callbacks topic in the PSoC Creator Help.

                            • 11. Re: USB_FS with Auto-DMA / API handling: HowTo?
                              user_246598725

                              Hello anks,

                               

                              You need to use EP ISRs Callbacks functions,

                              now it seems that we're getting on the right way

                              As you mentioned in your answer you accidentally posted the same document link two times - my mistake is that I accidentally missed the link to the second document. Sorry for that. In combination with the first document, the picture gets more clear

                               

                              From reading EP561332 (your 2nd document), what I understood is the following:

                              • ISR callbacks have to be configured for the OUT endpoints, where the ISR:
                                • fires when data has been received and DMA handling has finished (after the last DMA transaction for sizes greater than endpoint size)
                                • copies the received data to a second buffer for later processing
                                • sets a flag to indicate to the main application that data has been received
                                • re-arms the corresponding OUT endpoint by calling USBFS_EnableOutEP()
                              • ISR callbacks have to be configured for the IN endpoints, where the ISR:
                                • fires when the data has been read by the host (after the last DMA transaction for sizes greater than endpoint size)
                                • sets a flag indicating that the data has been retrieved from host and another IN transfer can be initiated or alternatively directly initiates another IN transfer if more than the packet size has to be sent
                                • re-arms the corresponding IN endpoint by calling USBFS_LoadInEP()

                               

                              So, remaining points are:

                              1. Is the above workflow true? If yes, I'll try to implement it that way and give feedback if the issues are resolved.
                              2. I checked USBFS component datasheet as well as AN56733, IMHO none of them clearly state that the user needs to implement custom ISR to handle the DMA transactions (USBFS component datasheet description gives the impression that all neccessary interrupt handling is done internally - additionally the only interrupt callback mentioned is for the OUT packet re-transmission chapter). With the two documents provided by you this gets a bit more clear. So I want to suggest that both USBFS component datasheet and AN56733 are reworked to make the user aware of that. Please take this into consideration.
                              3. For IN endpoints, what's the maximum buffer size for USBFS_LoadInEP()? USBFS component datasheet states the following for DMA auto mode:
                                1. Each endpoint buffer size is 32 bytes and the rest of the USB block buffer (size of 512 bytes) is a common area which acts as a FIFO for the endpoint that to which the host currently communicates.

                                2. When the endpoint buffer is full, the data comes into the FIFO (common area). This allocation allows servicing endpoint sizes greater than the USB block buffer size, because the USB block buffer is used as the infrastructure to manage data transfers and the actual data is stored in the system SRAM memory.

                                3. The above description states that the dedicated hardware block size is 512 bytes. But it's also mentioned that the endpoint size can be greater than 512 bytes. As far as I know this is only true for ISO endpoints and only applicable if only one endpoint is used. The above description sounds like the buffer sizes can be of any size. Which one is true? Please clarify what the maximum buffer sizes are depending on number of endpoints used and endpoint size.

                               

                              Thanks for your help until now, very appreciated.

                               

                              Regards

                              • 12. Re: USB_FS with Auto-DMA / API handling: HowTo?
                                user_246598725

                                Hi anks,

                                 

                                I'm sorry, I don't get it to work I attached the current project, running on a CY8CKIT-059. There are some outputs to serial interface for debug output and speed measurement. The host application is a small C# software, which transmit random data to the interrupt OUT endpoint and receives the same data on IN endpoint. This works well if the USB component is configured for manual-static buffer management.

                                 

                                For DMA-auto buffer management, I made the following changes:

                                1) the endpoint interrupt callbacks are registered for all six endpoints (three pairs of INT/BULK/ISO IN/OUT endpoints, same as AN56377)

                                2) each interrupt only sets a endpoint variable to 1 for further processing in the main application

                                3) the original endpoint buffers are registered for DMA handling in initialization by calling USBFS_LoadInEP() and USBFS_ReadOutEP() with non-null pointer value

                                4) there is an additional application buffer for each OUT endpoint to store the data for later processing as suggested by the documents you provided (I know that this buffer is not needed for simple loop transfer, but in a real project this buffer is needed)

                                5) the AN56377 original functions which handle the data transfer have been modified to check both variables mentioned in #2. If both are set, the OUT endpoint data is retrieved and copied to the local buffer mentioned in #4. After that, the contents of this buffer are copied to the IN endpoint buffer and the IN endpoint is re-enabled by calling USBFS_LoadInEP() with null pointer and size of the retrieved data.

                                 

                                The above workflow is what I understand how to do it, but it doesn't work. Can you clarify what I'm still doing wrong?

                                 

                                Regards

                                • 13. Re: USB_FS with Auto-DMA / API handling: HowTo?
                                  anks

                                  Hi Ralf,

                                   

                                  Please find the attached project for reference.

                                  Please check this on Control center:

                                  1.First chose out EP (0x02) and fill "Text to send" field with 64 bytes and then send "Transfer Data-Out"

                                  2.Then chose IN ISOC (0x81) and chose "Byte to transfer" with 64 bytes and click "Transfer Data-In"

                                   

                                  It does loopback of received data on Out EP to In EP for ISOC Transfers

                                  • 14. Re: USB_FS with Auto-DMA / API handling: HowTo?
                                    user_246598725

                                    Hi anks,

                                     

                                    I adapted the scheme to the interrupt endpoints of example #1 of AN56377. I hooked up a callback for the USBFS_EP_DMA_DONE_ISR exit for debug purpose. It seems that after the first OUT transaction the ISR fires continously. Is this intended behaviour?

                                    It slows down the application and the code couldn't work the USB_FS_LoadInEndpoint() function.

                                     

                                    Regards

                                    1 2 Previous Next