I'm trying to simply turn of an LED with a Button, using a falling edge EXTI Interrupt. Unfortunately, the LED is blinking without touching the button, debugging with gdb also shows, that the ISR is called repeatedly. As I tested the LED (PA5) and the Button (PC13: Input mode with pull-up resistor) before, their configuration is correct.
So I think there must be something wrong with the EXTI Interrupt configuration.
The configuration is done in assembly before calling main
with the following function:
@ r0 = EXTI-line (0 .. 15)
@ r1 = Trigger Seleetion, LSBs (... : b1 : b0),
@ b0 = 1 -> Rising Trigger enabled,
@ b1 = 1 -> Falling Trigger enabled
.global ConfigureEXTI
.type ConfigureEXTI, %function
ConfigureEXTI:
push { r4, lr }
@ register value for bit $r0 in r4
mov r4, #1
lsl r4, r0
ldr r2, =EXTI
ldr r3, [r2, #EXTI_IMR]
orr r3, r4
str r3, [r2, #EXTI_IMR]
tst r1, #1
ittt ne
ldrne r3, [r2, #EXTI_RTSR]
orrne r3, r4
strne r3, [r2, #EXTI_RTSR]
tst r1, #2
ittt ne
ldrne r3, [r2, #EXTI_FTSR]
orrne r3, r4
strne r3, [r2, #EXTI_FTSR]
@ First 4 EXTI lines with own ISR
cmp r0, #4
bhi 1f
add r0, #6
b 2f
1:
cmp r0, #9
ite ls
movls r0, #23 @ combined ISR for EXTI 5-9 (23) and EXTI 10-15 (40)
movhi r0, #40
2:
bl EnableIRQ
pop { r4, pc }
.ltorg
EnableIRQ
enables the Interrupt in the NVIC_ISER1 register, using the following code:
@ r0 = IRQ Number
.global EnableIRQ
.type EnableIRQ, %function
EnableIRQ:
ldr r1, =NVIC_ISER0
movs r2, #1
and r3, r0, #0x1f @ r3 <- r0 mod 32
lsls r2, r2, r3
@ calculating n = r0/32 to choose register NVIC_ISERn
lsrs r3, r0, #5
lsls r3, r3, #2
str r2, [r1, r3]
bx lr
.ltorg
ConfigureEXTI
is called from the Reset_Handler
:
Reset_Handler:
@ ...
mov r0, #13
mov r1, #2
bl ConfigureEXTI
b main
main
contains simply an endless loop while(1) __WFI();
The ISR is implemented in C:
void EXTI15_10_IRQHandler(void)
{
if((EXTI->PR & (1 << BUTTON_PIN)))
{
GPIOA->ODR ^= (1 << LED_PIN);
EXTI->PR |= (1 << BUTTON_PIN);
}
}
So I'm doing the steps I extracted out the reference manual:
- Programming trigger registers EXTI_RTSR and EXTI_FTSR
- Enabling the Interrupt request in EXTI_IMR
- Configuring the Interrupt at the NVIC
I'm not really sure why the Interrupt isn't working properly, is there maybe a step in setting it up, that I missed?
Edit: I just noticed something weird, the blinking of the LED only happens when connecting with gdb (over openocd), but if I just flash the .elf, the led doesn't blink (the button doesn't work nevertheless). commands used for flashing/debugging:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program
main.elf verify reset exit"
or debug
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
$ arm-none-eabi-gdb main.elf
(gdb) target remote :3333