Reputation: 406
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:
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.
Upvotes: 1
Views: 2056
Reputation: 406
This is a pretty unsatisfying result. While looking at the disassembly of the interrupt vector table, I noticed:
8000000: 20020000 .word 0x20020000
8000004: 08000124 .word 0x08000124
8000008: 08000595 .word 0x08000595
800000c: 08000595 .word 0x08000595
The second entry is supposed to be my reset vector
.section .interrupt_vector
.word _estack // Stack pointer
.word _reset
Although _reset is a thumb function, it is not encoded with the LSB set to indicate that. If I change the line to:
.word _reset + 1
...or put .thumb_func immediate before my reset handler in my startup code, it works correctly every time.
Upvotes: 0