11 Replies Latest reply on Aug 6, 2020 9:23 PM by AlEr_4025481

    FX3 data lost during DMA transfer

    AlEr_4025481

      Hi there,

       

      I'm fighting with data lost during DMA transfer and totally stuck on two questions... To be sure that received data is monotonic I attached an FPGA which works as a basic counter. FPGA sends to FX3 512 byte blocks, each block filled by 16-bit block number. For example, first 512 bytes of data filled by 0x0000, 2nd 512 bytes filled by 0x0001, 3rd 512 bytes filled by 0x0002 and so on. Verilog source code is below.

      module main(
          input RD,
          input RST,
          output [15:0] DATA,
      output LED
          );
      
      reg [23:0] counter;
      
      always @(negedge RST or posedge RD)
      begin
      if (!RST)
      counter <= 0;
      else
      counter <= counter + 24'd1;
      end
      
      assign DATA = counter[23:8];
      assign LED = counter[13];
      
      endmodule
      

      FX3 GPIF configured as master async device, each DATA_IN action asserts RD output.

      2020-08-02_21-38-37.png

      DMA configuration:

          dmaCfg.size = 16384;
          dmaCfg.count = 1;
          dmaCfg.prodSckId = CY_U3P_PIB_SOCKET_0;
          dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_1;
          dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
          dmaCfg.notification = 0;
          dmaCfg.cb = NULL;
          dmaCfg.prodHeader = 0;
          dmaCfg.prodFooter = 0;
          dmaCfg.consHeader = 0;
          dmaCfg.prodAvailCount = 0;
      

      As soon as vendor code received data transfer starts with CyU3PGpifSMSwitch() API. Every tyme I'm trying to get exactly 16384 bytes of data through bulk IN EP, no less, no more, because GPIF SM uses LD_DATA_COUNT action and grabs only 8192 words (16384 bytes). But unfortunately sometimes I see a data lost in the MIDDLE of transfer. Sometimes data received correctly, sometimes not. And as I see when data lost happens, it's always happens at the same offset between 0x0008 and 0x0009 words as on the 3rd picture below.

      2020-08-02_21-23-11.png

      2020-08-02_21-27-15.png

      2020-08-02_21-29-36.png

      So my first question is what I missed? Should I change something in GPIF or DMA config?

        • 1. Re: FX3 data lost during DMA transfer
          AlEr_4025481

          Another problem concerns GPIO and GPIF. As you see above my FPGA has reset input, reset happens when it asserts from high to low (on negative adge). So my FX3 source code uses DQ16 pin as reset output for FPGA.

          #define FPGA_RST_GPIO (33) /* FX3 DQ16 pin */
          ...
          gpioConfig.inputEn = CyFalse; // Configured as output
          gpioConfig.outValue = CyTrue; // Default RST level is HIGH (inactive state)
          gpioConfig.driveLowEn = CyTrue;
          gpioConfig.driveHighEn = CyTrue;
          gpioConfig.intrMode = CY_U3P_GPIO_NO_INTR;
          
          apiRetStatus = CyU3PDeviceGpioOverride (FPGA_RST_GPIO, CyTrue);
          ...
          apiRetStatus = CyU3PGpioSetSimpleConfig(FPGA_RST_GPIO, &gpioConfig);
          ...
          

           

          When reset output physically connected to FPGA every requested 16384 bytes of data starts from 0x0000 pattern (1st 512 bytes filled by 0x0000, 2nd 512 bytes filled by 0x0001 and so on). I mean it looks like reset output was toggled (driven from high to low) however my code do not uses CyU3PGpioSetValue(). As I see it happens when GPIF state machine reaches the final state. And as soon as I disconnect reset wire received data back to normal view, first 16384 bytes includes patterns from 0x0000 to 0x001F,  second 16384 bytes includes pattern from 0x0020 do 0x003F and so on.

           

          Is this normal for overridden GPIO? What I should to do to leave GPIO completely untouched when GPIF switches many tymes?

          • 2. Re: FX3 data lost during DMA transfer
            JayakrishnaT_76

            Hello,

             

            Are you facing the data loss while you try to transfer the first 16384 bytes? Or is it like the data loss is seen after you transfer multiple 16384 bytes? According to my understanding, you always transfer 16384 bytes from the FPGA to FX3. So, you can use the transition equation from STATE1 to STATE2 as !DATA_CNT_HIT.

            From the state machine and firmware, I understand that a vendor command is used to start the collection of data. Upon receiving this vendor command, the state machine switches to MYSTART state. Instead of this implementation can you try the following:

            1. Initially the state machine goes to IDLE state which is a start state.

            2. From IDLE, it transitions to STATE3.

            3. In STATE3, INTR_CPU is used. So the state machine passes the control to firmware (CyFxIntrCallback).

            4. In the function CyFxIntrCallback, check if the vendor command is received or not. This can be done by setting a global variable upon reception of the vendor command and checking the value of the global variable inside the function CyFxIntrCallback.

            5. If the value of the global variable is not set, then call the API CyU3PGpifControlSWInput(CyFalse). Please check the description of this API from the API guide.

            6. If the value of global variable is set, then reset the global variable and call the API CyU3PGpifControlSWInput(CyTrue).

            7. Remove the API CyU3PGpifSMSwitch in the vendor command implementation.

            8. Also, please try de-selecting the Repeat actions until next transition for STATE1.

            9. Use the state machine whose snapshot is attached below:

             

             

            Please try these and let me know if you are seeing any improvements.

             

            Best Regards,

            Jayakrishna

            • 3. Re: FX3 data lost during DMA transfer
              AlEr_4025481

              Hi Jayakrishna,

               

              Thanks for your reply!

               

              Are you facing the data loss while you try to transfer the first 16384 bytes? Or is it like the data loss is seen after you transfer multiple 16384 bytes?

              Data lost happens in random order, sometimes it happens in the first 16384 byte block (right after FX3 firmware started and 1st vendor command 0x00AB received), sometimes that first block may be transferred without data lost, but in this case data lost happens in next block.

               

              According to my understanding, you always transfer 16384 bytes from the FPGA to FX3. From the state machine and firmware, I understand that a vendor command is used to start the collection of data. Upon receiving this vendor command, the state machine switches to MYSTART state.

              Yes, that's absolutely correct.

               

              I did as your explained, but FX3 freezes right after CyU3PGpifSMStart(). I don't see any debug messages from my main thread loop and blue led is not blinking:

              // This loop is not executed   
               for (;;)
                  {
                  CyU3PGpioSetValue(LED_GPIO, CyFalse);
                      CyU3PThreadSleep (250);
                  CyU3PGpioSetValue(LED_GPIO, CyTrue);
                      CyU3PThreadSleep (1750);
                  CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "EP0 requests count (%d), interrupt count (%d)\r\n",
                  request_counter, gpif_intr_counter);
                  }
              

               

              My state machine looks like:

              2020-08-03_21-19-27.png

              Modified part of my source code:

              ...
              volatile CyBool_t gpif_fw_triggered = CyFalse;
              
              ...
              void CyFxIntrCallback(uint8_t stateId)
              {
                   gpif_intr_counter++;
              
                   if (gpif_fw_triggered == CyTrue)
                   {
                        gpif_fw_triggered = CyFalse;
                        CyU3PGpifControlSWInput(CyTrue);
                   } else
                        CyU3PGpifControlSWInput(CyFalse);
              }
              ...
              CyBool_t CyFxUsbSetupCB (uint32_t setupdat0, uint32_t setupdat1)
              {
              ...
                   gpif_fw_triggered = CyTrue;
                   //apiRetStatus = CyU3PGpifSMSwitch(256, MYSTART, 256, ALPHA_MYSTART, 0);
              ...
              }
              

               

              Full sources are attached.

              • 4. Re: FX3 data lost during DMA transfer
                AlEr_4025481

                Still waiting for help...

                • 5. Re: FX3 data lost during DMA transfer
                  RashiV_61

                  Hello,

                   

                  Please find the attached firmware with modifications in the GPIF state machine and firmware

                  Modifications to state machine are as follows:

                  sm.PNG

                  Initially, when the state machine is started it will go to STATE3 and do nothing. As soon as Vendor command (AB) is sent from the host the GPIF state machine will transition to State0.

                  In State1 the option of repeat actions until next transition is disabled so that counter increments only when there is a Data IN

                  And when one block of data is read or data counter hits there will be an interrupt to CPU and GPIF state machine will again go to State 3 and wait for next vendor command

                   

                  Please test this firmware and let me know results

                   

                  Regards,

                  Rashi

                  • 6. Re: FX3 data lost during DMA transfer
                    AlEr_4025481

                    Hello again,

                     

                    I spent a lot of time for experiments and result are still bad. First, I have added one more state to GPIF:

                    2020-08-05_13-21-06.png

                    Then I made sure that FX3 generates exactly 8192 RD pulses:

                    2020-08-05_12-49-54.png

                    First received 16384 shown below:

                    2020-08-05_12-56-40.png

                    2020-08-05_13-03-10.png

                    2020-08-05_13-06-53.png

                    As you can see there is two huge problems:

                    1. Data lost ALWAYS starts from offset 0x21FC, from each 16384 bytes two 16-bit words (four bytes) are lost.

                    2. Also data lost happens BETWEEN receiving each 16384 bytes. On the last two pictures only 508 bytes filed by 0x0020, two 16-bit words (four bytes) are lost.

                     

                    I have to say checking or unchecking "repeat actions until next transaction" on STATE1 (or any other state N) changes nothing. I even tried to use other lines as RD (CTL1, CTL2, CTL3 and so on) - nothing changes too. I thought about electrical noises, but my wires are short (~10 cm) and three GND wires are between FX3 and FPGA. Also my FPGA works well with Arduino Due, no data lost happens.

                     

                    Is it possible my FX3 has some kind of hardware bug?

                    DSCN9142.JPG

                    • 7. Re: FX3 data lost during DMA transfer
                      RashiV_61

                      Hello,

                       

                      Please try this state machine with some modifications and let me know the results

                      sm_1.PNG

                       

                      - After modifying the state machine please check the RD toggle is proper as checked in your response i.e. 8192 transitions  from low to high

                      - Along with the changes in the state machine, please do the following changes in the firmware

                      1) Change the DMA channel from CY_U3P_DMA_TYPE_AUTO to CY_U3P_DMA_TYPE_AUTO_SIGNAL

                      2) Change the DMA channel configuration by registering for PROD/CONS events and DMA callback

                       

                          dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;

                          dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;

                          dmaCfg.cb = CyFxDmaCallback; //NULL;

                          dmaCfg.prodHeader = 0;

                          dmaCfg.prodFooter = 0;

                          dmaCfg.consHeader = 0;

                          dmaCfg.prodAvailCount = 0;

                       

                         

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

                          if (apiRetStatus != CY_U3P_SUCCESS)

                          {

                              CyU3PDebugPrint (CY_FX_DEBUG_PRIORITY, "CyU3PDmaChannelCreate failed, Error code = %d\r\n", apiRetStatus);

                              CyFxAppErrorHandler (apiRetStatus);

                          }

                       

                      3) In the DMA callback track, the Prod and Cons event and later print it in the for{} loop

                       

                      *************Add this to the code***************

                      void

                      CyFxDmaCallback (

                              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)

                          {

                              glDMARxCount++;      // global variable

                          }

                       

                          if (type == CY_U3P_DMA_CB_CONS_EVENT)

                          {

                              glDmaTxCount++;    // global variable

                          }

                      }

                       

                      Print the values of the variables used for tracking the events

                      for (;;)

                          {

                              CyU3PThreadSleep (1000);

                              if (glIsApplnActive)

                              {

                                  /* Print the number of buffers received so far from the USB host. */

                                  CyU3PDebugPrint (6, "Data tracker: RxCount: %d, TxCount: %d\r\n", glDMARxCount, glDmaTxCount);

                              }

                       

                      .....

                      }

                       

                      4) After passing the vendor command (for the first time) please check that the PROD event   ( RxCount)  has incremented or not. After the RxCount incremented  (i.e.e the DMA buffer is full /ready to be consumed) do a Transfer IN (BULK IN).

                      Note: Transfer IN (BULK IN transfer) should not be done before  RxCount is incremented

                      Please share the debug prints.

                       

                      If possible probe the data lines (16-bit data bus) along with the RD signal and share the traces.

                       

                      Please let me know if any queries on this.

                       

                      Regards,

                      Rashi

                      • 8. Re: FX3 data lost during DMA transfer
                        AlEr_4025481

                        Hi Rashi,

                         

                        Thanks a lot for your reply. I understand your idea, I will try it tomorrow and share the results.

                        • 9. Re: FX3 data lost during DMA transfer
                          AlEr_4025481

                          Hi Rashi,

                           

                          I modified my source code according your advice, and now it looks like state machine works wrong. When first vendor command received GPIF makes less than 8192 RD pulses. My logic analyzer counts 8189 full pulses and last pulse not completed (was not togged from low to high).

                          2020-08-06_12-09-11.png

                          Received data is not correct, two words are still missing at the same offset 0x21FC.

                          2020-08-06_12-37-34.png

                          Debug output:

                          Event: CY_U3P_USB_EVENT_VBUS_VALID
                          Event: CY_U3P_USB_EVENT_CONNECT
                          Initialization completed.
                          Event: CY_U3P_USB_EVENT_SET_SEL
                          Event: CY_U3P_USB_EVENT_SETCONF
                          Connected to Super-Speed host.
                          Unknown EP0 request received
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0) <<< Vendor command sent here
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          ...
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN <<< A lot of CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          ...
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          glDmaRxCount (1), glDmaTxCount (0)
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          
                          ...
                          CYU3P_PIB_ERR_THR0_WR_OVERRUN <<< A lot of CYU3P_PIB_ERR_THR0_WR_OVERRUN
                          ...
                          

                           

                          As I found CYU3P_PIB_ERR_THR0_WR_OVERRUN goes away when I replaced 2nd !DATA_CNT_HIT by LOGIC_ONE:

                          2020-08-06_12-44-03.png

                          RD pulses count is 8192, but received data is still not valid, two words are missing as on the picture above (same offset 0x21FC).

                           

                          Debug output:

                          Event: CY_U3P_USB_EVENT_VBUS_VALID
                          Event: CY_U3P_USB_EVENT_CONNECT
                          Initialization completed.
                          Event: CY_U3P_USB_EVENT_SET_SEL
                          Event: CY_U3P_USB_EVENT_SETCONF
                          Connected to Super-Speed host.
                          Unknown EP0 request received
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (0), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0) <<< Vendor command sent here
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (0)
                          glDmaRxCount (1), glDmaTxCount (1) <<< Data transferred to host
                          glDmaRxCount (1), glDmaTxCount (1)
                          glDmaRxCount (1), glDmaTxCount (1)
                          glDmaRxCount (1), glDmaTxCount (1)
                          glDmaRxCount (1), glDmaTxCount (1)
                          
                          • 10. Re: FX3 data lost during DMA transfer
                            RashiV_61

                            Hello,

                             

                            I have tested the attached firmware at my end.

                             

                            1) I have pulled up DQ[15] pin and then passed the vendor command. On transfer IN I don't see the data loss

                            2) For the second test,I have pulled up DQ[1] pin and then passed the vendor command. I don't see the data loss in this case as well

                             

                            Here are the debug prints for the same

                            teraterm_prints.PNG

                             

                            From this test, we can confirm that the problem is not on the FX3 hardware but it might be in the synchronization between FX3 (IN DATA) and FPGA (DATA_OUT).

                            There is a possibility that data is not in sync with the DATA IN of FX3.

                             

                            To confirm that we would need the traces of data lines (16 bit) along with the RD signal. Please probe the data bus along with the RD signals and share the traces.

                             

                            Regards,

                            Rashi

                            • 11. Re: FX3 data lost during DMA transfer
                              AlEr_4025481

                              Hi Rashi,

                               

                              I already made a lot of experiments with different FPGA and logic analyzer. It seems my FX3 has a bug, so I ordered another board based on CYUSB3014. I'll compare both and hope second board will work correctly. I will post results later.