1TMTHEARCHITECTUREFORTHEDIGITALWORLD异常处理2TM263v07ExceptionHandlingtestAgenda序言中断处理软中断(SWI)处理其它异常处理3TM363v07ExceptionHandlingtestVectorTableVectortablecanbeat0xFFFF0000onARM720TandonARM9/10familydevicesFIQIRQ(Reserved)DataAbortPrefetchAbortSoftwareInterruptUndefinedInstructionReset0x1C0x180x140x100x0C0x080x040x00异常处理当异常产生时,ARMcore:拷贝CPSR到SPSR_mode设置适当的CPSR位:改变处理器状态进入ARM状态改变处理器模式进入相应的异常模式设置中断禁止位禁止相应中断(如果需要)保存返回地址到LR_mode设置PC位相应的异常向量返回时,异常处理需要:从SPSR_mode恢复CPSR从LR_mode恢复PCNote:这些操作只能在ARM态执行.4TM463v07ExceptionHandlingtest从SWI和Undef异常返回MOVSpc,lr从FIQ,IRQ和预取异常(PrefectAbort)返回SUBSpc,lr,#4从数据异常(DataAbort)返回SUBSpc,lr,#8如果LR之前被压栈的话使用LDM“^”LDMFDsp!,{pc}^异常返回:使用一数据处理指令:相应的指令取决于什么样的异常在特权模式不仅仅更新PC,而且拷贝SPSR到CPSR设置CPSR,“S”bitPC做为目的寄存器异常返回指令Seeendofpresentationforbackgroundinformationontheseinstructions5TM563v07ExceptionHandlingtest异常优先级异常在当前指令执行完成之后才被响应多个异常可以在同一时间产生异常指定了优先级和固定的服务顺序:ResetDataAbortFIQIRQPrefetchAbortSWIUndefinedinstruction6TM663v07ExceptionHandlingtest向量表指令32Mbytes4KbytesLiteralpoolcontainingaddressofUndefHandlerIRQhandlerwithin32MBytesBranchinstructionrangeSWIExceptionhandlerplacedonapplicableaddressboundaryFIQhandlerfollowsvectortableUndefhandleroutside32MBytesbranchinstructionrange0x00x10000x20000000xFFC0x80x180x300000000xFFFFFFFF0x1C0x4MOVPC,#0x30000000BIRQ_handler0x30008000IRQHandlerSWIHandlerFIQHandlerLDRPC,[PC,#+0xFF0]UndefHandler0x300080007TM763v07ExceptionHandlingtestARMorThumb?Thumb/ARM混合应用程序ARMCodeARMCodeThumbCodeFIQIRQ(Reserved)DataAbortPrefetchAbortSoftwareInterruptUndefinedInstructionReset8TM863v07ExceptionHandlingtest异常处理中的寄存器使用与异常发生相关的模式改变意味着所调用的异常处理程序至少要访问:私有的SP_mode(stackpointer).私有的LR_mode(linkregister).私有的SPSR_mode(savedprogramstatusregister).在FIQ异常处理中,另有5个私有的通用寄存器(r8_fiqtor12_fiq).其它的寄存器是所有模式公用的.异常处理程序必须确保其他的寄存器在退出前恢复到原来的状态这可以通过将任何正在使用的寄存器的内容保存在堆栈中,并在返回前恢复来实现任何所需寄存器的初始化要有应用程序的起始代码来完成,参阅:“EmbeddedSoftwareDevelopment”9TM963v07ExceptionHandlingtestAgenda序言中断处理软中断(SWI)处理其它异常处理10TM1063v07ExceptionHandlingtest中断处理ARM有两级外部中断FIQ,IRQ.可是大多数的基于ARM的系统有2个的中断源!因此需要一个中断控制器(通常是地址映射的)来控制中断是怎样传递给ARM的。在许多系统中,一些中断的优先级比其它中断的优先级高,他们要抢先任何正在处理的低优先级中断。Note:通常中断处理程序总是应该包含清除中断源的代码。地址映射中断控制器nIRQnFIQARMMultiplePeripheralinterruptsourcesARM读控制器寄存器并找到IRQ/FIQ中断源ARM写外设寄存器清相应中断源11TM1163v07ExceptionHandlingtestFIQvsIRQFIQ和IRQ提供了非常基本的优先级级别。在下边两种情况下,FIQs有高于IRQs的优先级:当多个中断产生时,FIQ高于IRQ.处理FIQ时禁止IRQs.IRQs将不会被响应直到FIQ处理完成.FIQs的设计使中断处理尽可能的快.FIQ向量位于中断向量表的最末.为了使中断处理程序可从中断向量处连续执行FIQ模式有5个额外的私有寄存器(r8-r12)中断处理必须保护其使用的非私有寄存器可以有多个FIQ中断源,但是考虑到系统性能应避免嵌套。12TM1263v07ExceptionHandlingtestC语言简单中断处理程序在C中可以在函数定义时使用关键词“__irq”来写一个简单的中断处理程序.这将导致:函数所有用到的寄存器被保护如果可能,任何远程调用所使用的其他寄存器也被保护函数退出使用正确的返回指令(修正pc=lr-4并从spsr恢复cpsr)__irq仅仅可在armcc中使用.可是被__irq函数调用的子程序可以用tcc编译.确保IRQ的堆栈指针已经设置!13TM1363v07ExceptionHandlingtestC中断处理示例__irqvoidIRQHandler(void){volatileunsignedint*source=(unsignedint*)0x80000000;if(*source==1)//whichinterruptwasitint_handler_1();//processtheinterrupt//insertchecksforotherinterruptsourceshere*(source+1)=0;//cleartheinterrupt}Outputwithout__irqOutputwith__irqSTMFDsp!,{r4,lr}STMFDsp!,{r0-r4,r12,lr}MOVr4,#0x80000000MOVr4,#0x80000000LDRr0,[r4,#0]LDRr0,[r4,#0]CMPr0,#1CMPr0,#1BLEQint_handler_1BLEQint_handler_1MOVr0,#0MOVr0,#0dfgSTRr0,[r4,#4]STRr0,[r4,#4]LDMFDsp!,{r4,pc}LDMFDsp!,{r0-r4,r12,lr}SUBSpc,lr,#414TM1463v07ExceptionHandlingtestC中断处理示例__irqvoidIRQHandler(void){volatileunsignedint*source=(unsignedint*)0x80000000;if(*source==1)//whichinterruptwasit?int_handler_1();//processtheinterrupt//insertchecksforotherinterruptsourceshere*(source+1)=0;//cleartheinterrupt}Outputwithout__irqOutputwith__irqSTMFDsp!,{r4,lr}MOVr4,#0x80000000LDRr0,[r4,#0]CMPr0,#1LEQint_handler_1MOVr0,#0STRr0,[r4,#4]LDMFDsp!,{r4,pc}STMFDsp!,{r0-r4,r12,lr}MOVr4,#0x80000000LDRr0,[r4,#0]CMPr0,#1BLEQint_handler_1MOVr0,#0STRr0,[r4,#4]LDMFDsp!,{r0-r4,r12,lr}SUBSpc,lr,#415TM1563v07ExceptionHandlingtest中断重新使能的问题当另外一个中断抢先当前中断时,如果程序员使用下边特殊的步骤来防止系统状态丢失,中断是可以嵌套:保存IRQ状态下的LR(LR_irq)保存IRQ状态下的SPSR(SPSR_IRQ)当中断可重入时,在中断处理程序中使用“BL…”必须特别小心:如果第二个中断产生,BL调用的返回地址(LR_irq)可能被冲掉,子程序将错误的返回–导致无限循环!解决方法是在使用“BL…”之前改变模式来避免LR_irq被冲掉通常使用“System”模式(这时BL使用LR_usr)在处理程序结束,必须:切换回IRQ模式禁止中断(来避免在恢复SPSR_irq到一个临时的寄存器中后它被冲掉).__irq不能用来写可重入中断处理程序必须采用采用下页中汇编代码段来代替。16TM1663v07ExceptionHandlingtestC可重入中断示例IRQHandlerSUBlr,lr,#4STMFDsp!,{lr}MRSr14,SPSRSTMFDsp!,{r12,r14}MOVr12,#IntBaseLDRr12,[r12,#IntSource]MRSr14,CPSRBICr14,r14,#0x9FORRr14,r14,#0x1FMSRCPSR_c,r14STMFDsp!,{r0-r3,lr}MOVr0,r12BLC_irq_handlerLDMFDsp!,{r0-r3,lr}MRSr12,CPSRBICr12,r12,0x1FORRr12,r12,0x92MSRCPSR_c,r12LDMFDsp!,{r12,r14}MSRSPSR_csxf,r14LDMFDsp!,{PC}^切换到IRQ模式同时禁止IRQ.LR_irq,SPSR_irq和工作寄存器(r12)压栈保护来避免下一次中断发生使它们被冲掉}保存R0-3,LR_user到user栈中,然后调用C子程序,中断源(R0)作为一个参数传入C处理函数。}恢复LR_irq,SPSR_irq和工作寄存器(r12),然后退出中断处理使用修正后的LR}读/清中断控制器中断源{切换到System模式同时使能IRQ{{17TM1763v07ExceptionHandlingtestQuiz1)中断向量表位于存储器的什么位置?2)IRQ或FIQ异常的返回指令是什么?3)什么类型的中断优先级最高?4)什么指令可以放在中断向量表?5)FIQ的什么特点使得它处理的速度比IRQ快?6)在嵌套的中断处理程序中,如何确保LR没有被破坏?18TM1863v07ExceptionHandlingtestAgenda序言中断处理软中断(SWI)处理其它异常处理19TM1963v07Exc