真的是醉了,查来查去原来是NXP公司给的中断服务函数框架的问题。
具体来说,我是参考了MCB2300的代码,里面的中断服务函数框架如下所示:
void Timer0Handler (void) __irq
{
T0IR = 1; /* clear interrupt flag */
IENABLE; /* handles nested interrupt */
timer0_counter++;
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
}
问题就是出在IENABLE和IDISABLE这两个宏定义里,其在irq.h中的宏定义如下
static DWORD sysreg; /* used as LR register */
#define IENABLE __asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }
#define IDISABLE __asm { MSR CPSR_c, #(IRQ32Mode|I_Bit); MSR SPSR_cxsf, sysreg }
意思是对程序状态寄存器CPSR和SPSR进行操作使其进入系统模式或IRQ模式,乍一看到没什么问题,可是移植进工程里就出数据中止异常的问题。
下午测试的时候我把定时器中断和串口中断中的IENABLE和IDISABLE语句全部注释掉再进行多次测试,都没有什么问题。
从官方框架的注释上来看这些宏定义是用于解决中断嵌套的,也就是说像我这个工程中有两个中断必然会涉及到嵌套,不过遗憾的是ARM7貌似不太推荐中断嵌套,周立功的《ARM嵌入式系统基础教程》中也提到对于ARM7的中断嵌套配置和操作较为复杂,不推荐使用。其次从代码上来看,估计是每一次进入中断都要对程序状态寄存器进行操作,而频繁的内核模式切换以及程序状态寄存器的强制操作(因为一般这一类最底层的寄存器都是不对用户开放的)导致了数据中止异常。
当然上述只是我的推测而已,不知道是否正确,还请大牛批评指正! |