Summary: I've configured a GPIO as an interrupt. I can see from all of the registers that it appears to be triggering, but my interrupt routine is never called.
Details: I'm using a Nucleo F446 board, and the documentation specifies that PC13 should be the input for the push button. I'd like to trigger an interrupt when this happens (I know that this isn't the best way to handle a button; I was having trouble with a more complex system and reduced it to this simplified example). I'm doing this on bare metal and not using any existing libraries.
PC13 comes into EXTI13:
I see that this is interrupt #40 from the microcontroller reference manual:
I'm configuring the microcontroller as follows (using pseudo-c here for simplicity):
Enable clocks for GPIOC block, SYSCFG
RCC_AHB1ENR |= GPIOC_EN RCC_APB2EN |= SYSCFG_EN
Enable external interrupts for GPIO C13 (it is by default an input)
SYSCFG_EXTICR4 |= (PCx << 4)
Set pin 13 of the interrupt mask, event mask, and rising trigger selection registers:
EXTI_IMR |= 1 << 13 EXTI_EMR |= 1 << 13 EXTI_RTSR |= 1 << 13
Enable IRQ 40
NVIC_ISER1 |= 1 << 8
Set up interrupt vector (here is a disassembly)
08000000 <_reset-0x124>: ... 80000e0: 08000621 .word 0x08000621 08000620 <exti15_10_handler>: 8000620: 4906 ldr r1, [pc, #24] ; (800063c <exti15_10_handler+0x1c>)
I have the main code in a loop printing a number of register values, which I will describe in a moment, to the serial port. I've implemented exti15_10_handler to turn on an LED and go into an infinite loop, so I should know when it is called, because it will also stop the printing. When I press and release the button, I see the following:
- In GPIOC_IDR (the GPIO input register), I can see bit 13 change, which tells me the GPIO block is working.
- In EXTI_PR (external interrupt pending), I see the value of bit 13 switch from 0 to 1 and stays there.
- In NVIC_ISPR1 (interrupt set pending), bit 8 (corresponding to interrupt 40) switches from 0 to 1 and stays there.
- However, NVIC_IABR0 (interrupt active bit register) does not change.
- Interrupt is not called, as I see no change in the LED and the board does not hang.
I'm sure I'm forgetting to enable something, but after dredging through the reference manuals and a bunch of code examples, I'm just not seeing it. I did try the following:
asm volatile ("cpsie i" : : : "memory");
To set the interrupt flag (which I think should have been on already). I'm curious if this looks familiar to anyone.