8 Replies Latest reply on Nov 28, 2018 3:49 AM by hman

    FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors

    bhoomilchavda

      Hi,

      Currently, I'm working on a data acquisition system and in which, one requirement is that when some DAQ done or any error condition or any special register read/write occurred after that time FPGA generate interrupt signal over GPIO line and due to this FX3's GPIO ISR will hit and it will put custom hex code(for testing I have used this hex code as counter which will increment each time when interrupt occurred) over Interrupt Endpoint of USB via CyU3PDmaChannelCommitBuffer() API using interruptdma channel.

       

      At my custom USB driver side, probe method executes successfully and my host can see the FX3 device as a vendor device. My custom driver have two interrupt specific IOCTL. One is ENABLE interrupt and second is DISABLE interrupt. basically, it will submit interrupt URB and kill same URB respectively. this two IOCTL is just extra control over interrupt endpoint because I don't wanna do such things in probe and disconnect method of my driver.

       

      At test application side, I can open /dev/xyz device which is created by probe method of my driver and then i will ENABLE my interrupt so that any future interrupt I can capture.

      Now Problem is occurred over here, when I submit Interrupt URB just after open device file, and perform some activity like special register read/write of FPGA to produce interrupt then 1st interrupt is occurred between FPGA and FX3 on GPIO line and I can see it over UART console of FX3 and  CyU3PDmaChannelCommitBuffer() API will put custom hex code also without any error which is totally perfect.... but at driver side, my already submitted URB is not getting any data and for that it is not executing completion callback. Now when I doing the same register read/write 2nd time to reproduce the same interrupt then my driver can able to hit that completion callback function and able to get custom hex code but that hex code is previous one.

       

      help me out... thanks in advance.

      regards,

      Bhoomil C.

        • 1. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
          hman

          Hello Bhoomil,

           

          - Can you test it on Windows PC using 'control_center.exe' application?

          - After connection the device to windows PC please bind it to cyusb3 driver.

          - Now by choosing the right endpoint you can initiate the interrupt transfers.

           

          In this way you can isolate the problem to your Linux driver code.

           

          Regards,

          Hemanth

          • 2. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
            bhoomilchavda

            Yup, I have already done such things. So using control centre utility the interrupt transfer is done successfully but Windows interrupt transfer in Synchronous. And same above Linux kind of thing I have done with custom Windows driver also.

             

            the behaviour is same in both OS using Asynchronous URB.

            • 3. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
              hman

              Hi,

               

              - Can I know for howmuch data is URB being created? And for one such request from the Host, howmuch data is the FX3 sending?

              - And Asynchronous transfers can be tested using 'streamer.exe' application.

               

              Regards,

              Hemanth

              • 4. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
                bhoomilchavda

                So the Interrupt endpoint descriptor at FX3 side have max packet len is 2 bytes.

                and at the driver side I have fill my URB same as above i.e. 2 bytes.

                 

                By the way, Cypress control center is giving me the 2 bytes data of interrupt but my requirement is not to use control center instead use our own develop custom Linux driver. And this Linux driver is as per standard I have written.

                • 5. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
                  bhoomilchavda

                  Hi hman

                  I have do following things at FX3 firmware side,

                   

                  void GPIOInterruptThread_Entry(uint32_t input)

                  {

                  static uint8_t uiIntCount = 0;

                  uint32_t eventFlag;

                  CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;

                  CyU3PDmaBuffer_t dmaInfo;

                   

                   

                      for (;;)

                      {

                  /* Wait for a GPIO event */

                   

                   

                      apiRetStatus = CyU3PEventGet (&glGPIOInterruptEvent, LEC_GPIO_INT_ACTIVE, CYU3P_EVENT_OR_CLEAR, &eventFlag, CYU3P_WAIT_FOREVER);

                          if (apiRetStatus == CY_U3P_SUCCESS)

                          {

                  if (eventFlag & LEC_GPIO_INT_ACTIVE)

                  {

                  CyU3PDebugPrint(4, "gpio intr event found \r\n");

                  uiIntCount++;

                  BlinkLED();

                   

                   

                  apiRetStatus = CyU3PDmaChannelGetBuffer(&glInterruptDmaChannel,

                  &dmaInfo, CYU3P_NO_WAIT);

                  if (apiRetStatus != CY_U3P_SUCCESS) {

                  CyU3PDebugPrint(4,

                  "DMA Get Buffer failed, interrupt missed. Code=%d\r\n",

                  apiRetStatus);

                  continue;

                  }

                   

                   

                  CyU3PMemSet(dmaInfo.buffer, (uint8_t) (0), 2);

                   

                   

                  dmaInfo.buffer[0] = uiIntCount;

                  apiRetStatus = CyU3PDmaChannelCommitBuffer(

                  &glInterruptDmaChannel, 2, 0);

                  if (apiRetStatus != CY_U3P_SUCCESS)

                  {

                  CyFxAppErrorHandler(apiRetStatus);

                  CyU3PDmaChannelReset (&glInterruptDmaChannel);

                  CyU3PDmaChannelSetXfer (&glInterruptDmaChannel, 0);

                   

                   

                  CyU3PDebugPrint(4, "DMA Commit Buffer failed, Code=%d\r\n",

                  apiRetStatus);

                  continue;

                  }

                  }

                  }

                  }

                  }

                   

                   

                  void GPIOInterruptCb(uint8_t gpioId)

                  {

                  if (gpioId == PIN_IRQ) //56)

                  {

                  CyU3PDebugPrint(4, "gpio intr occurred \r\n");

                  {

                  /* Set LEC_GPIO_INT_ACTIVE event */

                  CyU3PEventSet(&glGPIOInterruptEvent, LEC_GPIO_INT_ACTIVE, CYU3P_EVENT_OR);

                  }

                  }

                  }

                   

                   

                  And below is the endpoint descriptor for the same

                   

                      /* Endpoint descriptor for consumer EP2 */

                  0x07,                           /* Descriptor size */

                  CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

                  0x82,              /* Endpoint address and description */

                  CY_U3P_USB_EP_INTR,             /* Bulk endpoint type */

                  0x02,0x00,                      /* Max packet size = 2 bytes */

                  0x04,                           /* Servicing interval for data transfers : 0 for Bulk */

                   

                   

                  /* Super speed endpoint companion descriptor for consumer EP1 */

                  0x06,                           /* Descriptor size */

                  CY_U3P_SS_EP_COMPN_DESCR,       /* SS endpoint companion descriptor type */

                  0,     /* Max no. of packets in a burst(0-15) - 0: burst 1 packet at a time */

                  0x00,                           /* Max streams for bulk EP = 0 (No streams) */

                  0x02,0x00,                      /* Max packet size = 2 bytes */

                  • 6. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
                    hman

                    Hi,

                     

                    I have integrated your code to BulkSrcSink project.

                    And I have used streamer application to see the output and it looks good.

                    I have attached both project and the streamer application capture.

                     

                    - So, the problem is with your linux code.

                     

                    The streamer application does asynchronous transfers. So, you can refer to the implementation.

                     

                    Regards,

                    Hemanth.

                    • 7. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
                      bhoomilchavda

                      Hi hman

                       

                      Thanks for your great reply. Big Thanks to giving me the source code. So Before this testing, I would like to share one more update from my side.

                       

                      So the function below which will be called when GPIO will toggle. And Set registered GPIO event.

                       

                      void GPIOInterruptCb(uint8_t gpioId)

                      {

                      if (gpioId == PIN_IRQ) //56)

                      {

                      CyU3PDebugPrint(4, "gpio intr occurred \r\n");

                      {

                      /* Set LEC_GPIO_INT_ACTIVE event */

                      CyU3PEventSet(&glGPIOInterruptEvent, LEC_GPIO_INT_ACTIVE, CYU3P_EVENT_OR);

                      }

                      }

                      }

                       

                      AS A PART OF EXPERIMENT AND FIND OUT THE ROOT CAUSE

                      I have replace above code with below code snippet.

                       

                      void GPIOInterruptCb(uint8_t gpioId)

                      {

                      ;//Nothing...

                      }

                      void vendor_cmd_event_set(void)

                      {

                      CyU3PDebugPrint(4, "dummy gpio intr occurred \r\n");

                      {

                      /* Set LEC_GPIO_INT_ACTIVE event */

                      CyU3PEventSet(&glGPIOInterruptEvent, LEC_GPIO_INT_ACTIVE, CYU3P_EVENT_OR);

                      }

                      }

                       

                      And remove FPGA hardware and perform interrupt transfer only with the FX3 board, and firing custom vendor cmd and calling vendor_cmd_event_set() function .... then each time I get a perfect value of the interrupt counter.

                      So in short, In one sentence I would like to tell you that for host perspective whether it is Windows or Linux if I submitted my URB before doing any interrupt production related stuff then I always get that interrupt due to this pre submitted URB.

                       

                      I believe something becomes wrong when GPIO line and DMA interrupt channel work together ...

                      I have also come across at this question just a few hours back

                      FX3 interrupt capture

                       

                      thanks,

                      Bhoomil

                      • 8. Re: FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors
                        hman

                        Hi,

                         

                        You can also test with an application we have in Linux to check the difference in behavior. You can find the application in the below path:

                        <install_path>FX3_SDK_Linux_1.3.4\cyusb_linux_1.0.5.tar\cyusb_linux_1.0.5\bin

                         

                        Regards,

                        Hemanth