3
\$\begingroup\$

I wrote a simple C program for STM32:

main.c

  while (1)
  {
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
      HAL_Delay(400);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
      HAL_Delay(400);
  }

it.c

void EXTI0_IRQHandler(void)
{
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
      HAL_Delay(1000);
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
      HAL_Delay(1000);

  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

There is no problem when there is no delay interrupt; it enters ISR and exits.

But when delay interrupts, the program gets stuck at delay ().

My RCC settings are correct.

\$\endgroup\$
0

2 Answers 2

7
\$\begingroup\$

It sounds like EXTI0_IRQHandler() is preventing the systick timer from running. I believe HAL_Delay() uses the systick timer. So the timer stops incrementing and the HAL_Delay() function waits forever.

It may be possible to fix this by adjusting the priority of EXTI0_IRQHandler() lower than the systick mechanism so that systick continues to run even while EXTI0_IRQHandler() is running. Or you could re-write it so that EXTI0_IRQHandler() sets a global flag, and then read the flag in the main loop. If the flag is set, you toggle D14 in the main loop then clear the flag and call HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0) from the main loop.

\$\endgroup\$
1
  • \$\begingroup\$ Yes, by default, HAL_Delay() depends on the SysTick timer. In most cases when programming STM32 MCUs, the SysTick must have the highest priority in order to avoid deadlocks due to interrupt handlers using HAL_Delay() (which is a bad pattern anyway, but it happens, not only in the code in the question). \$\endgroup\$
    – wovano
    Jan 19, 2023 at 16:09
4
\$\begingroup\$

When studying embedded systems on the beginner level, we are always told to never write long ISRs. Especially don't call delays or print functions from inside the ISR.

Though in this case the most convenient fix might be a quick & dirty release of the global interrupt mask. Something like this:

void EXTI0_IRQHandler(void)
{
  __asm("CPSIE i"); // depending on your compiler's inline asm syntax

  ...
}

This allows other interrupts to occur even though you are still inside your ISR. Essentially you yield up your ISR's exclusive access to the CPU.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.