FX3: Fast interrupt timer implementation

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

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

0 Likes
1 Solution
abhinavg_21
Moderator
Moderator
Moderator
50 likes received 25 likes received 10 likes received

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

View solution in original post

0 Likes
3 Replies
abhinavg_21
Moderator
Moderator
Moderator
50 likes received 25 likes received 10 likes received

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

0 Likes
Anonymous
Not applicable

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,

0 Likes

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

0 Likes