Search code examples
embeddedstm32microcontroller

EXTI on GPIOB does not work but on GPIOA everything's ok


I would like to enable EXTI interrupts in order to have information on whether the port has changed its state. As you can see below, I've configured 2 pins, GPIOA5 and GPIOB3. Both have been configured with pullup resistors, so they should change state when they are connected to the ground.

The problem is that everything works for GPIOA5 but doesn't work for GPIOB3. The isr for GPIO5 is being called, but for GPIOB isn't.

I commented part of code regarding UART configuration as it's not relevant in this case - uart works fine, so I can see messages going out from MCU.

What could be a problem here?

I'm using STM32f411CEU6 and libopencm3.

#include <libopencm3/stm32/gpio.h>

#include <libopencm3/stm32/flash.h>
#include <libopencm3/cm3/systick.h>

volatile bool sensor_isr_process { false };
volatile bool sensor_isr_process2 { false };

extern "C" {

void exti3_isr()
{
  sensor_isr_process2 = true;

    exti_reset_request(EXTI3);
}

void exti9_5_isr()
{
  sensor_isr_process = true;

    exti_reset_request(EXTI5);
}
}

void configure_exti(uint32_t nvicirq, uint32_t exti, uint32_t gpioport)
{
  nvic_enable_irq(nvicirq);

  exti_select_source(exti, gpioport);

  exti_set_trigger(exti, EXTI_TRIGGER_FALLING);
  exti_enable_request(exti);
}

int main()
{
  //Setup Clock
  auto clock = rcc_clock_scale{};
  clock.pllm = 8;
  clock.plln = 100; //336;
  clock.pllp = 2; //4;
  clock.pllq = 4; //7;
  clock.pllr = 2; //0;
  clock.pll_source = RCC_CFGR_PLLSRC_HSI_CLK;
  clock.hpre = RCC_CFGR_HPRE_DIV_NONE; //?
  clock.ppre1 = RCC_CFGR_PPRE_DIV_2; // ?
  clock.ppre2 = RCC_CFGR_PPRE_DIV_NONE; // ?
  clock.voltage_scale = PWR_SCALE1; //?
  clock.flash_config = FLASH_ACR_DCEN | FLASH_ACR_ICEN |
      FLASH_ACR_LATENCY_2WS;
  clock.ahb_frequency  = 100000000;
  clock.apb1_frequency = 50000000;
  clock.apb2_frequency = 100000000;

  rcc_clock_setup_pll(&clock);

  //Enable GPIO
  rcc_periph_clock_enable(RCC_GPIOA);
  rcc_periph_clock_enable(RCC_GPIOB);

  //Setup GPIO
  gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO5);
  gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO3);

  configure_exti(NVIC_EXTI9_5_IRQ, EXTI5, GPIOA);
  configure_exti(NVIC_EXTI3_IRQ,   EXTI3, GPIOB);

  while(1)
  {
    if (sensor_isr_process) {
      // trace(1, "Sensor 1\r\n"); //sends message by uart
      sensor_isr_process = false;
    } 
    else if (sensor_isr_process2) {
      // trace(1, "Sensor 2\r\n"); //send message by uart
      sensor_isr_process2 = false;
    }
  }
}

Solution

  • I'm not familiar with libopencm3, but normally EXTI mappings are configured in SYSCFG_EXTICR registers and in order to access them, SYSCFG clock needs to be enabled.

    If you inspect its source file, you can see that exti_select_source() function doesn't enable SYSCFG clock itself. So probably you need to do it yourself by calling the relevant function:

    rcc_periph_clock_enable(RCC_SYSCFG);