改造了下:<br /> LDR PC, IRQ_Addr ;地址0x18<br />IRQ_Addr DCD IRQ_Handler ;0x38<br />IRQ_Handler <br /> SUB LR, LR, #4 ; Calculate the returning address 计算返回地址 <br /> STMFD SP!, {R0-R3, R12, LR} ; Protects the task environments 保存任务环境 <br /> MRS R3, SPSR ; Protects the status variable 保存状态 <br /> STMFD SP, {R3,LR}^ ; Protects SPSR and SP in user status, Notice: DO NOT write back.保存SPSR和用户状态的SP,注意不能回写 <br /> ; If the SP is written back, it should be adjusted to its appropriate value later.如果回写的是用户的SP,所以后面要调整SP <br /> NOP <br /> SUB SP, SP, #4*2 <br /> <br /> MSR CPSR_c, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Switch to the System Mode 切换到系统模式 <br />; MSR CPSR_c, #Mode_SYS:OR:F_Bit<br /> <br /> LDR R0, =0xFFFFFF00 ;VICVectAddr 0xFFFFFF00<br /> LDR PC, [R0] <br /> <br /> MSR CPSR_c, #Mode_IRQ:OR:I_Bit ; Switch bak to IRQ mode 切换回irq模式 <br /> LDMFD SP, {R3,LR}^ ; Recover SPSR and SP in user status, Notic: DO NOT write back. 恢复SPSR和用户状态的SP,注意不能回写 <br /> ; If the SP is written back, it should be adjusted to its appropriate value later.如果回写的是用户的SP,所以后面要调整SP <br /> MSR SPSR_cxsf, R3 <br /> ADD SP, SP, #4*2 ; <br /> <br /> LDMFD SP!, {R0-R3, R12, PC}^ ; <br /><br />中断处理函数基本类似如下:<br />void TIMER0_Handler(void) __irq<br />{<br /> VICIntEnClr = 1 << TIMER0_INT; //禁止T1中断<br />__asm { MRS sysreg, SPSR; MSR CPSR_c, #SYS32Mode }<br /><br />function();<br /> VICVectAddr = 0x0; <br /> VICIntEnable = 1 << TIMER0_INT; <br />}<br /><br />IRQ_Handler部分基本是盗版ZLG的,改了下,有2个问题<br />1, MSR CPSR_c, #Mode_SYS:OR:F_Bit <br />这句原本是打算仅关闭FIQ中断也禁止的,可一旦写成 MSR CPSR_c, #Mode_SYS:OR:F_Bit后,单步调试时箭头在LDR R0, =0xFFFFFF00 行首后单步执行,立马跑到数据异常入口。<br />2,改成MSR CPSR_c, #Mode_SYS:OR:F_Bit:I_BIT 后,在只有单个中断产生时能够正常响应和退出中断程序。在有第二个更高优先级中断产生时,程序跳出未执行完的低优先中断,进入高优先级的中断处理函数,可当高优先中断处理完毕后,程序不是回去执行前面未执行完的低优先中断处理函数,而是和所有中断都处理完毕一样,感觉是LR寄存器被破坏了,可又不知道改怎么改,哪位大侠指点下?<br />
|