ARM IRQ处理程序在GCC中无法正常工作

时间:2016-08-06 14:22:10

标签: c gcc arm

我正在使用LPC2138 soc开发一个裸机ARM项目。我为I2C写了一个IRQ中断处理程序。但它没有正确返回。正在为一次中断重复调用处理程序。

我已对此问题进行了详细的调试分析。

在ARM7TDMI参考手册中,它清楚地提到了以下内容。

enter image description here 但是当我反汇编代码时,我发现GCC生成的代码不会恢复CPSR resgister。最后还是一个未知的值。

enter image description here

我已经将IRQ处理程序声明为以下

void I2C0_IRQ_handler(void) __attribute__ ((interrupt("IRQ")));

这是GCC中的错误还是我做错了什么?

我用于构建项目的编译器,汇编器和链接器标志是:

CFLAGS := -mcpu=arm7tdmi-s -g3 -Wall -I. -gdwarf-2
AS_FLAGS := -mcpu=arm7tdmi-s -g3 -gdwarf-2
LD_FLAGS := -Wl,-Map,$(TARGET:%.hex=%).map -nostartfiles

1 个答案:

答案 0 :(得分:4)

你的分析有两个致命的缺陷:首先,你从CPU核心的角度看待它,其次,它是错误的。

第二个缺陷首先,我不确定为什么ARM7TDMI手册有这么奇怪的过于具体的措辞(你无论如何都不能现实地分开所有这些事情),但所有3个方面都由subs pc, lr, #4执行代码中的一行。 subs pc, lr is specifically an exception return instruction - 它以原子方式从SPSR恢复CPSR并返回到固定的LR地址。由于CPU的中断禁用标志位于CPSR中,因此假设该SPSR值中的I位是清楚的(考虑到您使用IRQ到达此处,您可以预期...),IRQ也将自动取消屏蔽在这个过程中。

因此,从CPU核心的角度来看,你的代码已经(凭借其最终指令)完成了异常处理程序所需的一切,即它在同一点恢复执行与IRQ发生时的状态相同 - 编译器肯定没有问题。然而,所做的事情是关于超出核心的外围方式仍在断言其中断这一事实,因此从IRQ返回后你做的下一件事就是愉快地采取同样的IRQ立即再次。无限重复。

就中断控制器而言,你至少已经超越了核心;写入VICVectAddr acknowledges the interrupt at the VIC,但这只会释放VIC本身以优先处理任何挂起的中断并传递下一个中断,因为外部源仍然被断言(假设没有更高优先级的IRQ来了)来自其他地方),仍然是同一个。

要实际处理中断并取得进展,您需要为I2C外设提供服务。 the LPC213x manual的第13.9节概述了每个中断条件需要做的事情,但是在清除断言中断方面,需要写入I2C0CONCLR的SIC字段。