4
\$\begingroup\$

Issue:

I'm having an impossible time debugging why one of my interrupts isn't working. I'm trying to setup a hardware interrupt on PA3, but as soon as I initialize it, the interrupt triggers and then it never triggers again.

Hardware:

The pin is pulled up (10k) externally and can be shorted to GND via a push button. If I probe the pin, I can see it toggle as I press the button. Further, if I poll the pin using a GPIO_ReadInputDataBit it is toggling correctly as I press the button. All my other interrupts that are configured by the same routine work fine.

Software:

I'm including the code below, but I'm mostly hoping someone can help explain how to debug the interrupt handler. I don't know much about it beyond configuring it which had been working fine until this hiccup. (SWA_Button is the one that's not working, while all the others are fine). Am I missing something really obvious?

*** UPDATE:

I just noticed that it seems PB3 is what is triggering that interrupt. How is the interrupt handler supposed to differentiate between an interrupt on PB3 and PA3?

    #define SWA_BUTTON_PIN                  GPIO_Pin_3
    #define SWA_BUTTON_GPIO_PORT            GPIOA
    #define SWA_BUTTON_GPIO_CLK             RCC_AHBPeriph_GPIOA
    #define SWA_BUTTON_EXTI_LINE            EXTI_Line3
    #define SWA_BUTTON_EXTI_PORT_SOURCE     EXTI_PortSourceGPIOA
    #define SWA_BUTTON_EXTI_PIN_SOURCE      EXTI_PinSource3
    #define SWA_BUTTON_EXTI_IRQn            EXTI2_3_IRQn 


    #define ROTARY_BUTTON_PIN               GPIO_Pin_1
    #define ROTARY_BUTTON_GPIO_PORT         GPIOA
    #define ROTARY_BUTTON_GPIO_CLK          RCC_AHBPeriph_GPIOA
    #define ROTARY_BUTTON_EXTI_LINE         EXTI_Line1
    #define ROTARY_BUTTON_EXTI_PORT_SOURCE  EXTI_PortSourceGPIOA
    #define ROTARY_BUTTON_EXTI_PIN_SOURCE   EXTI_PinSource1
    #define ROTARY_BUTTON_EXTI_IRQn         EXTI0_1_IRQn 

    typedef enum 
    {
      SWA_BUTTON = 0,
      BUTTON_ROTARY = 1,
      ROTARY_A = 2,
      ROTARY_B = 3,
      TX_LOOPBACK = 4,
      SWB_BUTTON = 5
    } Input_TypeDef;

    GPIO_TypeDef* INPUT_PORT[SYS_Num_Inputs] = {
      SWA_BUTTON_GPIO_PORT,         \
      ROTARY_BUTTON_GPIO_PORT,      \
      ROTARY_A_GPIO_PORT,           \
      ROTARY_B_GPIO_PORT,           \
      TX_LOOPBACK_GPIO_PORT,        \
      SWB_BUTTON_GPIO_PORT};

    const uint16_t INPUT_PIN[SYS_Num_Inputs] = {
      SWA_BUTTON_PIN,               \
      ROTARY_BUTTON_PIN,            \
      ROTARY_A_PIN,                 \
      ROTARY_B_PIN,                 \
      TX_LOOPBACK_PIN,              \
      SWB_BUTTON_PIN}; 

    const uint32_t INPUT_CLK[SYS_Num_Inputs] = {
      SWA_BUTTON_GPIO_CLK,          \
      ROTARY_BUTTON_GPIO_CLK,       \
      ROTARY_A_GPIO_CLK,            \
      ROTARY_B_GPIO_CLK,            \
      TX_LOOPBACK_GPIO_CLK,         \
      SWB_BUTTON_GPIO_CLK};

    const uint16_t INPUT_EXTI_LINE[SYS_Num_Inputs] = {
      SWA_BUTTON_EXTI_LINE,         \
      ROTARY_BUTTON_EXTI_LINE,      \
      ROTARY_A_EXTI_LINE,           \
      ROTARY_B_EXTI_LINE,           \
      TX_LOOPBACK_EXTI_LINE,        \
      SWB_BUTTON_EXTI_LINE};

    const uint16_t INPUT_PORT_SOURCE[SYS_Num_Inputs] = {
      SWA_BUTTON_EXTI_PORT_SOURCE,          \
      ROTARY_BUTTON_EXTI_PORT_SOURCE,       \
      ROTARY_A_EXTI_PORT_SOURCE,            \
      ROTARY_B_EXTI_PORT_SOURCE,            \
      TX_LOOPBACK_EXTI_PORT_SOURCE,         \
      SWB_BUTTON_EXTI_PORT_SOURCE};                  

    const uint16_t INPUT_PIN_SOURCE[SYS_Num_Inputs] = {
       SWA_BUTTON_EXTI_PIN_SOURCE,          \
       ROTARY_BUTTON_EXTI_PIN_SOURCE,       \
       ROTARY_A_EXTI_PIN_SOURCE,            \
       ROTARY_B_EXTI_PIN_SOURCE,            \
       TX_LOOPBACK_EXTI_PIN_SOURCE,         \
       SWB_BUTTON_EXTI_PIN_SOURCE}; 

    const uint16_t INPUT_IRQn[SYS_Num_Inputs] = {
      SWA_BUTTON_EXTI_IRQn,         \
      ROTARY_BUTTON_EXTI_IRQn,      \
      ROTARY_A_EXTI_IRQn,           \
      ROTARY_B_EXTI_IRQn,           \
      TX_LOOPBACK_EXTI_IRQn,        \
      SWB_BUTTON_EXTI_IRQn};

    SYS_Input_Init(SWA_BUTTON, INPUT_MODE_EXTI);
    SYS_Input_Init(SWB_BUTTON, INPUT_MODE_EXTI);
    SYS_Input_Init(BUTTON_ROTARY, INPUT_MODE_EXTI);
    SYS_Input_Init(ROTARY_A, INPUT_MODE_EXTI);
    SYS_Input_Init(ROTARY_B, INPUT_MODE_EXTI);
    SYS_Input_Init(TX_LOOPBACK, INPUT_MODE_EXTI);

    void SYS_Input_Init(Input_TypeDef SYS_Input, InputMode_TypeDef Input_Mode)
    {
      GPIO_InitTypeDef GPIO_InitStructure;
      EXTI_InitTypeDef EXTI_InitStructure;
      NVIC_InitTypeDef NVIC_InitStructure;

      /* Enable the SYS_Input Clock */
      RCC_AHBPeriphClockCmd(INPUT_CLK[SYS_Input], ENABLE);
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

      /* Configure SYS_Input pin as input */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_InitStructure.GPIO_Pin = INPUT_PIN[SYS_Input];
      GPIO_Init(INPUT_PORT[SYS_Input], &GPIO_InitStructure);

      if (Input_Mode == INPUT_MODE_EXTI)
      {
        /* Connect SYS_Input EXTI Line to SYS_Input GPIO Pin */
        SYSCFG_EXTILineConfig(INPUT_PORT_SOURCE[SYS_Input], INPUT_PIN_SOURCE[SYS_Input]);

        /* Configure SYS_Input EXTI line */
        EXTI_InitStructure.EXTI_Line = INPUT_EXTI_LINE[SYS_Input];
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        if (SYS_Input == ROTARY_A || SYS_Input == ROTARY_B || SYS_Input == TX_LOOPBACK) 
        {
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
        }
        else
        {
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;    
        }
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);

        /* Enable and set SYS_Input EXTI Interrupt to the lowest priority */
        NVIC_InitStructure.NVIC_IRQChannel = INPUT_IRQn[SYS_Input];
        NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure); 
      }
    }


    void EXTI2_3_IRQHandler(void)
    {
      if(EXTI_GetITStatus(SWA_BUTTON_EXTI_LINE) != RESET)
      {
          swaFlag = 1;
          EXTI_ClearITPendingBit(SWA_BUTTON_EXTI_LINE);
      }
    }

    void EXTI0_1_IRQHandler(void)
    {
      if(EXTI_GetITStatus(ROTARY_BUTTON_EXTI_LINE) != RESET)
      {
        ButtonFlag = 1;
        EXTI_ClearITPendingBit(ROTARY_BUTTON_EXTI_LINE);
      }
    }
\$\endgroup\$
3
\$\begingroup\$

I've found the issue. It turns out it is not possible to trigger off the same pin on multiple GPIO ports. I was overwriting my PA3 interrupt with a PB3 one.

enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for posting your follow-up! You can have up to 16 external interrupts (EXTI0 - EXTI15), but to use all of them you must choose your interrupt pins so that the pin numbers are different: That is, you can have different interrupts triggered by PA1, PA2, and PB3. But you cannot have different interrupts triggered by PA1, PB1, and/or PC1. \$\endgroup\$ – bitsmack Jan 9 '15 at 17:22
  • \$\begingroup\$ Looks more like INTxN must be triggered by PyN \$\endgroup\$ – Scott Seidman Jan 9 '15 at 19:38
  • \$\begingroup\$ Yeah, that's a more concise way of stating it :) \$\endgroup\$ – bitsmack Jan 9 '15 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.