12 Replies Latest reply on Jun 19, 2020 1:28 AM by RashiV_61

    FX3 UART to USB DMA "Wrap Up" problem.

    AnMc_4664421

      I have an application based on the UsbUart example.  The only major difference is that I am using the alternative UART TxD and RxD pins, compared to those used on the Dev Kit.

       

      The PC host application polls the hardware attached to the FX3 as ~1 second intervals, the response messages vary in length from a few bytes to ~120 bytes.

      My problem is that occasionally return messages get "garbled".  My guess is that the periodic, but asynchronous to incoming requests, "wrap up" operation in the `for (;;)` loop in `USBUARTAppThread_Entry()`  with its disable/enable of the UART is causing the problem.

       

      If I omit the "wrap up" then incomplete messages are returned, with the tail of the previous coming through with the beginning of the next, and shorter messages don't get through until (I assume) the DMA buffer is filled.  I've experimented with different buffer sizes, which can help with the longer responses if larger, but makes it worse for the shorter ones.

       

      If I omit the disable/enable, then after a while (~1 hour) the serial communications over USB lock up altogether.

       

      I have tried making the USB to UART DMA channel "AUTO_SIGNAL" and using the notification of a CONSUME event to set a flag to expect to need to wrap up, which could later be cleared after wrap up to avoid unnecessary disable/enable sequences, but this never seems to get triggered.  Would making it MANUAL work?, If so, what should the callback look like?  OTOH, should I just bypass the DMA altogether, and if so, can you give me some pointers as how this should look?

       

      I thought that this thread:  FX3 : UART to USB minimal DMA size workaround   might hold a solution, since the described problem seemed to match mine, but the solution suggested seemed just to point back to implementing the UsbUart example, and thus back to square one.

        • 1. Re: FX3 UART to USB DMA "Wrap Up" problem.
          RashiV_61

          Hello,

           

          The CyU3PDmaChannelSetWrapUp API is used to wrap and commit the partial buffer to the consumer socket. If the CyU3PDmaChannelSetWrapUp API is not called the DMA buffer only be committed when it is FULL.

           

          - Is there some pattern of the data sent through UART? Is the size of the data to be transferred fixed?

          - Can you share the debug prints of the problem that is faced while using CyU3PDmaChannelSetWrapUp API. This will help me to understand the problem better.

          - Please let me know the DMA buffer size being used in the firmware.

           

           

          I have tried making the USB to UART DMA channel "AUTO_SIGNAL" and using the notification of a CONSUME event to set a flag to expect to need to wrap up, which could later be cleared after wrap up to avoid unnecessary disable/enable sequences, but this never seems to get triggered.

          >> The CONS event is triggered when the consumer (USB in this case) consumes the data. Please let me why do you use this approach.

          To get the CONS event, it should be registered as shown below and then this event needs to be parsed in dmacallback

           

          dmaConfig.notification   = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

           

          void

          CyFxApplnDmaCallback (

                  CyU3PDmaMultiChannel *chHandle,

                  CyU3PDmaCbType_t      type,

                  CyU3PDmaCBInput_t    *input

                  )

          {

              CyU3PDmaBuffer_t    dmaBuffer;

              CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

           

              if (type == CY_U3P_DMA_CB_PROD_EVENT)

              {

          }

          else if (type == CY_U3P_DMA_CB_CONS_EVENT)

              {  

          }

           

          Regards,

          Rashi

          • 2. Re: FX3 UART to USB DMA "Wrap Up" problem.
            AnMc_4664421

            RashiV_61 wrote:

             

            The CyU3PDmaChannelSetWrapUp API is used to wrap and commit the partial buffer to the consumer socket. If the CyU3PDmaChannelSetWrapUp API is not called the DMA buffer only be committed when it is FULL.

            This I understand.

             

            - Is there some pattern of the data sent through UART?

            - Is the size of the data to be transferred fixed?

            Not really, most messages end with a CRLF sequence, but some larger transfers include CRLF within the message to format it for human readability with a simple terminal program.

            The data size is not fixed.

            The hardware attached to the UART and the application interrogating it are 3rd party and I have no control over these.  My H/W with the FX3 is intended to be a transparent middle man in the exchange of messages.

             

            - Can you share the debug prints of the problem that is faced while using CyU3PDmaChannelSetWrapUp API. This will help me to understand the problem better.

            There is no debug channel, and with my hardware assembled to the target hardware, I physically can't connect a JTAG debugger.  I rely on a logging facility in the 3rd party application to give me some insight into what it is seeing and how it is interpreting the responses.

             

            - Please let me know the DMA buffer size being used in the firmware.

            I started with the 32 bytes from the UsbUart example, and I have also tried 16 bytes (the minimum) and 128 bytes (just a bit longer than the most frequent and most useful response).

             

            The CONS event is triggered when the consumer (USB in this case) consumes the data. Please let me why do you use this approach.

            No, I have tried using the CONS event in the USB -> UART channel to indicate that a request has been sent to the attached hardware and a response is to be expected which will require "wrapping up".

            I have in my code:

                 ...

                 dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

                 dmaCfg.cb           = CyFxUSB2UARTDmaCallback;

                 ...

             

                /* AWM - Made AUTO_SIGNAL to attempt to synchronise with incoming requests */

                apiRetStatus = CyU3PDmaChannelCreate(&glChHandleUsbtoUart, CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaCfg);

             

            and the callback function is:

            /* Callback for USB to UART DMA events:

            * If the USB has produced data, signal via the RED LED OFF,

            * if the UART has consumed the data, signal via RED LED ON

            * and clear the buffer-flushed flag.

            * This is an AUTO DMA channel, no data commit required.     */

            void CyFxUSB2UARTDmaCallback (CyU3PDmaChannel *chHandle,  /* Handle to the DMA channel. */

                                          CyU3PDmaCbType_t type,      /* Callback type.             */

                                          CyU3PDmaCBInput_t *input)   /* Callback status.           */

            {

                if (type == CY_U3P_DMA_CB_PROD_EVENT)

                {

                    CyU3PGpioSetValue(RED_LED_GPIO, LED_OFF);

                }

                else if (type == CY_U3P_DMA_CB_CONS_EVENT)

                {

                    /* Clear the buffer-flushed flag, so the channel will get wrapped up */

                    glUART_RxBufferFlushed = CyFalse;

                    CyU3PGpioSetValue(RED_LED_GPIO, LED_OFF);

                }

            }

            Here, the RED LED is used as a means of signalling to me, via a 'scope, that something is happening, but I never see this event.

             

            The UART to USB DMA callback is as follows:

            /* Callback for UART to USB DMA events:

            * If the UART has produced data, commit it to the USB channel. */

            void CyFxUART2USBDmaCallback (CyU3PDmaChannel *chHandle, /* Handle to the DMA channel. */

                                          CyU3PDmaCbType_t type,     /* Callback type.             */

                                          CyU3PDmaCBInput_t *input)  /* Callback status.           */

            {

                if (type == CY_U3P_DMA_CB_PROD_EVENT)

                {

                    CyU3PDmaChannelCommitBuffer(&glChHandleUarttoUsb, input->buffer_p.count, 0);

                    glPktsPending++;

                }

                else if (type == CY_U3P_DMA_CB_CONS_EVENT)

                {

                    /* Decrement the packets pending counter, limiting at 0 */

                    if (glPktsPending >= 1)

                    {

                        glPktsPending--;

                    }

                    else

                    {

                        glPktsPending = 0;

                    }

                }

            }

             

            Finally, the periodic wrap up is as follows:

                for (;;)

                {

                    if (glIsAppUARTlnActive)

                    {

                        /* While the application is active, check for data sent during the

                         * last 50 ms. If no data has been sent to the host, use the channel

                         * wrap-up feature to send any partial buffer to the USB host.    */

                        if (glPktsPending == 0)

                        {

                            /* AWM - Do we really need to disable the UART??

                             * Perhaps it's to avoid incoming during "Wrap Up".

                             * It certainly seems that without it, the comms lock up,

                             * but with it, the comms are occasionally garbled. */

             

                            /* Check if the UART to USB DMA channel needs "wrapping up". */

                            if (glUART_RxBufferFlushed != CyTrue)

                            {

                                /* Disable UART Receiver Block */

                                UART->lpp_uart_config = regValueDs;

             

                                CyU3PDmaChannelSetWrapUp(&glChHandleUarttoUsb);

             

                                /* Re-enable UART Receiver Block */

                                UART->lpp_uart_config = regValueEn;

             

                                glUART_RxBufferFlushed = CyTrue;          /* Clear flag */

                            }

                        }

                        /* AWM - Why do this? To signify a check has been made? */

                        /* AWM- Commented out while we try doing the decrement in the DMA call-back,

                         * which appears to be working. */

            //          glPktsPending = 0;

                    }

                    CyU3PThreadSleep(50);

                }

             

            Cheers,

            Andy

            • 3. Re: FX3 UART to USB DMA "Wrap Up" problem.
              RashiV_61

              Hello Andy,

               

              Here is what I understood from your previous posts and I am having few questions for better understanding of the issue

               

              >>Data is sent from UART to USB when host application polls USB endpoint. Is this correct? Or is the data sent from USB to UART?

              >> Is some data sent from USB to UART while polling?

              >> what is the minimum bytes of data that is transferred?

               

              No, I have tried using the CONS event in the USB -> UART channel to indicate that a request has been sent to the attached hardware and a response is to be expected which will require "wrapping up".

              >> Is this channel used as feedback ?. I understood based on the response from the hardware connected to UART the CyU3PDmaChannelSetWrapUp API will be called. Is this correct?

               

              The consumer event will occur if the UART consumes the data which is sent by USB. You can try calling CyU3PDeviceReset (CyFalse) in the condition where the consumer event is checked.

               

              You can refer to this thread with a similar problem Re: Can ASCII ETX be used to produce EOP signal to DMA channel connected to FX3 UART  and let me know if this is what you are looking for.

               

              Regards,

              Rashi

               

              • 4. Re: FX3 UART to USB DMA "Wrap Up" problem.
                AnMc_4664421

                Hi Rashi,

                Thanks for your ongoing support.

                RashiV_61 wrote:

                 

                Here is what I understood from your previous posts and I am having few questions for better understanding of the issue

                 

                >>Data is sent from UART to USB when host application polls USB endpoint. Is this correct? Or is the data sent from USB to UART?

                The host application sends a character (typically a single character, no CRLF or similar) on the VCOM port provided by the FX3, which is forwarded to the UART Tx channel and thus to the attached hardware. This causes a response to be sent back on the Rx channel of the UART.  This response is of variable length, typically between 5 and 125 characters, but it can be much longer.  This response is returned to the host on the USB.

                 

                >> Is some data sent from USB to UART while polling?

                As described above, the "polling" is always accompanied by data from USB to UART and thus to the attached hardware.  The host does not poll the IN endpoint in the FX3.

                 

                >> what is the minimum bytes of data that is transferred?

                To the attached hardware on the UART Tx it is 1 byte.

                From the attached hardware on the UART Rx, it is 4 or 5 bytes.

                 

                >> Is this channel used as feedback ?. I understood based on the response from the hardware connected to UART the CyU3PDmaChannelSetWrapUp API will be called. Is this correct?

                My intention is that when a USB -> UART event occurs, the FX3 "knows" to expect a response on the UART Rx, which will need to be sent back to the host on the USB, and that this will need wrapping up because the message length is unlikely to be exactly an integral number of DMA buffer-size bytes.  The idea behind "knowing" that a wrap-up is required is to only do the wrap-up when necessary, and not every 50ms.

                 

                 

                You can try calling CyU3PDeviceReset (CyFalse) in the condition where the consumer event is checked.

                What will this do for me?  A reset seems quite drastic.

                 

                 

                You can refer to this thread with a similar problem Re: Can ASCII ETX be used to produce EOP signal to DMA channel connected to FX3 UART  and let me know if this is what you are looking for.

                At first glance, it does not appear to address my problem, but I will re-read it more carefully.

                 

                Regards,

                Andy

                • 5. Re: FX3 UART to USB DMA "Wrap Up" problem.
                  RashiV_61

                  Hello Andy,

                   

                  I understood the application.

                   

                  The idea of tracking the CONS event of USB to UART (AUTO SIGNAL) channel and then enabling the CyU3PDmaChannelSetWrapUp up API is correct.

                   

                  To track the CONS event you can use a variable instead of LED. Try incrementing the variable and check if that value of that variable is incremented or not. You can also try setting an event and check in the for{} loop by Event GET.

                   

                  Note: There is a possibility that CyU3PDmaChannelSetWrapUp is called before the complete data is filled in the DMA buffer so to avoid that a timer can be used to give enough time to get the data into the DMA buffer and then wrapping the DMA buffer

                   

                  Please let me know the results that are you observing any change in the variable which is incremented when CONS  event  (USB > UART channel) occur

                   

                  Let me know if any queries on this

                   

                  Regards,

                  Rashi

                  • 6. Re: FX3 UART to USB DMA "Wrap Up" problem.
                    AnMc_4664421

                    Hello Rashi,

                     

                    Working with a colleague, we have come up with pretty much the solution that you suggest, thanks.  The delay in replying is because we wanted to do some overnight testing.

                     

                    To track the CONS event you can use a variable instead of LED. Try incrementing the variable and check if that value of that variable is incremented or not. You can also try setting an event and check in the for{} loop by Event GET.

                    The LED was only ever used to provide some external indication of what was going on inside.  We did come up with the idea to increment a variable to detect changes and test for changes in the external timed loop.

                     

                    Note: There is a possibility that CyU3PDmaChannelSetWrapUp is called before the complete data is filled in the DMA buffer so to avoid that a timer can be used to give enough time to get the data into the DMA buffer and then wrapping the DMA buffer

                    My colleague spotted this possibility too.  So, the first time the test is made in the for (;;) loop, which, as you say could be too soon, we flag that the variable had not incremented then wait another delay time to check again.  Two non-increments in a row means that we wrap up the buffer, if there is an increment, then the new variable value is stored locally for the next comparison, the "has_not_changed" flag is cleared and we sleep again.

                     

                    This all appears to be working, but further testing is required.

                     

                    I do have one more question:  Why is it necessary to disable the UART before doing the wrap-up, then re-enable it afterwards?  This appears to be sometimes causing us further problems.

                     

                    Andy

                    • 7. Re: FX3 UART to USB DMA "Wrap Up" problem.
                      RashiV_61

                      Hi Andy,

                       

                      Is the problem resolved?

                       

                      Regards,

                      Rashi

                      • 8. Re: FX3 UART to USB DMA "Wrap Up" problem.
                        AnMc_4664421

                        Rashi asked:

                         

                        Is the problem resolved?

                        I'm afraid not.

                         

                        Were you able to get an answer to my question:

                        Why is it necessary to disable the UART before doing the wrap-up, then re-enable it afterwards?

                         

                        I found that when implementing the original version, closely based on the Cypress UsbUart example project, omitting this step got away from the "garbling" of the return data from UART to USB, but caused the communications to completely lock up after an hour or so.  Since improving the logic for the wrap-up, as discussed above in the thread, I have also tried removing the disable again, with better results.  I am now going to run an extended test of this arrangement.

                         

                        However, I would still like to know why it was put in in the first place?  Was it to improve the behaviour with the incomplete solution as provided in the example?

                         

                        It is looking more and more as though we will have to abandon the DMA approach and do a register based byte-by-byte transfer.  Do you have any pointers for an implementation, especially the mechanism for getting the data from the UART Rx FIFO into the USB IN Endpoint for return to the host?

                         

                        Cheers,

                        Andy

                        • 9. Re: FX3 UART to USB DMA "Wrap Up" problem.
                          RashiV_61

                          Hello Andy,

                           

                          Why is it necessary to disable the UART before doing the wrap-up, then re-enable it afterwards?

                          >> CyU3PDmaChannelSetWrapUp API will wrap up the current socket and commit the data to the consumer socket. In the UsbUart example, the wrapup is done for the UART >USB channel. The receiver of the UART is disabled before wrapping up the data to avoid the incoming data to the current socket (UART socket) while the socket is being wrapped up.

                          In your application, the data from UART to USB is definite i.e. 4-5 bytes and there will no data coming to UART (RX) till a request is made by host you can try removing the UART RX enable/disable which is used in the default usbuart project.

                           

                           

                          Do you have any pointers for implementation, especially the mechanism for getting the data from the UART Rx FIFO into the USB IN Endpoint for return to the host?

                          >> For using the UART in register mode you can refer to UartLpRegmode example of the SDK. As the received data (at UART) need to be sent to USB IN endpoint a DMA channel is needed. You can use a MANUAL_OUT channel for UART > USB. The data received at the RX FIFO needs to be copied to a buffer and then the buffer can be sent through MANUAL_OUT channel to USB IN endpoint.

                          You can refer to bulksrcsink example of the SDK which implements the MANUAL_OUT channel.

                           

                          Regards,

                          Rashi

                           

                           

                           

                           

                          • 10. Re: FX3 UART to USB DMA "Wrap Up" problem.
                            RashiV_61

                            Andy,

                             

                            Adding to my previous response

                            The UART can be configured either in DMA mode or in register mode. It cannot be configured in both simultaneously.

                             

                            Regards,

                            Rashi

                            • 11. Re: FX3 UART to USB DMA "Wrap Up" problem.
                              AnMc_4664421

                              Hi Rashi,

                               

                              Thanks for your help so far.

                               

                              We didn't manage to get the callback in the USB -> UART Tx DMA channel working in AUTO_SIGNAL mode, so we implemented a register interface to and from the UART, with USB -> CPU and CPU -> USB as MANUAL_IN and MANUAL_OUT DMA channels.

                              (Confusingly here IN and OUT are relative to the CPU, and not the USB host as applied when setting up the USN endpoints.)

                               

                              Cheers,

                              Andy

                              • 12. Re: FX3 UART to USB DMA "Wrap Up" problem.
                                RashiV_61

                                Hello Andy,

                                 

                                We didn't manage to get the callback in the USB -> UART Tx DMA channel working in AUTO_SIGNAL mode, so we implemented a register interface

                                >> The CONS event for USB >UART channel will only be generated if the UART TX consumes the data from the DMA buffer. Is the 1-byte data received by the UART hardware that is connected to FX3?

                                It would be convenient for you to configure the UART in DMA mode and implement the previously mentioned suggestion.

                                - Please check whether the event CY_U3P_DMA_CB_CONS_EVENT is generated using a variable and then printing the variable in for {}. If the data is received by the external hardware (UART), the CONS event would be generated.

                                 

                                Yes, MANUAL IN ( CPU is a consumer), and MANUAL OUT (CPU is producer) channels are named with respect to the CPU and not the USB host.

                                 

                                Regards,

                                Rashi