历史上的今天
返回首页

历史上的今天

今天是:2025年07月12日(星期六)

正在发生

2021年07月12日 | ARM裸机开发(二)——ARM异常处理

2021-07-12 来源:eefocus

一、ARM异常分类

异常就是正常的用户程序被暂时中止,处理器就进入异常模式。


ARM CPU的异常分为:复位异常、中断异常(IRQ,FIR)、预取指令中止异常、未定义指令异常、软件中断指令异常、数据中止访问异常。


1、复位异常

当CPU刚上电时或按下reset重启键之后进入该异常,该异常在管理模式下处理。


2、中断(IRQ、FIQ)异常

CPU和外部设备是分别独立的硬件执行单元,CPU对全部设备进行管理和资源调度处理,CPU要想知道外部设备的运行状态,要么CPU定时的去查看外部设备特定寄存器,要么让外部设备在出现需要CPU干涉处理时“打断”CPU,让它来处理外部设备的请求,毫无疑问第二种方式更合理,可以让CPU“专心”去工作,这里的“打断”操作就叫做中断请求,根据请求的紧急情况,中断请求分一般中断和快速中断,快速中断具有最高中断优先级和最小的中断延迟,通常用于处理高速数据传输及通道的中数据恢复处理,如DMA等,绝大部分外设使用一般中断请求。


3、预取指令中止异常

异常发生在CPU流水线取指阶段,如果目标指令地址是非法地址进入该异常,该异常在中止异常模式下处理。


4、未定义指令异常

异常发生在流水线技术里的译码阶段,如果当前指令不能被识别为有效指令,产生未定义指令异常,该异常在未定义异常模式下处理。


5、软件中断指令(swi)异常

异常是应用程序自己调用时产生的,用于用户程序申请访问硬件资源时,例如:printf()打 印函数,要将用户数据打印到显示器上,用户程序要想实现打印必须申请使用显示器,而用户程序又没有外设硬件的使用权,只能通过使用软件中断指令切换到内核态,通过操作系统内核代码来访问外设硬件,内核态是工作在特权模式下,操作系统在特权模式下完成将用户数据打印到显示器上。这样做的目的无非是为了保护操 作系统的安全和硬件资源的合理使用,该异常在管理模式下处理。


6、数据中止访问异常

异常发生在要访问数据地址不存在或者为非法地址时,该异常在中止异常模式下处理。


二、ARM异常发生的硬件操作

在异常发生后,ARM内核会自动做以下工作:


A、保存执行状态:将CPSR复制到发生的异常模式下SPSR中

B、模式切换:将CPSR模式位强制设置为与异常类型相对应的值,同时处理器进入到ARM执行模式,禁止所有IRQ中断,当进入FIQ快速中断模式时禁止FIQ中断

C、保存返回地址:将下一条指令的地址(被打断程序)保存在LR(异常模式下LR_excep)中

D、跳入异常向量表:强制设置PC的值为相应异常向量地址,跳转到异常处理程序中


1、保存执行状态

当前程序的执行状态是保存在CPSR里面的,异常发生时,要保存当前的CPSR里的执行状态到异常模式里的SPSR里,将来异常返回时,恢复回CPSR,恢复执行状态。


2、模式切换

硬件自动根据当前的异常类型,将异常码写入CPSR里的M[4:0]模式位,这样CPU就进入了对应异常模式下。不管是在ARM状态下还是在THUMB状态下发生异常,都会自动切换到ARM状态下进行异常的处理,这是由硬件自动完成的,将CPSR[5] 设置为 0。同时,CPU会关闭中断IRQ(设置CPSR 寄存器I位),防止中断进入,如果当前是快速中断FIQ异常,关闭快速中断(设置CPSR寄存器F位)。


3、保存返回地址

当前程序被异常打断,切换到异常处理程序里,异常处理完之后,返回当前被打断模式继续执行,因此必须要保存当前执行指令的下一条指令的地址到LR_excep(异常模式下LR,并不存在LR_excep寄存器,为方便读者理解加上_excep,以下道理相同),由于异常模式不同以及ARM内核采用流水线技术,异常处理程序里要根据异常模式计算返回地址。


4、跳入异常向量表

跳入异常向量表操作是CPU硬件自动完成的,当异常发生时,CPU强制将PC的值修改为一个固定内存地址,这个固定地址叫做异常向量。ARM的异常向量表如下:

异常向量表是一段特定内存地址空间,每种ARM异常对应一个字长空间(4Bytes),正好是一条32位指令长度,当异常发生时,CPU强制将PC的值设置为当前异常对应的固定内存地址。


