0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

通过HandleException处理所有异常

电子设计 来源:互联网 作者:佚名 2018-08-28 10:26 次阅读

NasIRy

1.中断/异常相量的装入和执行方式

中断和异常都是异步发生的事件,当该事件发生,系统将停止目前正在执行的代码转而执行事件响应的服务程序。而事件服务程序的入口点就是中断/异常向量所在的位置。ARM的中断向量可以是0x0开始的低地址向量,也可以是在FFFF0000位置的高向量地址。winCE下使用高地址作为trap区,所以在CE下arm使用高地址向量。

VectorINStructions

ldr pc, [pc, #0x3E0-8] ; reset

ldr pc, [pc, #0x3E0-8] ; undefined instruction

ldr pc, [pc, #0x3E0-8] ; SVC

ldr pc, [pc, #0x3E0-8] ; Prefetch abort

ldr pc, [pc, #0x3E0-8] ; data abort

ldr pc, [pc, #0x3E0-8] ; unused vector location

ldr pc, [pc, #0x3E0-8] ; IRQ

ldr pc, [pc, #0x3E0-8] ; FIQ

而在ffff03e0的位置放上如下的数据,每一项(32bit)对应一个异常的跳转地址也就是winCE的异常/中断向量跳转表。该表项的内容就是发生异常后将要执行的服务程序的入口地址。具体如下。

VectorTable

DCD -1 ; reset

DCD UndefException ; undefined instruction

DCD SWIHandler ; SVC

DCD PrefetchAbort ; Prefetch abort

IF :DEF:ARMV4T :LOR: :DEF:ARMV4I

DCD OEMDataAbortHandler ; data abort

ELSE

DCD DataAbortHandler ; data abort

ENDIF

DCD -1 ; unused vector

DCD IRQHandler ; IRQ

DCD FIQHandler ; FIQ

在上面的这些代码/数据在内存空间上按照上述要求放置好以后,每次触发一个异常就自动运行到相应跳转表项所对应的地址执行。

2.异常/中断服务程序

在arm下,由于有7种异常状态包括reset、Undef exception、software interrupt(swi)、Prefech Abort、DataAbort、IRQ、FIQ七种异常/中断。reset仅在复位时发生,其他6种都是在系统运行时发生。当任何一个异常发生并得到响应时,ARM 内核自动完成以下动作:

拷贝 CPSR 到 SPSR_

设置适当的 CPSR 位:

改变处理器状态进入 ARM 状态

改变处理器模式进入相应的异常模式

设置中断禁止位禁止相应中断

更新 LR_

设置 PC 到相应的异常向量

同时不管异常发生在ARM 还是Thumb 状态下,处理器都将自动进入ARM 状态。并且中断使能会自动被关闭。在这个时候由于部分通用寄存器是不同模式公用的,所以还需要保存这些将会被破坏的寄存器,待到处理完成的时候恢复这些寄存器被中断前的状态。另外在进入异常模式后,lr的值不一定就是我们所需恢复执行的位置,该位置受到异常类型和流水线误差的影响。在SWI模式下,LR就是返回值。在IRQ和FIQ中LR=LR-4,DataAbort下LR=LR-8;下面分别对这些服务程序进行分析。

2-1.undef exception服务程序

undef exception在执行到过非法的指令时产生,通常来模拟一些处理器不支持的功能,如浮点运算。简单说一下undef exception的过程:当当前指令为一条处理器不支持的指令时,处理器会自动动将该指令送交各协处理器(如MMU、FPU)处理,如果这些协处理器都无法识别这条指令的时候,就产生该异常。下面开始看相应的代码。

NESTED_ENTRY UndefException

sub lr, lr, #4 ; (lr) = address of undefined instruction

stmdb sp, {r0-r3, lr}

mov r1, #ID_UNDEF_INSTR

b CommonHandler

ENTRY_END UndefException

上面就是undef Exception的服务程序的入口处(已经将不参与编译和Thumb模式下的代码去掉),通过lr-=4计算出触发异常前的指令地址,同时保存r0-r3和lr入undef_exception stack用于最后恢复现场和取得异常指令本身,随后进入分发程序CommonHandler.CommonHandler是一个公共的异常服务程序,它通过不同的传入参数来进行处理,在这里mov r1,#ID_UNDEF_INSTR就是指定异常模式为undef Exception.

2-2.swi服务程序

按在ARM处理器的设计意图,系统软件的系统调用(SystemCalls)都是通过SWI指令完成。SWI相当于一个中断指令,不同的是SWI不是由外部中断源产生的,同时对应于SWI的异常向量位于0xc的位置或0xffff 000c的位置。也就是说当执行一个swi指令后,当前程序流中断,并转入0xc或0xffff000c执行,同时将CPSR_mode(当前程序状态寄存器)复制入SPSR_svc,转入SVC模式运行(使用特权模式的寄存器组)。也就是说系统通过执行SWI引发系统swi异常后切换入特权模式,系统调用功能号由swi xx后的xx决定,在运行完指定功能的代码后返回异常时的地址并恢复用户模式。Wince中这部分代码是如何实现的。

DCD SWIHandler ; SVC《--------------------------SWI入口点。

LEAF_ENTRY SWIHandler

IF {FALSE}

ENDIF

movs pc, lr

ENTRY_END SWIHandler

上面IF {FALSE}到ENDIF之间的代码在编译的时候是得不到编译的(事实上这部分代码是用于开发中调试使用的,针对特殊的硬件平台,一般与我们使用的硬件平台无关。所以下面摘抄的代码都不将不参与编译的内容写入),因此SWI服务程序就是一句话。movs pc, lr也就是直接回到SWI的地方,同时将SPSR_svc恢复到CPSR_mode中。这个过程中并没有进行在系统态执行特定系统指令序的工作,而仅仅是简单的返回,所以这不是系统调用,系统调用还需要根据调用号的不同运行指定的核心态代码。也就是说Wince的系统调用不是通过SWI来完成的,而是通过其他的异常处理手段达成的。

2-3 中断服务程序

IRQ(大概是最熟悉的异常方式了)在外部中断源在需要向处理器请求服务时发生,比如:时钟、外围器件FIFO上/下溢出、按键等等。IRQHandler就是中断的处理句柄,具体如下。

----------------------------------------------------------------------------------

NESTED_ENTRY IRQHandler

sub lr, lr, #4 ; fix return address

stmfd sp!, {r0-r3, r12, lr} ;保存将要用到的寄存器和lr压入stack_irq

PROLOG_END

和上面一样,服务程序的入口处都是例行公事的计算返回位置以抵消流水线误差。再将要用到的寄存器压入STACK_IRQ。

; Test interlocked API status.

;INTERLOCKED_START EQU USER_KPAGE 0x380

;INTERLOCKED_END EQU USER_KPAGE 0x400

sub r0, lr, #INTERLOCKED_START

cmp r0, #INTERLOCKED_END-INTERLOCKED_START

bllo CheckInterlockedRestart

上面这部分的内容是关于互锁的检测,由于如信号量这些同步手段都必须作为原子操作进行,不允许打断。所以如果中断发生在互锁API的执行过程中,就需要专门的处理了。这些API都是放在INTERLOCKED_START和INTERLOCKED_END之间的,通过LR很容易就检查出是否是INTERLOCKEDXXX的过程中。这里并不关心互锁的实现就绕开这部分代码继续往下看,当作中断没有发生在interlock过程处理。

;

; CAREFUL! The stack frame is being altered here. It's ok since

; the only routine relying on this was the Interlock Check. Note that

; we re-push LR onto the stack so that the incoming argument area to

; OEMInterruptHandler will be correct.

;

mrs r1, spsr ; (r1) = saved status reg

stmfd sp!, {r1} ; save SPSR onto the IRQ stack

mov r0,lr ; parameter to OEMInterruptHandler

msr cpsr_c, #SVC_MODE:OR:0x80 ; switch to supervisor mode w/IRQs disabled

stmfd sp!, {lr} ; save LR onto the SVC stack

stmfd sp!, {r0} ; save IRQ LR (in R0) onto the SVC stack (param)

;

; Now we call the OEM's interrupt handler code. It is up to them to

; enable interrupts if they so desire. We can't do it for them since

; there's only on interrupt and they haven't yet defined their nesting.

;

CALL OEMInterruptHandler

ldmfd sp!, {r1} ; dummy pop (parameter)

ldmfd sp!, {lr} ; restore SVC LR from the SVC stack

msr cpsr_c, #IRQ_MODE:OR:0x80 ; switch back to IRQ mode w/IRQs disabled

; Restore the saved program status register from the stack.

;

ldmfd sp!, {r1} ; restore IRQ SPSR from the IRQ stack

msr spsr, r1 ; (r1) = saved status reg

ldr lr, =KData ; (lr) = ptr to KDataStruct

cmp r0, #SYSINTR_RESCHED ;->时间片已到,进行调度

beq

%B20

; interrupted, reschedule again

msr spsr, r2

ldr lr, [r0, #TcxPc-TcxR3]

ldmdb r0,

movs pc,

lr

; return to user or system mode

HandleException是实际进行异常处理的函数,针对上面没有处理完的异常进一步分析并进行处理。这个函数是没有公开代码的,所以没有办法进一步深入下去。由于处理的异常类型比较多所以这个异常处理函数的代码量是相当大的,因此会耗费相对比较多的时钟周期,在之前的代码中我们都是在关闭中断的情况下进行异常处理,如果在这里还不打开中断的话整个异常处理过程会相当的长,这样会很大程度上影响系统的实时性,所以在这里调用HandleException之前是将中断重新打开的,待到处理完成再将中断关闭。对于这些异常,如果不能处理就只有两种情况:1.结束该进程/线程。2.挂起系统。第二种情况下挂起系统HandleException是不会返回的。因此,只有异常处理正常流程和结束线程的可能。对于返回的情况,这个时候如果返回触发异常的地址继续运行的话,仍然会导致异常,所以结束进程/线程都需要重新调度才能完成了。对于异常处理成功的情形,就不必调度了,直接就可以返回产生异常的地方继续执行。在这里还要考虑套嵌(这里仅仅是指系统模式和兼管模式的异常套嵌)的情形,也就是中断/异常已经进入调度状态又再次产生中断/异常,这个时候就强行取消上一次调度,进而重新调度。这用于调度过程中遇到异常恢复和剥夺的情况,如果不属于这种情况的话就直接恢复寄存器状态并且返回中断点继续执行。

; Return to a non-preemptible privileged mode.

;

; (r0) = ptr to THREAD structure

; (r2) = target mode

30 msr cpsr,

r2

; switch to target mode

add r0, r0, #TcxR0

ldmia r0,

; reload all registers & return

通过HandleException处理以后,已经完成了所有异常的处理,所以这里只是考虑反回的情况,由于这里不包含用户模式下的处理,所以这里处理的都是特权模式,完全可以访问kdata区域,这里就直接利用Kdata区域中的线程备份来完成恢复寄存器和返回。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    19275

    浏览量

    229737
  • SWI
    SWI
    +关注

    关注

    0

    文章

    56

    浏览量

    22892
  • WinCE
    +关注

    关注

    2

    文章

    128

    浏览量

    49035
收藏 人收藏

    评论

    相关推荐

    用OPA2353UA做电压跟随器时,输出有异常,是什么原因呢?

    请教下,我是用OPA2353UA做电压跟随器时,输出有异常,是什么原因呢? 输出波形如下
    发表于 08-07 08:19

    OPA615在输入为0 mv时,输出有异常直流电平怎么解决?

    OPA615在输入为0 mv时,输出有异常直流电平问题
    发表于 08-09 07:28

    Java中的常用异常处理方法 java推荐

    finally 代码块中,可以运行清理类型等收尾善后性质的语句。声明自定义异常在Java中可以自定义异常,在自定义异常类时需注意以下几点:1. 所有异常都必须是 Throwable
    发表于 01-19 17:26

    网络爬虫常见异常情况

    的关系,即HTTPError是URLError的子类,HTTPError有异常状态码与异常原因,URLError没有异常状态码。所以,我们在处理的时候,不能使用URLError直接代替
    发表于 05-09 17:26

    请问SYS/BIOS中有异常机制吗?用户可以自己设置异常处理函数吗?

    本帖最后由 一只耳朵怪 于 2018-6-20 10:53 编辑 请问SYS/BIOS中有异常机制吗?用户可以自己设置异常处理函数吗?目前开发用的C6678+SYS/BIOS。
    发表于 06-20 01:22

    多通道AD使用读多个通道数据有异常

    用一多通道AD7734转换4路模拟量,四通道单独用均好使;多通道启动后读任意一个通道数据正常,读多个通道数据有异常,请教原因,望不吝赐教,谢谢!
    发表于 11-19 09:13

    Java捕获异常处理的常用方法

    finally 代码块中,可以运行清理类型等收尾善后性质的语句。声明自定义异常在Java中可以自定义异常,在自定义异常类时需注意以下几点:1. 所有异常都必须是 Throwable
    发表于 11-27 11:40

    Java异常体系级处理办法

    Exception,Throwable作为所有异常的超类,如图:    Error:一般为底层的不可恢复的类,一般此类错误都比较严重,JVM将终止其运行的线程;  VirtualMachineError
    发表于 01-05 17:48

    LCD电容触摸屏,触摸屏幕时,总是会有异常坐标,这是为何?

    LCD电容触摸屏,触摸屏幕时,总是会有异常坐标,这是为何?
    发表于 07-02 10:58

    C语言的异常处理案例代码

    相信很多朋友在此之前可能根本没有使用或者听说过C语言的异常处理,印象中都是C++或者java才有的东西,C语言怎么会有异常处理呢?
    的头像 发表于 12-22 08:44 3818次阅读

    一种针对浮点运算的分段式异常处理方法

    异常会造成程序错误,实现完全没有异常的浮点计算软件也很艰难,因此,实现有效的异常处理方法很重要.但现有的异常
    发表于 01-19 15:50 1次下载

    处理器中异常和中断解决

    或中断请求(IRQ)。几乎所有的现代处理器都支持异常和中断,微控制器的中断可以由片上外设或软件产生。由此可见,通常我们处理的中断是异常的一种
    的头像 发表于 10-12 17:14 5075次阅读

    PLC的异常类型和处理办法

    1.中央处理异常: 如果出现中央处理异常报警,应检查连接到中央处理器内部总线的所有设备。具体
    发表于 04-19 09:43 0次下载
    PLC的<b class='flag-5'>异常</b>类型和<b class='flag-5'>处理</b>办法

    SpringMVC 如何优雅的处理各种异常

    那有没有一种方案,既不需要跟Controller耦合,也可以将定义的 异常处理器 应用到所有控制器呢?所以注解@ControllerAdvice出现了,简单的说,该注解可以把异常
    发表于 05-29 16:00 517次阅读
    SpringMVC 如何优雅的<b class='flag-5'>处理</b>各种<b class='flag-5'>异常</b>?

    变压器有异常响声是什么原因 变压器异常声响的原因有哪些?

    变压器有异常响声是什么原因 变压器异常声响的原因有哪些? 变压器是电力系统中非常重要的电气设备,用于将高电压变换为低电压或者低电压变换为高电压,以便进行输电或者供电。在变压器的运行过程中,有时候会发
    的头像 发表于 11-23 15:34 1w次阅读