该问题以解决,在此结一下题。下面讲一下我的解决思路和方法。 先说问题出在哪儿。我是采用了NXP官方MCB2300开发例程给的中断服务程序框架,如下图所示。 ![]() 原因出在IENABLE和IDISABLE这两个语句上,将所有中断服务程序中的这两个语句注释掉之后,多次测试再无异常和死机。 下面讲一下我个人觉得的原因。 首先IENABLE和IDISABLE是一个宏定义,其具体定义在irq.h中,如下图所示 ![]() 仔细看可以发现它们是对程序状态寄存器CPSR和SPSR进行操作,使内核进入系统模式或者是IRQ中断模式,乍一看貌似没什么问题,而且官方代码的注释也说这两个语句主要是为了解决中断嵌套用的。不过不知道是因为我没有配置完全还是怎么的,在本工程中确实会出现中断嵌套的问题,估计没有很好的处理中断嵌套,从而出现了数据中止异常吧。 可是回过头来想想如果是因为中断嵌套的配置没有做好,那为什么直接去掉这两个语句,换言之就是为什么直接放弃中断嵌套的配置,反而程序运行流畅不会异常和死机了呢? 个人觉得吧可能原因还是出在对程序状态寄存器的频繁操作和对内核模式的频繁切换所导致的问题,不过具体的原因因为个人所学有限目前还不能给予更加有效的正确的解释。 上述如果有谬误和纰漏的地方,还望大牛们批评指正。 |
真的是醉了,查来查去原来是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的中断嵌套配置和操作较为复杂,不推荐使用。其次从代码上来看,估计是每一次进入中断都要对程序状态寄存器进行操作,而频繁的内核模式切换以及程序状态寄存器的强制操作(因为一般这一类最底层的寄存器都是不对用户开放的)导致了数据中止异常。 当然上述只是我的推测而已,不知道是否正确,还请大牛批评指正! |