Since @Mouin has described the steps for you and you are using HAL already, here is how to execute those steps, so the way to configure it by using STM32CubeMX software provided by ST Microelectronics. (Note: Browsing that link is recommended as there are many-many examples for the STM32 family, STM32CubeF3 package for example.)
So in brief download it, create a new project for an STM32F3 Discovery board.
On the Pinout tab, the MCU will be shown with all its pins. Just click on a pin and select a functionality you want. In your case
GPIO_EXTI2on PA2 pin:
Now switch to do Configuration tab, and in the last column called System, click on the GPIO button. Available options can be seen on the image below:

Next step is to enable the corresponding interrupt. To do so close the Pin Configuration window and from the System column, click on the NVIC button. If you remember, the EXTI2 has been chosen on PA2 so tick the Enable checkbox for EXTI line2. You can set the priorities here as well.

Everything is ready, click on the Generate source code based on user settigns button →
. Following source files will be genereted:

GPIO configuration in gpio.c:
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOA_CLK_ENABLE();
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
/*Configure GPIO pin : PA2 */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_TSC_IRQn, 0, 0); // <--- This and
HAL_NVIC_EnableIRQ(EXTI2_TSC_IRQn); // <--- this are what were missing for you.
Interrupt service rutine in the stm32f3xx_it.c:
/**
* @brief This function handles EXTI line2 and Touch Sense controller.
*/
void EXTI2_TSC_IRQHandler(void)
{
/* USER CODE BEGIN EXTI2_TSC_IRQn 0 */
/* USER CODE END EXTI2_TSC_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
/* USER CODE BEGIN EXTI2_TSC_IRQn 1 */
/* USER CODE END EXTI2_TSC_IRQn 1 */
}
This is what will be called when an interrupt is triggered, it will call an IRQ handler for the GPIO2 and if everything is fine, the following callback will be called. You have to write your handler code here.
/**
* @brief Interrupt callback for GPIOs
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if ( GPIO_Pin == GPIO_PIN_2)
{
// Write your code here
}
}
You have to add the previous part manually (the callback), it has a weak declaration only but won't be generated. You can place it in the stm32f3xx_it.c .
If you want to learn more about the MCU, open up the reference manual and read the GPIO and NVIC section to know how it is done on register level.
Answer from Bence Kaulics on Stack Overflowc - STM32F3 Discovery - Implement GPIO-Interrupt - Stack Overflow
stm32 - Triggering interrupt on GPIO_Pin_4 (GPIOB) on STM32F042 - Stack Overflow
Quick question on interrupts on STM32
How to add external GPIO interrupts on STM32? - Electrical Engineering Stack Exchange
Videos
Since @Mouin has described the steps for you and you are using HAL already, here is how to execute those steps, so the way to configure it by using STM32CubeMX software provided by ST Microelectronics. (Note: Browsing that link is recommended as there are many-many examples for the STM32 family, STM32CubeF3 package for example.)
So in brief download it, create a new project for an STM32F3 Discovery board.
On the Pinout tab, the MCU will be shown with all its pins. Just click on a pin and select a functionality you want. In your case
GPIO_EXTI2on PA2 pin:
Now switch to do Configuration tab, and in the last column called System, click on the GPIO button. Available options can be seen on the image below:

Next step is to enable the corresponding interrupt. To do so close the Pin Configuration window and from the System column, click on the NVIC button. If you remember, the EXTI2 has been chosen on PA2 so tick the Enable checkbox for EXTI line2. You can set the priorities here as well.

Everything is ready, click on the Generate source code based on user settigns button →
. Following source files will be genereted:

GPIO configuration in gpio.c:
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOA_CLK_ENABLE();
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
/*Configure GPIO pin : PA2 */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_TSC_IRQn, 0, 0); // <--- This and
HAL_NVIC_EnableIRQ(EXTI2_TSC_IRQn); // <--- this are what were missing for you.
Interrupt service rutine in the stm32f3xx_it.c:
/**
* @brief This function handles EXTI line2 and Touch Sense controller.
*/
void EXTI2_TSC_IRQHandler(void)
{
/* USER CODE BEGIN EXTI2_TSC_IRQn 0 */
/* USER CODE END EXTI2_TSC_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
/* USER CODE BEGIN EXTI2_TSC_IRQn 1 */
/* USER CODE END EXTI2_TSC_IRQn 1 */
}
This is what will be called when an interrupt is triggered, it will call an IRQ handler for the GPIO2 and if everything is fine, the following callback will be called. You have to write your handler code here.
/**
* @brief Interrupt callback for GPIOs
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if ( GPIO_Pin == GPIO_PIN_2)
{
// Write your code here
}
}
You have to add the previous part manually (the callback), it has a weak declaration only but won't be generated. You can place it in the stm32f3xx_it.c .
If you want to learn more about the MCU, open up the reference manual and read the GPIO and NVIC section to know how it is done on register level.
Typically when talking about interrupts there is 2 main things to configure :
CPU +------+ Interrupt Vector (NVIC) +--------+ Peripheral
On the peripheral side : you have to configure which kind of event you 're wating: for example a rising edge on a GPIO, timer ticks...besides you have to tell your peripheral to notify the NVIC once this event happen
On Interrupt vector side: CPU will get notified by the mean of the interrupt vector, so here, basically, you have to configure the priority of your interrupt and the ISR to execute.
If you do this correctly the CPU will execute the ISR once the interrupt happens.
In your code there is no configuration for the NVIC, also you forget the link between the NVIC and the GPIO. I hope i give you some help, you can search the in the internet for concise code.
The tutorial I'm going through did this in the exti callback function:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == Blue_Btn_Pin)
{
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
}
}Where he said if(GPIO_Pin == Blue_Btn_Pin).
Does this mean that this HAL_GPIO_EXTI_Callback function is shared amongst all external interrupts? I originally thought this callback function would only be for external interrupt 0, which is what my blue button is connected to. But now I'm wondering if this function is shared amongst all the external interrupts? If not, why would you need to check that the GPIO_Pin is equal to the Blue_Btn_Pin?
Here is some more code that comes before the above function.
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
/**
* @brief EXTI line detection callback.
* @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
* @retval None
*/
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
