Interrupt issues with the STM32F411VE with Arduino Framework

I have developed a custom board using an STM32F411VET6, and I am having issues with getting everything working properly on the board. I found a similar board, and modified it. It works, but there are two issues. One is just minor, but one is a show stopper.

The minor issue is that all pins >PB_11 are off by one. I can deal with that. A more major issue for me is that I am having major issues with with interrupts on pin state change. Essentially, I want to have interrupts on state change of 16 pins.

If I use the following code, it works… It is operating on PE_1.

    stm32_interrupt_enable((GPIO_TypeDef *)GPIOE_BASE, GPIO_PIN_1, pinStateChanged_A0, GPIO_MODE_IT_RISING_FALLING);

If I then use the following code, the previous interrupt stops working, and this newer one works.

stm32_interrupt_enable((GPIO_TypeDef *)GPIOD_BASE, GPIO_PIN_1, pinStateChanged_C1, GPIO_MODE_IT_RISING_FALLING);

Here is the relevant part of my platformio.ini file

platform = ststm32
board = generic
framework = arduino
platform_packages = toolchain-gccarmnoneeabi@1.90201.191206

This points to the following generic.json file

	"build": {
	  "core": "stm32",
	  "cpu": "cortex-m4",
	  "extra_flags": "-DSTM32F411xE -DSTM32F4xx -DARDUINO_GENERIC_F411VETX ",
	  "f_cpu": "100000000L",
	  "mcu": "stm32f411vet6",
	  "product_line": "STM32F411xE",
	  "variant": "STM32F4xx/F411V(C-E)T"
	"debug": {
	  "jlink_device": "STM32F411VE",
	  "openocd_target": "stm32f4x",
	  "svd_path": "STM32F411xx.svd"
	"frameworks": [
	"name": "STM32F411VE (128k RAM. 512k Flash)",
	"upload": {
	  "maximum_ram_size": 131072,
	  "maximum_size": 524288,
	  "protocol": "stlink",
	  "protocols": [
	"url": "",
	"vendor": "Generic"

To get this to work, I needed to generate a ldscript.ld using STM32Cube and place it in .platformio/packages/framework-arduinoststm32/variants/STM32F4xx/F411V(C-E)T. Like I noted, the only issues I am seeing are with pin numbering and interrupts.

EDIT: If I use something like attachInterrupt(digitalPinToInterrupt(reader[2].in_D1), pinStateChanged_C1, CHANGE); I am still getting exactly the same issue. From further reading, there are a limited number of hardware interrupts; and it appears that all the 0 pins (PA_0, PB_0, …) should share the same interrupt. So should all the 1 pins (PA_1, PB_2, …) and so forth. It further appears that the software architecture should be rather smart, and then forward the hardware interrupts on. I have no idea why the latest attachInterrupt for a pin set is the only one that is working.

Any assistance would be appreciated. Thanks.

Exactly. On STM32, one EXTI hardware block, e.g., EXTI0, manages all the pins PA0, PB0, PC0, PD0, PE0, et cetera. There should be EXTI0 to EXTI15 available in hardware. See

Thanks so much for that. It just confirmed what I was seeing, and I couldn’t quite get my head around the software architecture being not having implemented something so visible. A chip limitation makes sense. I guess I will be doing a new prototype. I have other mods to make anyway.

Checking the reference manual does indeed mention that in the EXTI section. The important part is the diagram ‘External interrupt/event GPIO mapping’ (Figure 30), which has only four bits coming from the SYSCFG_EXTICRx register despite there being more than four pins to select from. Looking further, section 7.2.3 shows how SYSCFG_EXTICR1 is configured.

My confusion was that the datasheet suggested that ’ Up to 81 GPIOs can be connected to the 16 external interrupt lines.'. It just didn’t say that they could be connected simultaneously.