1 2 Previous Next 17 Replies Latest reply on Nov 28, 2019 10:50 PM by RashiV_61

    FX3 : UART to USB minimal DMA size workaround

    ChRO_4339966

      Hello,

       

      On my FX3 project I created an EP discussing with a FPGA through UART link.

      UART is configured on both sides to work with Byte mode DMA (dmaConfig.dmaMode = CY_U3P_DMA_MODE_BYTE)

       

      All this works like a charm, except that I live with a limitation that I would like to fix : at reception (FPGA->FX3), DMA requires a minimal of 16 bytes to operate, which seems to be a limitation of FX3 (UART?) DMA engine.

      This means if my FPGA sends less than 16 bytes of data they will not be forwarded to my USB endpoint.

       

      I would like to keep it as simple as possible to avoid having FX3 firmware sniffing at UART events and processing packets. Is there a simple solution for that ?

       

      Hereunder is my UART configuration :

       

      CyU3PReturnStatus_t ConfigureUartDma(void) {

          CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

          CyU3PDmaChannelConfig_t dmaConfig;

       

       

          // Create a AUTO channel for the USB to UART transfer

          CyU3PMemSet((uint8_t *)&dmaConfig, 0, sizeof(dmaConfig));

          dmaConfig.size           = 128; // Maximal number of bytes allowed per DMA buffer.

                                          // A larger message would stuck the EP

          dmaConfig.count          = 32;  // Store up to 32 words in DMA buffers

          dmaConfig.prodSckId      = FPGA_CONFIG_ENDPOINT_SOCKET;

          dmaConfig.consSckId      = UART_CONSUMER_SOCKET;

          dmaConfig.dmaMode        = CY_U3P_DMA_MODE_BYTE;

          Status = CyU3PDmaChannelCreate(&Usb2Uart_Handle, CY_U3P_DMA_TYPE_AUTO, &dmaConfig);

       

          // Start the DMA Channel with transfer size to Infinite

          Status = CyU3PDmaChannelSetXfer(&Usb2Uart_Handle, 0);

       

       

          // Create a AUTO channel for the UART to USB transfer

          CyU3PMemSet((uint8_t *)&dmaConfig, 0, sizeof(dmaConfig));

          dmaConfig.size          = 16;   // Minimal value allowed by DMA.

                                          // Any UART message longer than this will be split in 16 bytes "packets"

          dmaConfig.count         = 32;   // Up to 32 words can be stored in DMA buffers

          dmaConfig.prodSckId     = UART_PRODUCER_SOCKET;

          dmaConfig.consSckId     = FPGA_STATUS_ENDPOINT_SOCKET;

          dmaConfig.dmaMode       = CY_U3P_DMA_MODE_BYTE;

          Status = CyU3PDmaChannelCreate(&Uart2Usb_Handle, CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaConfig);

       

          // Start the DMA Channel with transfer size to Infinite

          Status = CyU3PDmaChannelSetXfer(&Uart2Usb_Handle, 0);

       

          return Status;

      }

       

      Thanks in advance

        • 1. Re: FX3 : UART to USB minimal DMA size workaround
          RashiV_61

          Hello Christophe,

           

          Please confirm if you referred to the USBUART example in the SDK.

           

          In the USBUARTAppThread_Entry function CyU3PDmaChannelSetWrapUp (&glChHandleUarttoUsb); is called in the for{} loop to  use the channel wrap-up feature to send any partial buffer to  the USB host.

          So you can use this API in you firmware as per your  application.

           

          Regards,

          Rashi

          • 2. Re: FX3 : UART to USB minimal DMA size workaround
            ChRO_4339966

            Hello Rashi,

             

            Thanks for feedback.

             

            No I am not using USBUART example from SDK. I did built my own application where UART is configured to use (AUTO ?) DMAs.

            This is done in 2 steps :

            - configure UART (see ConfigureUart() below)

            - configure DMA (see code in initial thread message)

             

            Doing so I don't have to have a thread running an infinite loop, but with this drawback I try to fix.

             

            My remaining question is : "Is there a fix for that I do I have to go through Manual DMA + Callback + CyU3PDmaChannelSetWrapUp + infinite loop ? "

             

             

            CyU3PReturnStatus_t ConfigureUart(void)

            {

                CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

                CyU3PUartConfig_t uartConfig;

             

             

                // Start the UART driver

                Status = CyU3PUartInit();

             

                // Configure my UART link, as fast as possible for interfacing with FPGA

                CyU3PMemSet ((uint8_t *)&uartConfig, 0, sizeof (uartConfig));

                uartConfig.baudRate = CY_U3P_UART_BAUDRATE_4M608K;

                uartConfig.stopBit  = CY_U3P_UART_ONE_STOP_BIT;

                uartConfig.txEnable = CyTrue;

                uartConfig.rxEnable = CyTrue;

                uartConfig.isDma    = CyTrue;

             

                /* Set the UART configuration; no callback  */

                Status = CyU3PUartSetConfig(&uartConfig, NULL);

             

                Status = CyU3PUartTxSetBlockXfer(0xFFFFFFFF);                  // Send as much data as I need to

                Status = CyU3PUartRxSetBlockXfer(0xFFFFFFFF);

             

                return Status;

            }

             

            I wrote this code a while back so excuse me if DMA modes of operations are not 100% clear in my mind.

             

            Regards

            Christophe

            • 3. Re: FX3 : UART to USB minimal DMA size workaround
              RashiV_61

              Hello Christophe,

               

              I didn't get the question. Can you restate it?

              From the previous post what i understood was that you want to commit the partial buffer.

              As per your previous response, DMA channel from UART to USB is AUTO_SIGNAL. Still you can use CyU3PDmaChannelSetWrapUp API in the for{}. But you need to register a call back and handle the PROD_EVENT. In the PROD_EVENT the partial buffer can be committed. (Refer to the modified UsbUart example with DMA_TYPE_ AUTO_SIGNAL channel between uart and usb). You can check the working of the  attached firmware and make changes to your firmware accordingly.

               

              If you wan to use DMA Manual channel you need to commit the data manually to the consumer socket. This is done when the buffer is full or PROD_EVENT occurs and in DMA channel you commit that buffer.

              But when the buffer is partially filled there will not be any PROD_EVENTS. So when you call  CyU3PDmaChannelSetWrapUp there will be PROD_EVENT even when the buffer is partially filled. In the callback, this buffer will then be committed to the consumer socket.

               

              We use this API in the for{} (as per usbuart example) to continuously check for partial buffer and commit it.

               

              Regards,

              Rashi

              • 4. Re: FX3 : UART to USB minimal DMA size workaround
                ChRO_4339966

                Hi Rashi,

                 

                You are right, I want to commit partially filled buffer.

                Then from your example, it looks like this is correct approach.

                I'll check if this works in my application and let you know.

                 

                Thanks a lot !

                Christophe

                • 5. Re: FX3 : UART to USB minimal DMA size workaround
                  ChRO_4339966

                  Hello Rashi,

                   

                  I applied proposed modifications to my code.

                  My UART to USB pipe is now failing.

                   

                  I instrumented this section of code and I get an error within callback function after initialization :

                  UartRxDMACallback call 
                  CyU3PDmaChannelCommitBuffer() failed, 71 = CY_U3P_ERROR_INVALID_SEQUENCE ?

                  Documentation mentions this happens when DMA is not configured. I checked how device is configured and I believe DMA should be configured.

                  C file handling UART function is attached for more details.

                  StartUart() function contained there is called by main program, which also have an infinite loop in a thread calling FlushUARTRxDMA() function every 100 ms.

                   

                  Thanks for support

                  Christophe

                  • 6. Re: FX3 : UART to USB minimal DMA size workaround
                    RashiV_61

                    Hello Christophe,

                     

                    I went through the source code of the CyU3PDmaChannelCommitBuffer() API.

                    The error 71 (0x47) is when the socket is not in suspend mode.

                    Please confirm that this FlushUARTRxDMA function is not called before the channel is created i.e. before calling CyU3PDmaChannelCreate and CyU3PDmaChannelSetXfer

                     

                    Regards,

                    Rashi

                    • 7. Re: FX3 : UART to USB minimal DMA size workaround
                      ChRO_4339966

                      Rashi,

                       

                      Here is code portion calling the function (within a specific thread) :

                          // Now run forever

                          while (1)

                          {

                              CyU3PThreadSleep(100);

                              // Check for UART data availabity (partially full DMA buffer)

                              if (glIsUartActive) {

                                Status = FlushUARTRxDMA();

                                CheckStatus("FlushUARTRxDMA()", Status);

                              }

                          }

                       

                      glIsUartActive is set to true within StartUart() function after UART and associated DMAs are configured:

                       

                      CyU3PReturnStatus_t StartUart(void)

                      {

                          CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

                       

                          // Configure UART for interfacing with FPGA

                          Status = ConfigureUart();

                          CheckStatus("ConfigureUart()", Status);

                       

                          // Configure USB endpoints linked to UART

                          Status = ConfigureUartEP();

                          CheckStatus("ConfigureUartEP()", Status);

                       

                       

                          // Create DMAs between EP and UART

                          Status = ConfigureUartDma();

                          CheckStatus("ConfigureUartDma()", Status);

                       

                       

                          // Mark USB <-> UART communication as active

                          glIsUartActive = CyTrue;

                       

                       

                          return Status;

                      }

                       

                      So function should be called AFTER dma is configure within ConfigureUartDma() function.

                       

                      Christophe

                      • 8. Re: FX3 : UART to USB minimal DMA size workaround
                        RashiV_61

                        Hello Christophe,

                         

                        Can you share your complete firmware as I am not able to reproduce the problem at my end.

                        The source code of CyU3PDmaChannelCommitBuffer() API checks  the state of socket (suspend or not)

                         

                        Also, share the debug logs.

                         

                        Regards,

                        Rashi

                        • 9. Re: FX3 : UART to USB minimal DMA size workaround
                          RashiV_61

                          Hello Christophe,

                           

                          From the firmware i found that you are using one Uart consumer socket for debugging and also you are creating a channel from USB to UART.

                          Uart block has only two sockets i.e. one consumer socket ans one producer socket. So you can use the consumer socket for one purpose only either it can be for USB > UART channel or for debugging purpose.

                           

                          You can see in the UsbtoUart example doesn't have provision for debug prints due to this reason.

                           

                          So can you please comment out the API's used for debugging

                          You can check whether the API is failing or not by calling the CYU3PDeviceRest(CyFalse) API in the condition checking for error

                           

                          Regards,

                          Rashi

                          • 10. Re: FX3 : UART to USB minimal DMA size workaround
                            ChRO_4339966

                            Hello Rashi,

                             

                            I think there is a lack of understanding here.

                            FX3 firmware operates as a bridge between UART module and EP2 (IN/OUT).

                            My Debug console is targeted towards EP4.

                             

                            So UART and associated EP are not used to carry debug messages.

                             

                            Also, note all this was working OK (except 16 bytes limitation we are discussing) before I tried using CyU3PDmaChannelSetWrapUp.

                             

                            Regards

                            Christophe

                             

                            • 11. Re: FX3 : UART to USB minimal DMA size workaround
                              RashiV_61

                              Hello Christophe,

                               

                              Please refer to this KBA Invalid Sequence Error in Multi-Channel Commit Buffer - KBA218830 . This is for multichannel commit buffer failure but similar conditions are checked in the source code of CyU3PDmaChannelCommitBuffer API. This KBA is for UVC applications but the cause of this error in your application is due to slow host. ( IN tokens)

                               

                              As per this KBA CyU3PDmaChannelCommitBuffer() and CyU3PDmaChannelSetWrapUp() Returns INVALID_SEQUENCE Errors When Using 32-Bit GPIF™ II Interface - KBA85503  you have set the clock to 403.2 MHz

                               

                              When do you get this failure after some  transfers or as soon as you program the FX3 with the firmware. Can you share the debug prints when this error occurs. It would also help me to understand the flow of the code.

                               

                              Regards,

                              Rashi

                              • 12. Re: FX3 : UART to USB minimal DMA size workaround
                                ChRO_4339966

                                Hello Rashi,

                                 

                                Sorry for late reply, but I had really little time to work on this till yesterday.

                                I looked at KBAs you mentionned. 1st one is the kind of issue I was suspecting.

                                 

                                Actually, at initialisation every "important" step is marked for debug (DebugPrint) and then pushed to a specific EP.

                                What happens is that it looks like this buffer tends to become full at initialisation and blocks execution of the code.

                                I then need to poll my EP to continue execution.

                                This is really close to KBA description.

                                 

                                For your information, here is the kind of log I get when all messages are printed :

                                Initialize USB Debug Console Successful

                                USBThread completed init. Monitoring USB events...

                                CyU3PUartInit Successful

                                CyU3PUartSetConfig Successful

                                CyU3PUartTxSetBlockXfer Successful

                                CyU3PUartRxSetBlockXfer Successful

                                ConfigureUart() Successful

                                Device ready, DebugThread waking up

                                Setup FPGA_CONFIG_ENDPOINT Successful

                                Flush FPGA_CONFIG_ENDPOINT Successful

                                Setup FPGA_STATUS_ENDPOINT Successful

                                Flush FPGA_STATUS_ENDPOINT Successful

                                ConfigureUartEP() Successful

                                Usb2Uart DmaChannelCreate Successful

                                Usb2Uart DmaChannelStart Successful

                                Uart2Usb DmaChannelCreate Successful

                                Uart2Usb DmaChannelStart Successful

                                ConfigureUartDma() Successful

                                StartUart() Successful

                                UartRxDMACallback call

                                CyU3PDmaChannelCommitBuffer() failed, 71 = CY_U3P_ERROR_INVALID_SEQUENCE

                                ?

                                CyU3PDmaChannelSetWrapUp() Successful

                                FlushUARTRxDMA() Successful

                                 

                                I then tried a 1st fix that consists in suspending all DebugPrint until UART DMA callback is called.

                                I received same error log on Debug EP at CommitBuffer call:

                                USBThread completed init. Monitoring USB events...

                                UartRxDMACallback call

                                CyU3PDmaChannelCommitBuffer() failed, 71 = CY_U3P_ERROR_INVALID_SEQUENCE

                                ?

                                CyU3PDmaChannelSetWrapUp() Successful

                                FlushUARTRxDMA() Successful

                                Device ready, DebugThread waking up?

                                 

                                KBA218830 solution proposal seems to bring other problem, since I cannot afford stopping GPIF state machine (will be used at the same time to transport data from FPGA to my host application). Or maybe could I apply this to UART and then acting only on UART config ?

                                 

                                It is still possible in my code modification to add this CyU3PDmaChannelCommitBuffer/CyU3PDmaChannelSetWrapUp there is something that went wrong...

                                Maybe UartRxDMACallback definition is incorrect ? Are arguments passed from OS to callback function ? What is chHandle parameters that is unused there ?

                                 

                                void UartRxDMACallback(

                                        CyU3PDmaChannel   *chHandle, /* Handle to the DMA channel. */

                                        CyU3PDmaCbType_t   type,     /* Callback type.             */

                                        CyU3PDmaCBInput_t *input)    /* Callback status.           */

                                {

                                    CyU3PReturnStatus_t Status = CY_U3P_SUCCESS;

                                    if (type == CY_U3P_DMA_CB_PROD_EVENT)

                                    {

                                        glIsDebugActive = CyTrue;

                                        DebugPrint(4, "\r\nUartRxDMACallback call");

                                        Status = CyU3PDmaChannelCommitBuffer (&Uart2Usb_Handle, input->buffer_p.count, 0);

                                        CheckStatus("CyU3PDmaChannelCommitBuffer()", Status);

                                        glPktsPending++;

                                    }

                                }

                                 

                                Regards

                                Christophe

                                • 13. Re: FX3 : UART to USB minimal DMA size workaround
                                  RashiV_61

                                  Hello Christophe,

                                   

                                  Can you comment out CyU3PDmaChannelCommitBuffer API in the PROD event.

                                  Don't call any API inside the PROD event. For AUTO and AUTO_SIGNAL channel you don't need to call CyU3PDmaChannelCommitBuffer

                                  The buffer will be committed without calling that API

                                   

                                  Regards,

                                  Rashi

                                  • 14. Re: FX3 : UART to USB minimal DMA size workaround
                                    ChRO_4339966

                                    Rashi,

                                     

                                    This did not solve the issue. Actually, removing call to this function in DMA callback makes callback useless.

                                    Nevertheless, I noticed some difference :

                                    - without call to CyU3PDmaChannelCommitBuffer in DMA callback, there is no USB frame sent on my EP

                                    - with call to CyU3PDmaChannelCommitBuffer in DMA callback, I get a USB frame, but it is empty.

                                     

                                    Christophe

                                     

                                    1 2 Previous Next