Problema:
Estoy teniendo un tiempo imposible de depurar por qué una de mis interrupciones no funciona. Estoy intentando configurar una interrupción de hardware en PA3, pero tan pronto como la inicializo, la interrupción se dispara y luego nunca se vuelve a activar.
Hardware:
El pin se levanta (10k) externamente y puede cortocircuitarse a GND mediante un botón pulsador. Si pruebo el pin, puedo verlo alternar mientras presiono el botón. Además, si selecciono el pin con un GPIO_ReadInputDataBit, se está activando correctamente cuando presiono el botón. Todas mis otras interrupciones que están configuradas por la misma rutina funcionan bien.
Software:
Incluyo el código a continuación, pero espero que alguien pueda ayudar a explicar cómo depurar el controlador de interrupciones. No sé mucho sobre eso, más allá de configurarlo, que había funcionado bien hasta este problema. (SWA_Button es el que no funciona, mientras que todos los demás están bien). ¿Me estoy perdiendo algo realmente obvio?
*** ACTUALIZACIÓN:
Acabo de notar que parece que PB3 es lo que está activando esa interrupción. ¿Cómo se supone que el controlador de interrupciones debe diferenciar entre una interrupción en PB3 y 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);
}
}