ARM异常的优先级从高到低依次为Reset→Data abort→FIQ→IRQ→Prefetch abort→Undefined instruction/SWI。


跳入异常向量表操作是异常发生时,硬件自动完成的,剩下的异常处理任务完全交给了程序员。由异常向量表可知,异常向量是一个固定的内存地址,可以通过向地址处写一条跳转指令,让它跳向我们自己定义的异常处理程序的入口,就可以完成异常处理。


异常向量表的存在,让硬件异常处理和程序员自定义处理程序有机联系起来。异常向量表里0x00000000地址处是reset复位异常,每种异常向量都占有四个字节,最后一个异常是快速中断异常,将其安装在此也有它的意义,在0x0000001C地址处可以直接存放快速中断的处理程序,不用设置跳转指令,这样可以节省一个时钟周期,加快快速中断处理时间。


安装异常向量表:


b reset              ;跳入reset处理程序

b HandleUndef          ;跳入未定义处理程序

b HandSWI            ;跳入软中断处理程序

b HandPrefetchAbt       ;跳入预取指令处理程序

b HandDataAbt          ;跳入数据访问中止处理程序

b HandNoUsed          ;跳入未使用程序

b HandleIRQ          ;跳入中断处理程序

b HandleFIQ          ;跳入快速中断处理程序


通常安装完异常向量表,跳到程序员自己定义的处理程序入口,此时被打断程序的现场尚未保存,因此在异常处理程序的入口里先要保存打断程序现场。


保存执行现场:


异常处理程序最开始,要保存被打断程序的执行现场,程序的执行现场无非就是保存当前操作寄存器里的数据,可以通过下面的栈操作指令实现保存现场:


STMFD SP_excep!, {R0 – R12, LR_excep}


注:LR_abt,SP_excep分别为对应异常模式下LR和SP,为方便读者理解加上_abt


在跳转到异常处理程序入口时,就已经切换到对应异常模式下,因此这里的SP是异常模式下的SP_excep,所以被打断程序现场(寄存器数据)是保存在异常模式下的栈里,上述指令将R0~R12全部都保存到了异常模式栈,最后将修改完的被打断程序返回地址入栈保存,所以保存该返回地址就是为了将来可以通过类似:MOV PC, LR的指令,返回用户程序继续执行。


异常发生后,要针对异常类型进行处理,因此,每种异常都有自己的异常处理程序。


三、ARM异常的返回地址

每一种异常发生时,其返回地址都要根据具体异常类型进行重新修复返回地址,再次强调下,被打断程序的返回地址保存在对应异常模式下的LR_excep里。


1、中断(FIQ、IRQ)异常

快速中断请求和一般中断请求返回处理是一样的。通常处理器执行完当前指令后,查询FIQ/IRQ中断引脚,并查看是否允许FIQ/IRQ中断,如果某个中断引脚有效,并且系统允许该中断产生,处理器将产生FIQ/IRQ异常中断,当FIQ/IRQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置),当FIQ/IRQ异常中断产生时,处理器将值(pc-4)保存到FIQ/IRQ异常模式下的寄存器lr_irq/lr_irq中,它指向当前指令之后的第2条指令,因此正确返回地址可以通过下面指令算出:


SUBS PC,LR_irq,#4 ; 一般中断


SUBS PC,LR_fiq,#4 ; 快速中断


注:LR_irq/LR_fiq分别为一般中断和快速中断异常模式下LR,并不存在LR_xxx寄存器,为方便读者理解加上_xxx


2、预取指令中止异常

在指令预取时,如果目标地址是非法的,该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行,当执行到该被标记成有问题的指令时,处理器产 生指令预取中止异常中断。发生指令预取异常中断时,程序要返回到该有问题的指令处,重新读取并执行该指令,因此指令预取中止异常中断应该返回到产生该指令 预取中止异常中断的指令处,而不是当前指令的下一条指令。


指令预取中止异常中断由当前执行的指令在ALU里执行时产生,当指令预取中止异常中断发生时,程序计数器pc的值还未更新,它指向当前指令后面第2条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。此时处理器将值(pc-4)保存到lr_abt中,它指向当前指令的下一条指令,所以返回操作可以通过下面指令实现:


SUBS PC,LR_abt,#4


注:LR_abt为中止模式下LR,并不存在LR_abt寄存器,为方便读者理解加上_abt


3、未定义指令异常

未定义指令异常中断由当前执行的指令在ALU里执行时产生,当未定义指令异常中断产生时,程序计数器pc的值还未更新,它指向当前指令后面第2条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置),当未定义指令异常中断发生时,处理器将值(pc-4)保存到lr_und中,此时(pc-4)指向当前指令的下一条指令,所以从未定义指令异常中断返回可以通过如下指令来实现:


