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.

  1. 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_EXTI2 on PA2 pin:

  2. 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:

  3. 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 Overflow
🌐
ST Wiki
wiki.st.com › stm32mcu › wiki › Getting_started_with_EXTI
Getting started with EXTI - stm32mcu - ST wiki
The EXTI (EXTernal Interrupt/Event) controller consists of up to 40 edge detectors for generating event/interrupt requests on STM32L47x/L48x devices. Each input line can be independently configured to select the type (interrupt or event) and ...
🌐
DeepBlue
deepbluembedded.com › home › blog › stm32 external interrupt example lab
STM32 External Interrupt Example LAB – DeepBlue
January 20, 2024 - The ISR that gets called and executed when this interrupt occurs can be found in the stm32f1xx_it.h file, so let’s head over to it now! Point the mouse to the function HAL_GPIO_EXTI_IRQHandler() and right-click its name and then open the declaration for it.
Discussions

c - STM32F3 Discovery - Implement GPIO-Interrupt - Stack Overflow
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_EXTI2 on 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... More on stackoverflow.com
🌐 stackoverflow.com
stm32 - Triggering interrupt on GPIO_Pin_4 (GPIOB) on STM32F042 - Stack Overflow
I am looking for a sample code for triggering an interrupt upon signal changes on GPIO_Pin_4 (GPIOB) on STM32F042. I saw some examples for STMF10x and STMF4x, but nothing for STM32F042. I am not us... More on stackoverflow.com
🌐 stackoverflow.com
Quick question on interrupts on STM32
That's the designed behavior. The STM32 platform assigns a single external interrupt "line" to all its GPIO ports (A, B, C, etc). So you have to design your circuit in such a way that you can disambiguate an external interrupt based on the pin number. This can get really difficult if not impossible with complex circuits and it's one the most frustrating shortcomings of the platform IMO. More on reddit.com
🌐 r/embedded
7
2
September 13, 2022
How to add external GPIO interrupts on STM32? - Electrical Engineering Stack Exchange
I'm trying to configure STM32CubeMx to external GPIO interrupts, however, in the NVIC screen I don't see an EXTI... interrupt to be set. What should I do to be able to e.g. check for interrupts on... More on electronics.stackexchange.com
🌐 electronics.stackexchange.com
🌐
GitHub
github.com › dekuNukem › STM32_tutorials › blob › master › lesson2_external_interrupt › README.md
STM32_tutorials/lesson2_external_interrupt/README.md at master · dekuNukem/STM32_tutorials
The only limitation, at least on STM32F0, is the total number of 16 channels. That means if you're using external interrupt on multiple pins, their pin number has to be different. Here is a simple illustration: ... Still, 16 pins is better than Arduino's measly 2 pins, and more than enough for most situations. We continue working on the project files from the last section, so save a copy if you want. Open up the test.ioc file again and left click on PA3 to switch it to GPIO_EXTI3.
Author   dekuNukem
Top answer
1 of 2
23

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.

  1. 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_EXTI2 on PA2 pin:

  2. 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:

  3. 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.

2 of 2
4

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.

🌐
Microcontrollers Lab
microcontrollerslab.com › home › stm32 nucleo › gpio external interrupts stm32 nucleo with stm32cubeide
GPIO External Interrupts STM32 Nucleo with STM32CubeIDE
December 2, 2025 - This is because Line 5-Line 9 and Line 10-Line 15 have the same interrupt handler. The IRQ has to be set for NVIC and the handler shows the prototype of the handler function. To use this button, we should configure the PA0 pin of GPIOA as a digital input pin. For demonstration purposes, we will control the onboard LED of STM32 Nucleo board with a push button and instead of a polling method, we will use an interrupt method to capture state whenever the state of input changes.
Top answer
1 of 1
1

There are several things you need to do to make GPIO interrupt happen. The peripherals of interest include:

  1. GPIOx - Obviously
  2. EXTI - Handles GPIO interrupts, sets edges, masks pins ("Set rising edge interrupt to EXTI5" - note we set the pin number, but not the port here)
  3. SYSCFG - Assigns GPIO port to pin interrupt (make EXTI5 a GPIOA5 interrupt and not GPIOB5 interrupt)
  4. NVIC - Enable interrupts

GPIO and SYSCFG require clock provided to them from RCC, EXTI doesn't have any clock enable bits in RCC as per reference manual, must be always operational then.

So the sequence of actions seems to be roughly the following:

  1. Enable GPIO port clock, configure the pin (input, pull-up?)
  2. In EXTI, configure edge and pin number (EXTI1 for GPIOx1, EXTI5 for GPIOx5 etc.), unmask the desired pin.
  3. Enable SYSCFG clock, assign GPIO port to the desired EXTIx (note this rules out having interrupts on PA5 and PB5 at the same time)
  4. Configure EXTI interrupt in NVIC.

The logic of GPIO interrupts looks more or less like this:
When the desired edge happens on a GPIO pin, EXTI gets a signal from pin 5 (EXTI5 from GPIOA5 and not from GPIOB5 as per SYSCFG), and if that signal is unmasked, it is sent further into NVIC, which in turn triggers an interrupt.

Note that some EXTIx can share a single NVIC interrupt, so you will have to check within interrupt handler which EXTIx actually triggered it (in the EXTI registers). In case of your MCU, EXTI0 and EXTI1 share one NVIC interrupt, as do EXTI2 and EXTI3, and there is one NVIC interrupt for EXTI4...EXTI15. It's slightly different for every MCU.

