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.