我正在尝试使用下降沿 EXTI 中断简单地打开带有按钮的 LED。不幸的是,LED 在没有触摸按钮的情况下闪烁,使用 gdb 进行调试也显示 ISR 被重复调用。我之前测试过 LED (PA5) 和 Button(PC13:带上拉电阻的输入模式),它们的配置是正确的。
所以我认为EXTI中断配置肯定有问题。
main
在使用以下函数调用之前,配置是在汇编中完成的:
@ 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
使用以下代码启用 NVIC_ISER1 寄存器中的中断:
@ 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
从以下位置调用Reset_Handler
:
Reset_Handler:
@ ...
mov r0, #13
mov r1, #2
bl ConfigureEXTI
b main
main
只包含一个无限循环while(1) __WFI();
ISR 在 C 中实现:
void EXTI15_10_IRQHandler(void)
{
if((EXTI->PR & (1 << BUTTON_PIN)))
{
GPIOA->ODR ^= (1 << LED_PIN);
EXTI->PR |= (1 << BUTTON_PIN);
}
}
所以我正在执行我提取参考手册的步骤:
- 编程触发寄存器 EXTI_RTSR 和 EXTI_FTSR
- 在 EXTI_IMR 中启用中断请求
- 在 NVIC 上配置中断
我不太确定为什么中断不能正常工作,是否有设置它的步骤,我错过了?
编辑:我刚刚注意到一些奇怪的事情,LED 的闪烁仅在与 gdb 连接(通过 openocd)时发生,但如果我只是闪烁 .elf,则 LED 不会闪烁(但按钮不起作用)。用于闪烁/调试的命令:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program
main.elf verify reset exit"
或调试
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
$ arm-none-eabi-gdb main.elf
(gdb) target remote :3333