1
\$\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\$
5
  • 1
    \$\begingroup\$ Well, maybe when you call HAL_Delay from inside an interrupt handler it prevents the systick timer from calling the interrupt handler for the systick counter. Meanwhile, Hal_Delay is actually waiting for the systick timer to increment by 1000, but that never happens. \$\endgroup\$ – mkeith May 8 at 6:53
  • \$\begingroup\$ I am not super good with this stuff, but if you can make sure the systick timer ISR has higher priority than EXTI0_IRQHandler(), maybe that would resolve the issue by allowing systick to pre-empt it and thus continue to function. \$\endgroup\$ – mkeith May 8 at 6:55
  • \$\begingroup\$ it's just like you said \$\endgroup\$ – İbrahim ATİKER May 8 at 7:04
  • 1
    \$\begingroup\$ problem solved thank you very much mkeith \$\endgroup\$ – İbrahim ATİKER May 8 at 7:04
  • 1
    \$\begingroup\$ @mkeith I don't remember the specifics of STM32 but generally interrupt priorities decide who gets to interrupt next. They typically don't allow interrupts to interrupt other interrupts. So you get an ADC and UART interrupt while you are executing another ISR, the MCU picks the one with the highest priority after you are done executing the current one. \$\endgroup\$ – Lundin May 10 at 9:11
3
\$\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\$
2
\$\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, privacy policy and cookie policy

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