问题描述
我正在尝试使用下降沿EXTI中断简单地通过按钮打开LED。不幸的是,LED闪烁而不触摸按钮,使用gdb进行调试还显示,ISR被反复调用。 在我之前测试过LED(PA5)和按钮(PC13:带上拉电阻的输入模式)时,它们的配置是正确的。
所以我认为EXTI中断配置一定有问题。
@ 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,#EXTI_IMR]
tst r1,#1
ittt ne
ldrne r3,#EXTI_RTSR]
orrne r3,r4
strne r3,#EXTI_RTSR]
tst r1,#2
ittt ne
ldrne r3,#EXTI_FTSR]
orrne r3,#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,#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上配置中断
我不太确定为什么中断无法正常运行,我错过了设置它的步骤吗?
编辑:我只是注意到有些奇怪,仅当与gdb连接(通过openocd)时,LED才发生闪烁,但是如果我只是闪烁.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
解决方法
PC13:带上拉电阻的输入模式
不要使用内部上拉,这些(通常)电阻太高。使用 1k-10k 范围内的外部上拉。