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);
}
}