Skip to main content
Graduate
March 19, 2024
Question

EXTI0 double interrupt on one edge

  • March 19, 2024
  • 2 replies
  • 2250 views

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

 

    This topic has been closed for replies.

    2 replies

    Super User
    March 19, 2024

    > 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

     

    GuidotedAuthor
    Graduate
    March 20, 2024

    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

    Explorer II
    March 20, 2024

    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?

    Super User
    March 20, 2024

    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

    GuidotedAuthor
    Graduate
    March 20, 2024

    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