Electronic – STM32F7 gets stuck in external interrupt callback function

gpio-external-interruptinterruptsmicrocontrollerstm32stm32f7

i am working on a project to connect a camera to an STM32F7 Discovery board using the DCMI interface.
The camera part works fine, but i have a strange problem with external interrupts from the onboard push button.

I enable external interrupts for the button using the function provided in the STM BSP package:

BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);

The external interrupt for this button is now on GPIO_PIN_11.
This interrupt is handled by the HAL_GPIO_EXTI_Callback function which i can implement in my main.c file.

I am using STM HAL/BSP libraries.

The interrupt on a button press works and the callback function is entered correctly, but here is where the problem begins.

Here is what i want to do on a button press:

{
        if(capture_status == 0)
        {
            start_capture_continuous((uint8_t*)CAMERA_FRAME_BUFFER);//start continuous grabbing, if not already running
            if(suspended == 1)
            {
                Camera_Resume();//resume DCMI and DMA if necessary and wakeup sensor from standby
            }
        }
        else
        {
            Camera_status = stop_capture();//stop if already running and update the status
            Camera_Suspend();//halt DCMI and DMA and put sensor in standby mode
        }
    HAL_Delay(50);
}

Explanation of this code:

This code is for toggling the camera live preview on the LCD.

start_capture_continuous((uint8_t*)CAMERA_FRAME_BUFFER);

This function starts continuous grabbing of frames from the camera and updates the frame buffer. It basically references the HAL_DCMI_Start_DMA function.

stop_capture();

This function stops the DMA transfer.

Camera_Suspend and Camera_Resume disable/enable the DCMI interface and send standby/wakeup commands to my camera sensor via I2C.

So here is where the problem starts:

If i put this code in the callback function, the MCU gets stuck somewhere in this function. Just a reset can get me back to normal state.

Somewhere on the internet I read that this issue could be I2C related, but even if I delete the I2C parts in the callback function the behaviour is not as intended:
Sometimes it works for about three times or it gets stuck immediately again.
I believe the problem is in the HAL_DCMI_Start_DMA function, but i am not sure.

Are there any common mistakes which lead to a problem like this?

I hope is has become clear what my problem is and someone can give me some hints to solve it.

btw: If i use the button in polling mode in the main infinite loop and do exact the same things on a button press everything works well.

To clarify my interrupt routines:

Main interrupt Handler:

void EXTI15_10_IRQHandler(void)
{
//if button pressed
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_11) != RESET)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
}
//if touchscreen interrupt
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_13) != RESET)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
}

calls:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}

calls after resetting IT flag:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
sprintf((char*)text, "EXTI pin: %d", GPIO_Pin);
BSP_LCD_DisplayStringAt(5, LINE(8), (uint8_t*)text, LEFT_MODE);
//if button pressed -> toggle preview
if(GPIO_Pin == GPIO_PIN_11)
{
    BSP_LED_Toggle(LED1);
}
//ts interrupt
if(GPIO_Pin == GPIO_PIN_13)
{

}
}

This works flawlessly, but if I replace BSP_LED_Toggle(LED1); with the code above, the function gets stuck.

Update:
I found the mistake. The SysTick interrupt priority was set to the lowest (15), so calling HAL_Delay() from an ISR with the same or higher priority caused an infinite loop in the HAL_Delay function.

So, take care: If you are using the default HAL settings provided by ST, the priority for SysTick IRQ is set to 15 when calling HAL_Init(). You have to change that in the stm32f7xx_hal_conf.h file or by using the HAL_InitTick(TickPriority) function.

Here is what the HAL documentation of HAL_InitTick says about that issue:

Care must be taken if HAL_Delay() is called from a peripheral ISR
process, The the SysTick interrupt must have higher priority
(numerically lower) than the peripheral interrupt. Otherwise the
caller ISR process will be blocked. The function is declared as __weak
to be overwritten in case of other implementation in user file.

Best Answer

Update: I found the mistake. The SysTick interrupt priority was set to the lowest (15), so calling HAL_Delay() from an ISR with the same or higher priority caused an infinite loop in the HAL_Delay function.

So, take care: If you are using the default HAL settings provided by ST, the priority for SysTick IRQ is set to 15 when calling HAL_Init(). You have to change that in the stm32f7xx_hal_conf.h file or by using the HAL_InitTick(TickPriority) function.

Here is what the HAL documentation of HAL_InitTick says about that issue:

Care must be taken if HAL_Delay() is called from a peripheral ISR process, The the SysTick interrupt must have higher priority (numerically lower) than the peripheral interrupt. Otherwise the caller ISR process will be blocked. The function is declared as __weak to be overwritten in case of other implementation in user file.