历史上的今天
返回首页

历史上的今天

今天是:2025年04月23日(星期三)

正在发生

2020年04月23日 | windowsCE异常和中断服务程序初探

2020-04-23 来源:eefocus

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

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


在kernelStart的过程中通过程序将如下代码复制到ffff0000的位置.

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;具体原因我们就不讨论了,有兴趣可以参看<基于ARM 的嵌入式程序开发要点>一文。


下面分别对这些服务程序进行分析。

  

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      ;->时间片已到,进行调度

推荐阅读

史海拾趣

博众电气(BOZHONG ELECTRIC)公司的发展小趣事

博众电气始终坚信,品质是企业生存和发展的根本。因此,公司始终将品质管理放在首位,并严格执行ISO9001等国际质量管理体系标准。

为了进一步提升产品品质和管理水平,博众电气还积极申请并通过了多项国际认证。这些认证不仅证明了博众电气的产品品质和管理水平达到了国际先进水平,还为公司的国际化发展提供了有力保障。

ALCOA公司的发展小趣事

在20世纪的后半叶,ALCOA继续在技术上取得重大突破。例如,在40年代,公司采用N-40(Niagara)50kA中心下料预焙阳极电解槽技术为政府建造了铝冶炼厂。此外,公司还不断扩大海外业务,建立了全球性的生产和销售网络。这种全球布局使得ALCOA能够更好地满足不同地区的市场需求,也增强了公司的竞争力。

埃派克森微电子(Apexone)公司的发展小趣事

自2002财年以来,埃派克森微电子的业绩呈现出连续增长的态势。公司凭借出色的产品性能和市场竞争力,成功打入多家国内外知名企业,逐渐在目标市场占据了一席之地。经过数年的发展,埃派克森在全球模拟芯片供应商中已占据重要地位,其产品在通讯核心芯片、多媒体电子、消费电子、汽车电子等领域均有着广泛的应用。

Hammond公司的发展小趣事

自2002财年以来,埃派克森微电子的业绩呈现出连续增长的态势。公司凭借出色的产品性能和市场竞争力,成功打入多家国内外知名企业,逐渐在目标市场占据了一席之地。经过数年的发展,埃派克森在全球模拟芯片供应商中已占据重要地位,其产品在通讯核心芯片、多媒体电子、消费电子、汽车电子等领域均有着广泛的应用。

Beckhoff Automation GmbH公司的发展小趣事

品质是电子行业的生命线,BCD Semi公司深知这一点。因此,公司始终将品质管理放在首位,建立了完善的品质管理体系和质量控制流程。公司从原材料采购、生产制造到产品出厂,每一个环节都进行严格的质量把控,确保产品的高品质和稳定性。同时,BCD Semi还不断引进先进的生产设备和技术,优化生产流程,提高生产效率,为客户提供更优质的产品和服务。

FTDI [Future Technology Devices International Ltd.]公司的发展小趣事

近年来,FTDI通过并购等方式不断拓展其业务范围。例如,电连技术通过发行股份及支付现金的方式收购了FTDI的部分股权,使FTDI成为其控股子公司。这一并购不仅为电连技术带来了FTDI在USB桥接芯片领域的领先技术,还促进了双方在产品、客户和销售渠道等方面的协同效应。同时,FTDI也借此机会进一步提升了其在新兴市场如汽车电子、物联网等领域的竞争力。

问答坊 | AI 解惑

用于高灵敏度器件的交流与直流测量方法

用于高灵敏度器件的交流与直流测量方法…

查看全部问答>

新手请教一个shell问题

小弟现在在启动系统的时候出现shell不能正常运行的情况,感觉是没有shell fdIn = ioGlobalStdGet (STD_IN);     fdOut = ioGlobalStdGet (STD_OUT);     fdErr = ioGlobalStdGet (STD_ERR);     #endif /* SHEL ...…

查看全部问答>

关于U-BLOX 5S的GPS模块在接收数据上分析的问题

小弟最近调试GPS模块,通过单片机串口已经能够接收GPS模块发来的信息了,但是在接收$GPMRC消息的时候,总是有时间信息,后面的定位信息总是V,看手册说V是无法定位,只有A后面才是有效数据,但是总是收不到A,为什么还能收到时间呢?…

查看全部问答>

wince下用什么函数可代替getenv()???

wince下用什么函数可代替getenv()?希望知道的高手告诉一下…

查看全部问答>

求助!信号处理问题

我做一个多参数测试仪,现在有一个复合信号,怎么样分离出交流分量和直流分量. …

查看全部问答>

3D洗衣机 今天你凭什么牛气冲天?

本帖最后由 jameswangsynnex 于 2015-3-3 19:58 编辑 3D智能控制技术,小身材大容量的秘密   过去,人们不得不在洗衣机占位和洗衣效率之间做出选择,要么牺牲精致装修的效果,选择庞然大物;要么牺牲洗衣效率,忍受多次洗衣的繁琐。现在,为了调 ...…

查看全部问答>

请教版主STM32的抗干扰问题

                                 我用STM32做了一个光源控制器,下面有个驱动板。用STM32引脚中的PD8,9,10接1K电阻直接驱动一个指示用LED,一切正常 ...…

查看全部问答>

【晒经典】晒晒我设计的家用煤气报警器

这个从PCB到程序都是本楼主一人完成,现晒晒原理哈,这个老好了,重来就不误报呵呵       这个报警器可不是一般的报警器它可控制电磁阀。直接就关了煤气,等人回来后再把电磁阀拨出来。又重新使用,这个可以挂在家里煤气的 ...…

查看全部问答>

AVR单片机矩阵键盘控制电机

AVR单片机矩阵键盘控制电机,PE口接键盘,pc口接电机,电机正转是0x28,我不知道哪里有问题,求帮忙#include <iom128v.h> #define uchar unsigned char #define uint unsigned int uchar tab[]={0x28,0x28,0x28,0x28}; void delay(uint k) ...…

查看全部问答>

入门贴虚拟机+ubuntu 12.04 环境搭建教程

http://wenku.baidu.com/view/734ae36148d7c1c708a14530.html…

查看全部问答>