The PC13 EXTI interrupt (EXTI15_10) configured here keeps firing none stop. Most other questions about this same topic indicate that the respective EXTI_PR pending bit needs to be cleared in the ISR. I am clearing the bit in my code.
The nucleo-103rb board connects GPIO PC13 to a user button that I am using to toogle the timer interrupt that blinks the LED between 1 second and .5 second. The board has a debouncer capacitor/resistor, so I don't think a dirty signal is the issue. Even without touching the button, the ISR keeps firing.
Also, in my gdb debug session, if I turn off the edge trigger set *EXTI_FTSR = (unsigned int)0x00000000
, the board exits the ISR and settles in the while(1)
loop, LED blinking and all. Then, in the debug session, I set an EXTI software pend set *0x40010410 = 0x00002000
, then after continuing, the EXTI ISR changes the LED speed and exits back to while(1) without issue.
I can't figuire out why the EXTI ISR keep firing non-stop.
The code:
#define _stackInit 0x20005000U
// RCC base 0x40021000
volatile unsigned int * const RCC_APB2ENR = (unsigned int *)0x40021018; // offset 0x18 APB2ENR
volatile unsigned int * const RCC_APB1ENR = (unsigned int *)0x4002101c; // offset 0x1c APB1ENR
// GPIOA base 0x40010800
volatile unsigned int * const GPIOA_CRL = (unsigned int *)0x40010800; // offset 0x00 CRL
volatile unsigned int * const GPIOA_ODR = (unsigned int *)0x4001080c; // offset 0x0c ODR
// GPIOC base 0x40011000
volatile unsigned int * const GPIOC_CRL = (unsigned int *)0x40011000; // offset 0x00 CRL
volatile unsigned int * const GPIOC_CRH = (unsigned int *)0x40011004; // offset 0x04 CRH
volatile unsigned int * const GPIOC_IDR = (unsigned int *)0x40011008; // offset 0x08 IDR
volatile unsigned int * const GPIOC_ODR = (unsigned int *)0x4001100c; // offset 0x0c ODR
// TIM2 base 0x40000000
volatile unsigned int * const TIM2_CR1 = (unsigned int *)0x40000000; // offset 0x00 CR1
volatile unsigned int * const TIM2_PSC = (unsigned int *)0x40000028; // offset 0x28 PSC
volatile unsigned int * const TIM2_DIER = (unsigned int *)0x4000000c; // offset 0x0c DIER
volatile unsigned int * const TIM2_ARR = (unsigned int *)0x4000002c; // offset 0x2c ARR
volatile unsigned int * const TIM2_SC = (unsigned int *)0x40000010; // offset 0x10 SC
// NVIC base 0xE000E100
volatile unsigned int * const NVIC_ISER0 = (unsigned int *)0xE000E100; // offset 0x00 ISER0
volatile unsigned int * const NVIC_ISER1 = (unsigned int *)0xE000E104; // offset 0x04 ISER1
// EXIT base 0x40010400
volatile unsigned int * const EXTI_IMR = (unsigned int *)0x40010400; // offset 0x00 IMR
volatile unsigned int * const EXTI_FTSR = (unsigned int *)0x4001040c; // offset 0x0c FTSR
volatile unsigned int * const EXTI_PR = (unsigned int *)0x40010414; // offset 0x14 PR
int c_entry()
{
// enable GPIOA clock and set PB5 to output
*RCC_APB2ENR |= (unsigned int)0x00000004;
*GPIOA_CRL = (unsigned int)0x44244444;
// enable GPIOC clock and set PC13 to input with pull up
*RCC_APB2ENR |= (unsigned int)0x00000010;
*GPIOC_CRH = (unsigned int)0x44844444;
// enable EXTI on PC13
*EXTI_IMR |= (unsigned int)0x00002000;
*EXTI_FTSR |= (unsigned int)0x00002000;
// enable TIM2 clock and configure the timer interrupt
*RCC_APB1ENR |= (unsigned int)0x00000001;
*TIM2_PSC = (unsigned short)0x00ff;
*TIM2_ARR = (unsigned short)31250u;
*TIM2_DIER = (unsigned short)0x0001;
*TIM2_CR1 = (unsigned short)0x0001;
// enable TIM2 global interrupt in NVIC
*NVIC_ISER0 |= (unsigned int)(0x01<<0x1c); //0x1c, TIM2 global interrupt position 28
// enable TIM2 global interrupt in NVIC
*NVIC_ISER1 |= (unsigned int)(0x01<<0x08); //0x08, EXTI_15_10 interrupt position 40
while(1);
//return 0;
}
void TIM2_IRQHandler()
{
//toggle PA5
*GPIOA_ODR ^= 0x20u;
// clear TIM2 int pending bit
*TIM2_SC &= ~(unsigned short)0x0001;
}
void EXTI15_10_IRQHandler()
{
if (*TIM2_ARR == (unsigned short)31250u){
*TIM2_ARR = (unsigned short)15625u;
} else {
*TIM2_ARR = (unsigned short)31250u;
}
*EXTI_PR = (unsigned int)0x00002000;
}
// Begin and End addresses for the .bss section; symbols defined in linker script
extern unsigned int __bss_start__;
extern unsigned int __bss_end__;
void __attribute__ ((section(".after_vectors"))) Reset_Handler (void)
{
// Initialize bss section by iterating and clearing word by word.
// It is assumed that the pointers are word aligned.
unsigned int *p = &__bss_start__;
while (p < &__bss_end__) {
*p++ = 0;
}
c_entry();
}
void __attribute__ ((section(".after_vectors"))) Default_Handler(void)
{
while(1);
}
// cortex-m core exceptions
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) NMI_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) HardFault_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) MemManage_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) BusFault_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) UsageFault_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SVC_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DebugMon_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) PendSV_Handler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SysTick_Handler(void);
// chip level interrupts
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) WWDG_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) PVD_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TAMPER_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) RTC_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) FLASH_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) RCC_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI0_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI4_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel4_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel5_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel6_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA1_Channel7_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) ADC1_2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USB_HP_CAN1_TX_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USB_LP_CAN1_RX0_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) CAN1_RX1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) CAN1_SCE_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI9_5_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM1_BRK_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM1_UP_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM1_TRG_COM_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM1_CC_IRQHandler(void);
//void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM4_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) I2C1_EV_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) I2C1_ER_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) I2C2_EV_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) I2C2_ER_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SPI1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SPI2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USART1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USART2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USART3_IRQHandler(void);
//void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) EXTI15_10_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) RTCAlarm_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) USBWakeUp_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM8_BRK_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM8_UP_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM8_TRG_COM_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM_CC_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) ADC3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) FSMC_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SDIO_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM5_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) SPI3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) UART4_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) UART5_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM6_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) TIM7_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA2_Channel1_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA2_Channel2_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA2_Channel3_IRQHandler(void);
void __attribute__ ((section(".after_vectors"),weak, alias ("Default_Handler"))) DMA2_Channel4_5_IRQHandler(void);
typedef void(* const pHandler)(void);
// The vector table.
// The linker script to place at correct location in memory.
__attribute__ ((section(".isr_vector"),used)) pHandler __isr_vectors[] =
{
//core exceptions
(pHandler)_stackInit, // Inital Stack Pointer
Reset_Handler, // reset handler
NMI_Handler, // NMI handler
HardFault_Handler, // hard fault handler
MemManage_Handler, // MPU fault handler
BusFault_Handler, // bus fault handler
UsageFault_Handler, // usage fault handler
0x00, // reserved
0x00, // reserved
0x00, // reserved
0x00, // reserved
SVC_Handler, // SVCall handler
DebugMon_Handler, // debug monitor handler
0x00, // reserved
PendSV_Handler, // PendSV handler
SysTick_Handler, // systick handler
// chip level interrupts
WWDG_IRQHandler, /* Window Watachdog */
PVD_IRQHandler, /* PVD EXTI Line Detect */
TAMPER_IRQHandler, /* Tamper */
RTC_IRQHandler, /* RTC Global */
FLASH_IRQHandler, /* Flash Global */
RCC_IRQHandler, /* RCC Global */
EXTI0_IRQHandler, /* EXTI Line 0 */
EXTI1_IRQHandler, /* EXTI Line 1 */
EXTI2_IRQHandler, /* EXTI Line 2 */
EXTI3_IRQHandler, /* EXTI Line 3 */
EXTI4_IRQHandler, /* EXTI Line 4 */
DMA1_Channel1_IRQHandler, /* DMA1 Channel1 Global */
DMA1_Channel2_IRQHandler, /* DMA1 Channel2 Global */
DMA1_Channel3_IRQHandler, /* DMA1 Channel3 Global */
DMA1_Channel4_IRQHandler, /* DMA1 Channel4 Global */
DMA1_Channel5_IRQHandler, /* DMA1 Channel5 Global */
DMA1_Channel6_IRQHandler, /* DMA1 Channel6 Global */
DMA1_Channel7_IRQHandler, /* DMA1 Channel7 Global */
ADC1_2_IRQHandler, /* ADC1 and ADC2 Global */
USB_HP_CAN1_TX_IRQHandler, /* USB High Priority or CAN TX */
USB_LP_CAN1_RX0_IRQHandler, /* USB Low Priority or CAN RX0 */
CAN1_RX1_IRQHandler, /* CAN RX1 */
CAN1_SCE_IRQHandler, /* CAN SCE */
EXTI9_5_IRQHandler, /* EXTI Line[9:5] */
TIM1_BRK_IRQHandler, /* TIM1 Break */
TIM1_UP_IRQHandler, /* TIM1 Update */
TIM1_TRG_COM_IRQHandler, /* TIM1 Trigger and Commutation */
TIM1_CC_IRQHandler, /* TIM1 Capture Compare */
TIM2_IRQHandler, /* TIM2 Global */
TIM3_IRQHandler, /* TIM3 Global */
TIM4_IRQHandler, /* TIM4 Global */
I2C1_EV_IRQHandler, /* I2C1 Event */
I2C1_ER_IRQHandler, /* I2C1 Error */
I2C2_EV_IRQHandler, /* I2C2 Event */
I2C2_ER_IRQHandler, /* I2C2 Error */
SPI1_IRQHandler, /* SPI1 Global */
SPI2_IRQHandler, /* SPI2 Global */
USART1_IRQHandler, /* USART1 Global */
USART2_IRQHandler, /* USART2 Global */
USART3_IRQHandler, /* USART3 Global */
EXTI15_10_IRQHandler, /* EXTI Line[15:10] */
RTCAlarm_IRQHandler, /* RTC Alarm EXTI Line */
USBWakeUp_IRQHandler, /* USB WakeUp EXTI Line */
TIM8_BRK_IRQHandler, /* TIM8 Break */
TIM8_UP_IRQHandler, /* TIM8 Update */
TIM8_TRG_COM_IRQHandler, /* TIM8 Trigger and Commutation */
TIM_CC_IRQHandler, /* TIM8 Capture Compare */
ADC3_IRQHandler, /* ADC3 Global */
FSMC_IRQHandler, /* FSMC Global */
SDIO_IRQHandler, /* SDIO Global */
TIM5_IRQHandler, /* TIM5 Global */
SPI3_IRQHandler, /* SPI3 Global */
UART4_IRQHandler, /* UART4 Global */
UART5_IRQHandler, /* UART5 Global */
TIM6_IRQHandler, /* TIM6 Global */
TIM7_IRQHandler, /* TIM7 Global */
DMA2_Channel1_IRQHandler, /* DMA2 Channel1 global */
DMA2_Channel2_IRQHandler, /* DMA2 Channel2 global */
DMA2_Channel3_IRQHandler, /* DMA2 Channel3 global */
};
The linker script:
NTRY(Reset_Handler)
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}
SECTIONS
{
.text :
{
*(.isr_vector)
*(.after_vectors)
*(.text)
} > FLASH
.bss :
{
__bss_start__ = .; /* symbol for c code to initialize bss section */
*(.bss)
*(COMMON)
__bss_end__ = .; /* symbol for c code to initialize bss section */
} > RAM
}
It is built with:
/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb -g main.c -o main.o
/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/arm-none-eabi-ld -T main.ld -Map main.map --cref main.o -o main.elf
I condensed all the code into one file for ease of posting as a question.