windowsCE异常和中断服务程序初探


nbsp; 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                
  ...
  endif
        movs    pc, lr
        entry_end swihandler
        上面if 到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!,                        ; save spsr onto the irq stack   
        mov     r0,lr                     &

COPYRIGHT(C) 2011 厦门永宏亚得机电科技有限公司版权所有(闽ICP备05025945号) ALL RIGHTS RESERVED?

电话: 0592-5190891 传真: 0592-5190720 E-Mail: E-mail:yade8895@163.com
地址: 厦门市海沧区兴港六里17号2607室 邮编:361009 联系人:翟先生