MOV PC, LR_und


注:LR_und为未定义模式下LR,并不存在LR_und寄存器,为方便读者理解加上_und


4、软中断指令(SWI)异常

SWI异常中断和未定义异常中断指令一样,也是由当前执行的指令在ALU里执行时产生,当SWI指令执行时,pc的值还未更新,它指向当前指令后面第2条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置),当未定义指令异常中断发生时,处理器将值(pc-4)保存到lr_svc中,此时(pc-4)指向当前指令的下一条指令,所以从SWI异常中断处理返回的实现方法与从未定义指令异常中断处理返回一样:


MOV PC, LR_svc


注:LR_svc为管理模式下LR,并不存在LR_svc寄存器,为方便读者理解加上_svc


5、数据中止异常

发生数据访问异常中断时,程序要返回到该有问题的指令处,重新访问该数据,因此数据访问异常中断应该返回到产生该数据访问中止异常中断的指令处,而不是当前指令的下一条指令。


数据访问异常中断由当前执行的指令在ALU里执行时产生,当数据访问异常中断发生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置)。此时处理器将值(pc-4)保存到lr_abt中,它指向当前指令后面第2条指令,所以返回操作可以通过下面指令实现:


SUBS PC, LR_abt, #8


注:LR_abt为中止模式下LR,并不存在LR_abt寄存器,为方便读者理解加上_abt


四、ARM异常的返回

异常处理完成之后,返回被打断程序继续执行,具体操作如下:


A、恢复被打断程序运行时寄存器数据

B、恢复程序运行时状态CPSR

C、通过进入异常时保存的返回地址,返回到被打断程序继续执行


异常发生后,进入异常处理程序时,将用户程序寄存器R0R12里的数据保存在了异常模式下栈里面,异常处理完返回时,要将栈里保存的的数据再恢复回原先R0R12里,毫无疑问在异常处理过程中必须要保证异常处理入口和出口时栈指针SP_excep要一样,否则恢复到R0~R12里的数据不正确,返回被打断程序时执行现场不一致,出现问题,虽然将执行现场恢复了,但是此时还是在异常模式下,CPSR里的状态是异常模式下状态,因此要恢复SPSR_excep里的保存状态到CPSR里,SPSR_excep是被打断程序执行时的状态,在恢复SPSR_excep到CPSR的同时,CPU的模式和状态从异常模式切换回了被打断程序执行时的模式和状态。此刻程序现场恢复了,状态也恢复了,但PC里的值仍然指向异常模式下的地址空间,我们要让CPU继续执行被打断程序,因此要再手动改变PC的值为进入异常时的返回地址,该地址在异常处理入口时已经计算好,直接将PC = LR_excep即可。


上述操作通常可以通过一条指令实现上述全部操作:


LDMFD SP_excp!, {r0-r12, pc}^


注:SP_excep为对应异常模式下SP,^符号表示恢复SPSR_excep到CPSR


中断处理流程图:

推荐阅读

史海拾趣

DeLorme公司的发展小趣事

进入21世纪后,DeLorme公司凭借其在GPS技术领域的深厚积累,不断推出具有创新性的产品。其中,一款集成了GPS、电子罗盘和高度计等多功能的户外导航设备在市场上引起了广泛关注。这款产品不仅具有高精度、高可靠性的特点,还具备了用户友好的界面设计和人性化的操作体验。通过这款产品,DeLorme公司进一步巩固了其在户外导航领域的领先地位。

Advantech公司的发展小趣事

随着公司业务的不断发展,DeLorme公司开始积极寻求市场扩张的机会。他们通过与国外知名品牌的合作,将自己的产品推向了国际市场。同时,他们还积极参与国际性的户外活动和赛事,通过这些活动提高品牌知名度和影响力。在国际市场的竞争中,DeLorme公司凭借其独特的技术优势和优质的产品质量逐渐获得了认可。

Cooper Industries公司的发展小趣事

在电工产品领域,Cooper Industries同样取得了显著的成就。2000年,公司收购了Eagle电气,并将其与已有的接线装置产品系列合并,组建成了一个名为“库柏电工”的新事业部。这一举措不仅丰富了公司的产品线,也使其在电工产品领域的技术实力得到了进一步提升。库柏电工提供了超过10000个高质量装置的产品组合,广泛应用于工业、商业和住宅领域,满足了不同客户的需求。同时,公司还不断投入研发,推出更加先进、高效的电工产品,为行业的发展做出了积极贡献。

