cancel
Showing results for 
Search instead for 
Did you mean: 

EXTI0 double interrupt on one edge

Guidoted
Associate III

I developed a 62.5kbit synchronous self-clocked (similar to SDLC) communication firmware for STM32F412, to be interfaced with an old device via RS485.
It works in "bitbanging" using a 16us interrupt timer (TIM11) to sample the bits and EXTI0 (PB0) interrupt on both rising and falling edges to synchronize the timer for a center of bits data sampling.
There is a problem with EXTI0 interrupt, because few times I have two interrupts intead of one, in one of the front.
With an oscilloscope I've seen that there are no spikes or glitches on PB0 and the signal edges are right.
My EXTI0 interrupt code duration is less than 3us and TIM11 interrupt code duration is less than 4us.

EXTIO interrupt has priority of 0,0 and TIM11 interrupt has priority of 0,1


This is my simple EXTI0 interrupt code:

void EXTI0_IRQHandler(void)
{
   /* USER CODE BEGIN EXTI0_IRQn 0 */

   ...my code...

   /* USER CODE END EXTI0_IRQn 0 */

   HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

  /* USER CODE BEGIN EXTI0_IRQn 1 */

  /* USER CODE END EXTI0_IRQn 1 */
}

 

What can be the issue and how can it be solved?

Thanks ad best regards

G

 

8 REPLIES 8

> I have two interrupts instead of one,

One potential cause is late clear of flag which causes the interrupt.

But also note, that EXTI interrupts are asynchronous and can capture very fast impulses - are you sure your oscilloscope has enough bandwidth and sampling frequency?

JW

 

Many thanks for the answer Jan.

My scope in 200 MHz 1GS/s.

I modified my code as follows, and it seems to improve but not solve the issue:

 

void EXTI0_IRQHandler(void)
{
    /* USER CODE BEGIN EXTI0_IRQn 0 */
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)

    {
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);

        ...my code...

        if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET) {
            __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);    // just to be sure to clear any pending IRQ
        }

    }

    /* USER CODE END EXTI0_IRQn 0 */

    // HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

    /* USER CODE BEGIN EXTI0_IRQn 1 */

    /* USER CODE END EXTI0_IRQn 1 */
}

 

What I found now is that sometimes I have the exti0 interrupt even few hundreds of ns or few us BEFORE the rising or falling edge, and this is very strange.

What I'm doing is also to enable and disable the EXTI0 interrupt in the TIM11 interrupt code, to have the EXTI0 interrupt only when it is needed; normally it would happen in the middle of the bit, about 8us from the rising or falling edge.

To enable and disable it I use HAL_NVIC_EnableIRQ(EXTI0_IRQn) and HAL_NVIC_DisableIRQ(EXTI0_IRQn).

Thanks again for the help.

Best regards

G

The "... also to enable and disable the EXTI0 interrupt in the TIM11 interrupt code ..." makes me think of:

You do clear the EXTI0 flags explicitly right before enabling the EXTI0 interrupt?

Thanks Andreas.

I've done it, but it adds troubles, losing clock synchronizing, so I eliminated that...

I need to investigate why it happens.

Thanks and best regards

G

 

To exclude the possibility EXTI catches fast spikes, replace it with timer input capture's interrupt. TIMx_CHx is synchronous, i.e. clocked by the timer's internal clock, and can be further filtered, see TIMx_CCMRx.ICxF bitfield.

PB0 appears to be TIM3_CH3 (TIMx_CHxN are unusable as inputs).

JW

If this causes trouble, then there is some flaw in your program logic. Interrupts are enabled to detect *future* edges, not ones from the past (as it would be totally unclear when they occurred), hence it is vital to clear the flags before looking for a following edge.

I never used and explored the timer input capture's interrupts capability, I must learn about it and I have to see if I could still use the PB0 as "clock synchronizer" and as input pin to read the bit value at the same time.

Thanks and best regards

G

 

Yes, I agree and I have to investigate what happens and why...

Thanks and best regards

G