3 Replies Latest reply on Jun 6, 2018 4:44 AM by abga

    FX3: Fast interrupt timer implementation

    jameswagner

      Hi all,

       

      I'm currently trying to implement a timer/counter with <1us of jitter.

       

      I have the the following code:

       

      GPIO CONFIGURATION:

         CyU3PGpioComplexConfig_t gpioComplexConfig;

         CyU3PGpioClock_t gpioClock;

       

         gpioClock.fastClkDiv = 10;

         gpioClock.slowClkDiv = 10;

         gpioClock.simpleDiv = CY_U3P_GPIO_SIMPLE_DIV_BY_2;

         gpioClock.clkSrc = CY_U3P_SYS_CLK_BY_4;

         gpioClock.halfDiv = 0;

         apiRetStatus = CyU3PGpioInit(&gpioClock, GPIO_Interrupt);

       

         apiRetStatus = CyU3PDeviceGpioOverride (GPIO_TIMER, CyFalse);

         if (apiRetStatus != CY_U3P_SUCCESS)

         {

            printDebugMessage("CyU3PDeviceGpioOverride failed\n");

         }

        

          // Im putting an 8KHz square wave into GPIO_TIMER
          // This will generate an interrupt every 125us

       

         gpioComplexConfig.outValue = CyFalse;

         gpioComplexConfig.inputEn = CyTrue;

         gpioComplexConfig.driveLowEn = CyFalse;

         gpioComplexConfig.driveHighEn = CyFalse;

         gpioComplexConfig.pinMode = CY_U3P_GPIO_MODE_STATIC;

         gpioComplexConfig.intrMode = CY_U3P_GPIO_INTR_TIMER_THRES;

         gpioComplexConfig.timerMode = CY_U3P_GPIO_TIMER_POS_EDGE;

         gpioComplexConfig.timer = 0;

         gpioComplexConfig.period =  0x00000001;   // Reset after each interrupt

         gpioComplexConfig.threshold = 0x00000001; //Generate interrupt every 125us

       

         apiRetStatus = CyU3PGpioSetComplexConfig(GPIO_TIMER, &gpioComplexConfig);

         if (apiRetStatus != CY_U3P_SUCCESS)

         {

           printDebugMessage("CyU3PGpioSetComplexConfig failed: %d\n",apiRetStatus);

         }

       

      GPIO INTERRUPT CALLBACK:

       

      void GPIO_Interrupt(uint8_t gpioId)

      {

         if(gpioId == GPIO_TIMER)

         {

            // Pulse TEST_GPIO for debug

            CyU3PGpioSetValue(TEST_GPIO, CyTrue);

            CyU3PGpioSetValue(TEST_GPIO, CyFalse);

         }

      }

       

       

      When I measure the signal coming out of 'TEST_GPIO', I observe pulses at 125us, as expected. HOWEVER I'm experiencing ~20us of jitter.

       

      The other data flow in this system is as follows:

      1. GPIF to USB (DMA)
      2. USB to GPIF (DMA)

       

       

      I want to set the GPIO interrupt to the highest priority, to ensure that the jitter is below 1us.

       

      I have tried to use the following API function to set the interrupt vector of the GPIO to the highest priority:

         CyU3PVicIntSetPriority(CY_U3P_VIC_GPIO_CORE_VECTOR, 0);

       

      However, the jitter is still there.

       

       

      I now want to set the interrupt from the GPIO as a fast interrupt (FIQ). Could you please help me with this?

       

       

      Regards,

      James

        • 1. Re: FX3: Fast interrupt timer implementation
          abga

          Hi,

           

          CyU3PGpioSetValue() API already has some delay before setting the hardware pin to the desired logic level. Instead of using this API you can refer to the KBA 90267 which will guide you how to set GPIO pins through registers directly:

           

          Increasing Frequency of Bit-Banged GPIO Clock in EZ-USB® FX3™ - KBA90267

           

          Please try this and confirm.

           

          Thanks & Regards

          Abhinav

          • 2. Re: FX3: Fast interrupt timer implementation
            jameswagner

            Hi Abhinav,

             

            I have implemented the gpio toggle with the register access as you suggested. This does reduce latency - however I'm really trying to reduce the jitter.

             

            I believe the source of this jitter is other interrupts which are running on the system. For this reason I want to implement the GPIO Block interrupt as an FIQ. It doesnt look like the FIQ handler has been defined for the SDK. As shown in cyu3vectors_gcc.S:

             

            .global __CyU3PFiqHandler

            __CyU3PFiqHandler:

                 b   __CyU3PFiqHandler

             

             

            I have started to write the assembly code to complete the FIQ interrupt handler, as follows:

             

            .global __CyU3PFiqHandler

            __CyU3PFiqHandler:

                stmdb   sp!, {r0-r3}                                

                mrs     r0, SPSR                                                         

                sub     lr, lr, #4                                                                

                stmdb   sp!, {r0, r10, r12, lr}                            

                bl      CyU3PFiqContextSave                              

                                                                                                                           

                ldr     r1, =CY_U3P_VIC_ADDRESS_ADDRESS       

                mov     r2, #0                                                             

                str     r2, [r1]                                                  

                ldr     r1, =CY_U3P_VIC_INT_CLEAR_ADDRESS      

                ldr     r2, =CY_U3P_VIC_GPIO_MASK            

                str     r2, [r1]                                                     

                                                                                                                           

                /*"bl      CyU3PIrqNestingStart*/           /* !!Not sure if needed for FIQ. I cant find an equivalent FIQ function */                     

                bl      CyU3PGpioCoreIntHandler                                

                /*"bl      CyU3PIrqNestingStop*/           /* !!Not sure if needed for FIQ. I cant find an equivalent FIQ function */                  

                                                                                                                           

                ldr     r1, =CY_U3P_VIC_INT_ENABLE_ADDRESS  

                ldr     r2, =CY_U3P_VIC_GPIO_MASK                  

                str     r2, [r1]                                    

                b       CyU3PFiqContextRestore            

             

            Setting the GPIO block as FIQ:

               uvint32_t *vic_int_select_p = ((uvint32_t *)(0xfffff00c));

               uvint32_t *vic_int_enable_p = ((uvint32_t *)(0xfffff0010));

               uvint32_t *vic_int_clear_p = ((uvint32_t *)(0xfffff0014));

               /* Disable GPIO Interrupt */

               *vic_int_clear_p = VIC_GPIO_MASK;

               /* Set as FIQ Interrupt */

               *vic_int_select_p = VIC_GPIO_MASK;

               /* Enable GPIO Interrupt */

               *vic_int_enable_p = VIC_GPIO_MASK;

             

             

            Can I get some assistance here. What else is involved with setting up an FIQ on the FX3?

             

             

            Regards,

            • 3. Re: FX3: Fast interrupt timer implementation
              abga

              Hi,

               

              Right now current implementation of FX3 firmware doesn't handle FIQ_Interrupt. You can generate PWM wave at GPIO. Refer to the section 8.9.4.3 of FX3 TRM.

               

              Thanks & Regards

              Abhinav