首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

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

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

; mark reschedule needed
                            ;情况1:r0=SYSINTR_RESCHED=1
                            ;情况2: r0 =r0-SYSINTR_DEVICES>=SYSINTR_MAX_DEVICES        
10      ldrb    r0, [lr, #bResched]             ; (r0) = reschedule flag
        orr     r0, r0, #1                      ; set "reschedule needed bit"
        strb    r0, [lr, #bResched]             ; update flag


20      mrs     r1, spsr                        ; (r1) = saved status register value


        and     r1, r1, #0x1F                   ; (r1) = interrupted mode
        cmp     r1, #USER_MODE                  ; previously in user mode?
        cmpne   r1, #SYSTEM_MODE                ; if not, was it system mode?
        cmpeq   r0, #1                          ; user or system: is resched == 1
        ;if(SytemMode(spsr)||UserMode(spsr))&&r0!=1) return;
        ldmnefd sp!, {r0-r3, r12, pc}^          ; can't reschedule right now so return
  *************************************************************************************
        sub     lr, lr, #4
        ldmfd   sp!, {r0-r3, r12}
        stmdb   lr, {r0-r3}
        ldmfd   sp!, {r0}
        str     r0, [lr]                        ; save resume address
        mov     r1, #ID_RESCHEDULE              ; (r1) = exception ID
        b       CommonHandler
        ENTRY_END IRQHandler
    将spsr_irq压入IRQ堆栈保存。为调用OEMInterruptHandler作准备。(通常中断处理程序切换入系统态执行的目的在于避免使用终端模式下的寄存器,以方便是实现终端套嵌,这儿切入系统态时终端使能是关闭的,对于模态切换的原因我很迷惑。)OEMInterrupt需要在特权模式下执行,所以这里增加了切换入特权(SVC)模式的内容。紧接着将要用与传递参数的寄存器保存。设定传入参数,r0就可以开始调用OEMInterruptHandler了,这里的调用规则遵循windowsCE的规范而不是ATPCS的规范。具体过程参考arm Parameter Passing@msdn。下面是函数原形。int OEMInterruptHandler(unsigned int ra);这里传入的参数就是上面的r0,事实上r0代表的参数ra并没有实质的作用在这里仅仅是形式上的实现一下而已,不过在这儿可以看到这个传入的ra实际上就是被中断的地址,如果需要知道被中断的位置可以通过ra来查询,而msdn里面说这个参数是保留的。返回的参数也是保存在r0中。其中返回值是系统中断类型。其中SYSINTR_RESCHED为系统时钟中断,每次时间片用完,该时钟便产生中断,并设置kData结构的bResched位,进入调度流程。如果中断类型是系统设备中断,那就设置PendEvents,待再次调度的时候处理中断。所以OEMInterruptHandler必须提前就要对中断进行响应对该中断源设置mask,防止在这过程中同一中断不停发生,导致中断饱和影响程序流的执行,直道中断处理真正完成后再次开放该中断的mask。在这里还可以看到的是系统设备中断号的范围是从SYSINTR_DEVICES到SYSINTR_MAX_DEVICES,也就是从9-40一共32个设备中断号,其中SYSINTR_FIRMWARE为8+16号,这个在编写OAL的中断服务程序时需要注意。如果当前的返回值既不是设备中断号又不是调度中断号,则读出当前调度标示,根据该标示进行判断是否调度/或返回.如果是进入调度流程则恢复初始的寄存器状态,再按CommonHandler的要求保存寄存器。进入CommonHandler,等待分发。

2-3 FIQ服务程序
        照例看看程序
        NESTED_ENTRY FIQHandler
        sub     lr, lr, #4                      ; fix return address
        stmfd   sp!, {r0-r3, r12, lr}
        PROLOG_END
        CALL    OEMInterruptHandlerFIQ
        ldmfd   sp!, {r0-r3, r12, pc}^          ; restore regs & return for NOP
        ENTRY_END FIQHandler
        LTORG
返回列表