cancel
Showing results for 
Search instead for 
Did you mean: 

Delay in processing the external GPIO interrupts

AKris.4
Associate II

I am using the STM32 GO71RB for motor control, My objective is to calculate the position of the motor while its running. I am trying to find the forward/reverse position of the motor using the encoder feedback; the encoder I am using is HEDS-550.

For this, I have taken two encoder signals as External GPIO interrupts in STM controller and from the phase shift in the encoder signals, I am able to calculate my forward and reverse position correctly. I have properly tested the positioning of the motor at a speed of 250 rpm.

How ever, If I am rotating the motor at rpm of 500 and above, I am observing a delay in processing the GPIO interrupts and as a result I am observing misses in the position calculation.

I have enabled rising and falling edge detection for the above said GPIO interrupts.

In the EXTI4_15_IRQHandler, I am checking for the rising and falling edges of the GPIOs using the EXTI->RPR1 and EXTI->FPR1 registers. Based on the order in which the rising and falling edges are coming, I am calculating the forward/reverse position.

As I said earlier, the issue I am facing is that there is a delay in processing the edge interrupts and this delay is occurring occasionally only and at these times, I am missing my position calculation.

To identify the issue, I have used a GPIO pin to mimic the status of the interrupts received and when probed, I have observed that sometimes a there is a delay (60-80 microseconds at 500 rpm) in the GPIO output, ie sometimes GPIO status is changing only after a delay after the change of interrupt status. Normally, this delay is less than 10 microseconds. Also, at lower rpms like 250 rpm, this much delay is not observed.

My external interrupts are processed as follows:

void EXTI4_15_IRQHandler(void)

{

  /* USER CODE BEGIN EXTI4_15_IRQn 0 */

#if 0

        Test_dummy = 0;

        if ((__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_PIN_7)) != 0x00u)        //EF on Channel 1 (Yellow) on MSO

        {

            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, RESET);                // Channel 3 (Pink) in MSO

            Test_dummy++;

            Prev_E = B_FALL;

            __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_PIN_7);

        }

        if ((__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_PIN_7)) != 0x00u)        //ER on Channel 1 (Yellow) in MSO

        {

            HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, SET);                    // Channel 3 (Pink) in MSO

            Test_dummy++;

            if(Prev_E == A_RISE)

            {

                posCount_X++;

            }

            Prev_E = B_RISE;

            __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_PIN_7);

        }

        if((__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_PIN_8)) != 0x00u)        //ER on Channel 2 (Blue) in MSO

        {

            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, SET);                    // Channel 3 (Green) in MSO

             Test_dummy++;

            Prev_E = A_RISE;

            __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_PIN_8);

        }

        if((__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_PIN_8)) != 0x00u)        //EF on Channel 2 (Blue) in MSO

        {

            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, RESET);                // Channel 3 (Green) in MSO

            Test_dummy++;

            if(Prev_E == B_FALL)

            {

                posCount_X--;

            }

            Prev_E = A_FALL;

            __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_PIN_8);

        }

       if(Test_dummy>1)

        {

       }

#endif

  /* USER CODE END EXTI4_15_IRQn 0 */

  //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);

  //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);

  /* USER CODE BEGIN EXTI4_15_IRQn 1 */

 /* USER CODE END EXTI4_15_IRQn 1 */

}

The oscilloscope trace is as follows:

0693W00000Sw5lKQAR.jpg 

Now here the the channel 3 is supposed to follow channel 1 and Channel 4 is supposed to follow channel 2... but as you can see there is an instance in channel 3 where there is a considerable delay (right around the middle) which is almost 60us... this is a random behavior and the delay values also vary. this ideally shouldn't happen.. even worse case issue is when the delay exceeds the next edge change, in which case i can totally miss an edge.

i am using this to calculate the number of edges so this is causing a lot of issues.

Can anyone throw some support on this to identify the reason for delay in processing the GPIO interrupts.

5 REPLIES 5

So perhaps 30 KHz upward? Perhaps the code isn't tight enough​ and you're saturating or swamping the MCU?

C​an you use TIM in Encoder Mode, or to measure the phase relationship between a pair of signals?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
AKris.4
Associate II

I am using the 64MHz clock. I am not doing much to saturate the MCU..

Currently, I cannot use the TIM in encoder mode to get the UP/DOWN count as the corresponding pins are connected to other inputs.

A lot of the HAL scales poorly.

Watch also other interrupt of higher priority, or that might block.

I'd expect it should be able to get into the hundreds of KHz. Perhaps toggle some GPIO to gauge latency or missing counts via a logic analyzer or scope.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Updated the original post with the Interrupt code and the MSO plot.

also we have made the GPIO as the highest priority. there are 2 other interrupt (SPI and timer) but they have priority as 2 compared to 0 for GPIO.

S.Ma
Principal

Probably the WCET is too large.

Do you check in the exti interrupt possible overruns? Say both rise and fall occured, or the pin level has unexpected level?

Timer captures, ideally with dma on ram loop relaxes the WCET min latency for normal operation.

Check all yout interrupts, their latency, their frequency, their priority, and deduct the limit.

When the sw and time is not enough, time to optimize or use more HW resources.