cancel
Showing results for 
Search instead for 
Did you mean: 

GPIO_EXTI example – HAL_NVIC_EnableIRQ() not ending

Sebastian Gniazdowski
Associate III
Posted on January 19, 2017 at 21:19

I'm compiling and running GPIO_EXTI example code for Nucleo-F767ZI board (on SW4STM32). The handler that blinks LED1 isn't connected and this matches what readme.txt says:

In this example:

    - EXTI_Line15_10 is connected to PC.13 pin

      - when falling edge is detected on EXTI_Line15_10 by pressing User push-button, LED1 toggles once

On STM32F767ZI-Nucleo:

    - EXTI_Line15_10 is connected to User push-button

So, handler isn't set for the Nucleo board. When I push user button and pause (debugging) the program, it is then in default handler / infinite loop. All correct.

However, the program never goes beyond those lines of EXTI15_10_IRQHandler_Config(void):

  /* Enable and set EXTI line 15_10 Interrupt to the lowest priority */

  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);

  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

When I pause, I'm still in HAL_NVIC_EnableIRQ(), the program never returns to main() to do its infinite while() loop. As already said above, it however does react to user button, so the IRQ is correctly enabled.

I attach state after step-into the function, and step over its content. As it can be seen, the program forever runs that line (thread state says: 'Running: Step').

UPDATE: Here is the source code (main.c) of the GPIO_EXTI example, copied from official CubeMX package for F767 (V1.5.1):

http://pastebin.com/kBRT2ApU

 

Best regards,

Sebastian

#irq #examples #hang #exti_irqhandler #stm32cubemx-examples* #nucleo-f767zi
1 ACCEPTED SOLUTION

Accepted Solutions
Sebastian Gniazdowski
Associate III
Posted on January 22, 2017 at 20:00

Solution: empty while loop in main() has been optimized away to such extent that the debugger was showing last executed instruction in HAL_NVIC_EnableIRQ(). So it looked like if program was stuck in that call. Adding a volatile variable to the loop revealed that everything is fine.

View solution in original post

8 REPLIES 8
Posted on January 19, 2017 at 22:22

The Cortex-Mx processors need you to clear the source of the interrupt, otherwise they will continually tail-chain and no foreground execution will occur. You need to review what your IRQHandler code is doing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on January 20, 2017 at 14:19

It's not my IRQHandler – this is an official example. There is no IRQHandler, but HAL_GPIO_EXTI_Callback(). I tried to add __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13) here:

static void EXTI15_10_IRQHandler_Config(void)

{

  GPIO_InitTypeDef   GPIO_InitStructure;

  /* Enable GPIOC clock */

  __HAL_RCC_GPIOC_CLK_ENABLE();

  /* Configure PC.13 pin as input floating */

  GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;

  GPIO_InitStructure.Pull = GPIO_NOPULL;

  GPIO_InitStructure.Pin = GPIO_PIN_13;

  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

  // The added line

  __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13);

  /* Enable and set EXTI line 15_10 Interrupt to the lowest priority */

  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 1);

  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

But still no change – program loops inside HAL_NVIC_EnableIRQ() as the screenshot shows.

Best regards,

Sebastian

Posted on January 20, 2017 at 17:09

Ok, but the screen shot really shows me nothing useful..

Right now I suspect it is off an an interrupt state, so you'd have to check the vector table and make sure it is binding with 

EXTI15_10_IRQHandler properly. Could you show the code in 

EXTI15_10_IRQHandler?

Put a break point in the Default Handler, EXTI15_10_IRQHandler and have the Hard Fault handler output diagnostic information if it gets there.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on January 20, 2017 at 17:40

I did 'ack EXTI15_10_IRQHandler': and the only reference found is:

Drivers/CMSIS/Device/ST/STM32F7xx/Source/Templates/gcc/startup_stm32f767xx.s

203:  .word     EXTI15_10_IRQHandler              /* External Line[15:10]s        */

428:   .weak      EXTI15_10_IRQHandler

429:   .thumb_set EXTI15_10_IRQHandler,Default_Handler

I had no such function defined – working on verbatim copy of the GPIO_EXTI example (link to source at end of original post). So this explains why Default_Handler was being called.

The code expects this to happen:

void

HAL_GPIO_EXTI_Callback

(

uint16_t

GPIO_Pin

)

{

 

if

(

GPIO_Pin

==

GPIO_PIN_13

)

 

{

   

/* Toggle LED1 */

    BSP_LED_Toggle

(

LED1

)

;

 

}

}

But I think that this to happen, something has to be done to route interrupt not to EXTI15_10_IRQHandler(), but to HAL_GPIO_EXTI_IRQHandler(), because only there HAL_GPIO_EXTI_Callback() is called. Is there such thing? Does the example simply lack EXTI -> GPIO_EXTI binding, or what...?

When I define EXTI15_10_IRQHandler(), and blink LED there, it does blink, although toggling is unstable (sometimes it blinks just for a moment):

void EXTI15_10_IRQHandler(void)

{

    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_13);

    /* Toggle LED1 */

    BSP_LED_Toggle(LED1);

}

Pausing after blink still shows that 'HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);' is the line being in execution.

Best regards,

Sebastian

Posted on January 20, 2017 at 18:36

I found the cause of half of this. The document 'Description of STM32F0xx HAL and Low-layer drivers' says:

When selecting EXTI mode with interrupt generation, the user must call HAL_GPIO_EXTI_IRQHandler() from stm32f0xx_it.c and implement HAL_GPIO_EXTI_Callback()

Turned out that somehow the file stm32f7xx_it.c (I have F7) didn't copy from the Examples directory into my CubeMX–prepared project. There was no EXTI15_10_IRQHandler() function in CubeMX generated file, and no HAL_GPIO_EXTI_IRQHandler() call in it.

Execution is still stuck at 'HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);' line, though (but handlers are called and the LED blinks).

Best regards,

Sebastian

Sebastian Gniazdowski
Associate III
Posted on January 22, 2017 at 17:39

Here is complete source code of the example. It's CubeMX project with files overwritten with those from GPIO_EXTI. Diff on the two projects reveals that everything possible is the same.

https://github.com/psprint/CubeEmpty

S.Ma
Principal
Posted on January 22, 2017 at 19:53

If possible, here would be my checklist: Has the port be selected for the EXTI properly? Exti 10..15 can be pa11, pb12, pc12, etc... Just make sure toggling the led does not trigger an exti by mistake...

Usually regardless of the code, it is very handy to put a breakpoint in the interrupt..

Then when the code stops, look at gpio and exti peripheral registers.

Remember the pending flag is cleared by clearing the right PR bit. Search for the code that does this and breakpoint onto it.

Sebastian Gniazdowski
Associate III
Posted on January 22, 2017 at 20:00

Solution: empty while loop in main() has been optimized away to such extent that the debugger was showing last executed instruction in HAL_NVIC_EnableIRQ(). So it looked like if program was stuck in that call. Adding a volatile variable to the loop revealed that everything is fine.