DECON公司的发展小趣事

品质是企业的生命线,DECON公司深知这一点。因此,公司建立了完善的品质管理体系,从原材料采购到生产过程的每一个环节都进行严格的质量监控。公司引进了先进的生产设备和技术,优化了生产流程,提高了生产效率和产品质量。同时,公司还建立了完善的售后服务体系,为客户提供及时、高效的技术支持和解决方案。

Aeroflex Metelics / Hi-Rel Components公司的发展小趣事

品质是企业的生命线,DECON公司深知这一点。因此,公司建立了完善的品质管理体系,从原材料采购到生产过程的每一个环节都进行严格的质量监控。公司引进了先进的生产设备和技术,优化了生产流程,提高了生产效率和产品质量。同时,公司还建立了完善的售后服务体系,为客户提供及时、高效的技术支持和解决方案。

Fremont_Micro_Devices_USA公司的发展小趣事

品质是企业的生命线,DECON公司深知这一点。因此,公司建立了完善的品质管理体系,从原材料采购到生产过程的每一个环节都进行严格的质量监控。公司引进了先进的生产设备和技术,优化了生产流程,提高了生产效率和产品质量。同时,公司还建立了完善的售后服务体系,为客户提供及时、高效的技术支持和解决方案。

问答坊 | AI 解惑

简易无线话筒

如果你的收录机有调频接收波段,不妨动手制作一个无线话筒,可给你的生活增添不少乐趣。这里介绍一个无线话筒,在开阔地区有效距离约100 m左右。…

查看全部问答>

这样的情况是装减速机好,还是不装好呢?

现有一设备用伺服电机驱动丝杆带动平台做往复运动,现算出达到平台最高运动速度,丝杆的转速需要500转每分钟,伺服电机的额定转速为3000转每分钟. 请问一下各位这时是电机直连丝杆好呢,还是电机通过1:4减速机减速后连接丝杆好呢,电机直联也能驱动,但 ...…

查看全部问答>

电源工程师需要的基本技能和专业理论知识(薪水评估)

开关电源产品的设计过程实际是一个优化折衷的过程.工程师们常常在各种电性能参数之间举棋不定,如稳态性能与动态性能的折衷,功率密度与可靠性的折衷等.在追求低功耗高效率的今天,摆在电源工程师面前的难题仍然是功耗和性能的取舍. 开发一个开关电 ...…

查看全部问答>

急求DSP控制写CF卡的程序代码,相关资料也可以,谢谢帮助!

要用DSP控制向CF卡写数据,具体流程是什么?请高手指点 急求DSP控制写CF卡的程序代码,相关资料也可以,谢谢帮助! 我的邮箱:haolinchen_0@126.com…

查看全部问答>

sdi分配器

    小弟我最近要做sdi分配器,查了一天资料也没有找到合适的方案,哪位仁兄能给个提示?比如推荐相关的芯片,小弟我不胜感激!…

查看全部问答>

谁有《arm嵌入式系统开发》的源代码请共享下好吗?

《arm嵌入式系统开发》这本书的英文名字是《arm system developer\'s guide》。 一本很好的书,可惜源代码不能下载了,谁有的话共享下好吗?谢谢。 …

查看全部问答>

在tf卡上CeMountDBVol为什么会出错?

{                         CeMountDBVol(&g_guidDB, szPath, …

查看全部问答>

分析:百万高清摄像机容易被忽视的考察点 [转帖]

最近看到很多网友在喜欢论坛粘贴百万高清网络摄像机的漂亮图片,来吸引大家的眼球,确实清晰度要比模拟摄像机高很多。百万高清是行业发展的必然趋势,但是大家千万不能只看到像素,却忽略了百万高清网络摄像机的其他重要考察点。 【发热量】 ...…

查看全部问答>

团购示波器群:359838(6位qq群)

团购示波器群:359838(6位qq群) --本群目的:团购示波器和其他各种电工仪表工具以及DIY 业余DIY或者搞兼职,万用表是必用的,每个电工都有, 但示波器就不一定了,没示波器,调电路不是不行,得多花 非常多的功夫。 这些功夫就是钱啊,时间就 ...…

查看全部问答>

点火线圈不良引起间歇性断火

故障现象:一辆上海通用五菱LZW6360Ei7型微型客车,配备电喷发动机。该车出现严重的加速无力、“缺缸”现象,以致无法正常行驶。据车主反映,每次更换火花塞后,车辆能正常行驶1000km左右,然后就出现高速“闯车”现象,而且越来越严重,最后导致车 ...…

查看全部问答>