P.S. I chose to give a detailed explanation rather than just write the code, because 1) "please bro write me code" is a meh teaching material and because 2) you probably wanted to see the code to understand how it works, so I skipped an extra step. Most things you need to do here are only 2-5 lines each, so I think you should be able to handle it now.

🌐
STMicroelectronics Community
community.st.com › t5 › stm32-mcus-products › how-to-configure-gpio-interrupt-with-cubemx › td-p › 469373
How to configure GPIO Interrupt with CubeMX - STMicroelectronics Community
August 13, 2015 - Click the GPIO pin on the chip view and select the signal GPIO_EXTI. Go to the configuration tab, click the NVIC button and enable the interrupts for EXTI lines. Best regards. ... I am using an STM32F407 (on disco F4 boards). It seems that when you select as suggested, the GPIO configuration ...
Find elsewhere
🌐
Reddit
reddit.com › r/embedded › quick question on interrupts on stm32
r/embedded on Reddit: Quick question on interrupts on STM32
September 13, 2022 -

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
   */
}
🌐
EMCU
emcu.eu › gpios-interrupt
GPIOs interrupt & Atollic | EMCU
The GPIOs has 16 interrupt lines. All pins with same number are connected to line with same number. They are multiplexed to one line. Each line can trigger an interrupt on rising, falling or rising_falling edge on signal. IMPORTANT: You can not use two pins on one line simultaneously.
🌐
Microcontrollers Lab
microcontrollerslab.com › home › stm32 blue pill › stm32 blue pill external interrupts with stm32cube ide and hal libraries
STM32 Blue Pill External Interrupts with STM32Cube IDE - HAL Libraries
December 2, 2025 - The table below shows the different interrupt handlers for the GPIO pins: We have a total of seven interrupt handlers according to the pin which we will set up as the external interrupt pin. This is because Line5-Line9 and Line10-Line15 have the same interrupt handler. The IRQ has to be set for NVIC and the handler shows the prototype of the handler function. Now we will learn how to handle interrupts in the Blue Pill STM32 using a push button to toggle an LED.
🌐
ControllersTech®
controllerstech.com › home › stm32 tutorials › external interrupt using registers
STM32 External Interrupt via Registers | ControllersTech
September 14, 2025 - RCC->AHB1ENR |= 1; // enable clock to PA GPIOA->MODER |= 0;//MODE INPUT FOR PA ... 1. Enable the SYSCFG/AFIO bit in RCC register 2. Configure the EXTI configuration Register in the SYSCFG/AFIO 3. Disable the EXTI Mask using Interrupt Mask Register (IMR) 4. Configure the Rising Edge / Falling Edge Trigger 5.
🌐
STM32F4 Discovery
stm32f4-discovery.net › home › stm32f4 external interrupts tutorial
STM32F4 External interrupts tutorial - STM32F4 Discovery
April 29, 2016 - Each STM32F4 device has 23 external interrupt or event sources. They are split into 2 sections. First interrupt section is for external pins (P0 to P15) on each port, and other section is for other events, like RTC interrupt, Ethernet interrupt, USB interrupt and so on.
🌐
GitHub
github.com › mnemocron › STM32-Tutorial › blob › master › STM32 Tutorial 07 - GPIO Interrupts (EXTI) using HAL (and FreeRTOS).pdf
STM32-Tutorial/STM32 Tutorial 07 - GPIO Interrupts (EXTI) using HAL (and FreeRTOS).pdf at master · mnemocron/STM32-Tutorial
Getting started with the STM32 HAL development environment. Tutorial documents in Markdown. - STM32-Tutorial/STM32 Tutorial 07 - GPIO Interrupts (EXTI) using HAL (and FreeRTOS).pdf at master · mnemocron/STM32-Tutorial
Author   mnemocron
🌐
STMicroelectronics Community
community.st.com › t5 › stm32-mpus-embedded-software-and › resources-for-enabling-interrupts-and-configuring-gpios › td-p › 160705
Resources for enabling interrupts and configuring GPIOs?
April 7, 2021 - Every digital GPIO can be configured as external interrupt (EXTI) source. UM2534 User manual "Discovery kits with STM32MP157 MPUs" pin assignments or you might use STM32CubeMX for interactive pin planning.
🌐
All About Circuits
forum.allaboutcircuits.com › home › forums › embedded & programming › microcontrollers
Why are STM32 GPIO pins, when used as external interrupts, set as NOPULL? | All About Circuits
November 8, 2022 - and this is the pulse routine, until this is entered no interrupts get triggered (unless I do so manually by touching PIN0 to ground). ... static void pulse_led_forever(uint32_t interval) { HAL_DeInit(); HAL_Init(); __GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = { 0 }; GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); while (1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_Delay(interval); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(interval); } }
🌐
Embedded There
embeddedthere.com › stm32-external-interrupt-with-hal-example-code
STM32 External Interrupt with HAL Example Code – Embedded There
November 30, 2023 - The link is given below: How to create stm32 project in stm32cubeide with example code · After creating the project in Stm32CubeIDE, go to the Device Configuration Tool of STM32CubeIDE and configure the pin PC13 [User_Button] as a GPIO interrupt.