在OS_CPU_A.ASM中,定义了开、关中断的方法,在uC/OS-II系统中有三种方法可以实现中断开关,而ARM只适用于模式三,即使用一个局部变量,在中断进入之间保存CPU状态,退出时候再恢复状态。
OSStart()函数调用OSStartHighRdy()来使就绪态任务中优先级最高的任务开始运行,OSStartHighRdy()必须调用OSTaskSwHook(),调用完STaskSwHook()后,应该使OSRunning标志位为TRUE,最后再切换到最高优先级任务。此函数只是完成了高优先级任务寄存器的恢复,并没有保存当前任务的寄存器。
OSCtxSw(),任务级切换;
OSIntCtxSw(),中断级别的任务切换;
异常处理程序

********************************************************************************************************
;                                           PUBLIC FUNCTIONS
;********************************************************************************************************
                                                                ; External references
    EXTERN  OSRunning
    EXTERN  OSPrioCur
    EXTERN  OSPrioHighRdy
    EXTERN  OSTCBCur
    EXTERN  OSTCBHighRdy
    EXTERN  OSIntNesting
    EXTERN  OSIntExit
    EXTERN  OSTaskSwHook

                                                                ; Functions declared in this file
    PUBLIC  OS_CPU_SR_Save
    PUBLIC  OS_CPU_SR_Restore
    PUBLIC  OSStartHighRdy
    PUBLIC  OSCtxSw
    PUBLIC  OSIntCtxSw
                                                                ; Functions related to exception handling
    PUBLIC  OS_CPU_ARM_ExceptResetHndlr
    PUBLIC  OS_CPU_ARM_ExceptUndefInstrHndlr
    PUBLIC  OS_CPU_ARM_ExceptSwiHndlr
    PUBLIC  OS_CPU_ARM_ExceptPrefetchAbortHndlr
    PUBLIC  OS_CPU_ARM_ExceptDataAbortHndlr
    PUBLIC  OS_CPU_ARM_ExceptAddrAbortHndlr
    PUBLIC  OS_CPU_ARM_ExceptIrqHndlr
    PUBLIC  OS_CPU_ARM_ExceptFiqHndlr
    EXTERN  OS_CPU_ExceptHndlr
;********************************************************************************************************
;                                                EQUATES
;********************************************************************************************************
;根据CPSR的低8位设置I,F,T,及M[4:0]
OS_CPU_ARM_CONTROL_INT_DIS        EQU  0xC0                     ; Disable both FIQ and IRQ
OS_CPU_ARM_CONTROL_FIQ_DIS        EQU  0x40                     ; Disable FIQ
OS_CPU_ARM_CONTROL_IRQ_DIS        EQU  0x80                     ; Disable IRQ
OS_CPU_ARM_CONTROL_THUMB          EQU  0x20                     ; Set THUMB mode
OS_CPU_ARM_CONTROL_ARM            EQU  0x00                     ; Set ARM mode
OS_CPU_ARM_MODE_MASK              EQU  0x1F
OS_CPU_ARM_MODE_USR               EQU  0x10                     ;用户模式   
OS_CPU_ARM_MODE_FIQ               EQU  0x11                     ;FIQ模式
OS_CPU_ARM_MODE_IRQ               EQU  0x12                     ;IRQ模式
OS_CPU_ARM_MODE_SVC               EQU  0x13                     ;管理模式
OS_CPU_ARM_MODE_ABT               EQU  0x17                     ;终止模式
OS_CPU_ARM_MODE_UND               EQU  0x1B                     ;未定义模式
OS_CPU_ARM_MODE_SYS               EQU  0x1F                     ;系统模式
;定义异常
OS_CPU_ARM_EXCEPT_RESET           EQU  0x00
OS_CPU_ARM_EXCEPT_UNDEF_INSTR     EQU  0x01
OS_CPU_ARM_EXCEPT_SWI             EQU  0x02
OS_CPU_ARM_EXCEPT_PREFETCH_ABORT  EQU  0x03
OS_CPU_ARM_EXCEPT_DATA_ABORT      EQU  0x04
OS_CPU_ARM_EXCEPT_ADDR_ABORT      EQU  0x05
OS_CPU_ARM_EXCEPT_IRQ             EQU  0x06
OS_CPU_ARM_EXCEPT_FIQ             EQU  0x07
;********************************************************************************************************
;                                      CODE GENERATION DIRECTIVES
;********************************************************************************************************
    RSEG CODE:CODE:NOROOT(2)
    CODE32

;*********************************************************************************************************
;                                  CRITICAL SECTION METHOD 3 FUNCTIONS
;采用ucos所提出的模式3来禁止中断和开中断,实现硬保护
; Description: Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
;              would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;              disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
;              disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
;              into the CPU's status register.
;
;也就是说cpu_sr是一个局部变量,在进入中断之前使用它来保存状态,退出时再恢复
;
; Prototypes : OS_CPU_SR  OS_CPU_SR_Save    (void);
;              void       OS_CPU_SR_Restore (OS_CPU_SR  os_cpu_sr);
;
;
; Note(s)    : (1) These functions are used in general like this:
;
;                 void Task (void  *p_arg)
;                 {
;                                                               /* Allocate storage for CPU status register.            */
;                 #if (OS_CRITICAL_METHOD == 3)
;                      OS_CPU_SR  os_cpu_sr;
;                 #endif
;
;                          :
;                          :
;                      OS_ENTER_CRITICAL();                     /* os_cpu_sr = OS_CPU_SR_Save();                        */
;                          :
;                          :
;                      OS_EXIT_CRITICAL();                      /* OS_CPU_SR_Restore(cpu_sr);                           */
;                          :
;                          :
;                 }
;
;              (2) OS_CPU_SR_Restore() is implemented as recommended by Atmel's application note:
;
;                    "Disabling Interrupts at Processor Level"
;*********************************************************************************************************

OS_CPU_SR_Save
    MRS     R0, CPSR                                            ;复制CPSR到R0
OS_CPU_SR_Save_Loop
                                                                ; Set IRQ and FIQ bits in CPSR to disable all interrupts
    ORR     R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS
    
    ;RO中存放了CPSR,把#OS_CPU_ARM_CONTROL_INT_DIS和R0进行逻辑或运算,结果存放到R1中
    
    MSR     CPSR_c, R1
    
    ;传送R1的内容到CPSR,但是只修改CPSR中的控制位域[7:0]
    
    MRS     R1, CPSR                                            ; Confirm that CPSR contains the proper interrupt disable flags
    AND     R1, R1, #OS_CPU_ARM_CONTROL_INT_DIS
    CMP     R1,     #OS_CPU_ARM_CONTROL_INT_DIS
    BNE     OS_CPU_SR_Save_Loop                                 ; Not properly disabled (try again)
    BX      LR                                                  ; Disabled, return the original CPSR contents in R0
OS_CPU_SR_Restore                                               ; See Note #2
    MSR     CPSR_c, R0
    BX      LR
;*********************************************************************************************************
;                                           START MULTITASKING
;                                       void OSStartHighRdy(void)
;
; Note(s) : 1) OSStartHighRdy() MUST:
;              a) Call OSTaskSwHook() then,
;              b) Set OSRunning to TRUE,
;              c) Switch to the highest priority task.
;;*********************************************************************************************************
OSStartHighRdy
                                                                ; Change to SYS mode
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
    LDR     R0, ?OS_Running                                     ; OSRunning = TRUE;
    MOV     R1, #1
    STRB    R1, [R0]
    ;LDR指令将存储器中一个32位的字数据传送到目的寄存器,而STR相反,STRB只是传输低8位
    LDR     R0, ?OS_TaskSwHook                                  ; OSTaskSwHook();
    MOV     LR, PC
    BX      R0
                                                                ;    SWITCH TO HIGHEST PRIORITY TASK
    LDR     R0, ?OS_TCBHighRdy                                  ;    Get highest priority task TCB address
    LDR     R0, [R0]                                            ;    get stack pointer
    LDR     SP, [R0]                                            ;    switch to the new stack
    LDR     R0, [SP], #4                                        ;    pop new task's CPSR
    
    ;有些代码在这里写成 LDMFD   SP!,{R0}
    
    MSR     CPSR_cxsf, R0
    LDMFD   SP!, {R0-R12, LR, PC}                               ;    pop new task's context
;*********************************************************************************************************
;                         PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
;                         任务级切换
; Note(s) : 1) OSCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
;
;           2) The pseudo-code for OSCtxSw() is:
;              a) Save the current task's context onto the current task's stack
;              b) OSTCBCur->OSTCBStkPtr = SP;
;              c) OSTaskSwHook();
;              d) OSPrioCur             = OSPrioHighRdy;
;              e) OSTCBCur              = OSTCBHighRdy;
;              f) SP                    = OSTCBHighRdy->OSTCBStkPtr;
;              g) Restore the new task's context from the new task's stack
;              h) Return to new task's code
;
;           3) Upon entry:
;              OSTCBCur      points to the OS_TCB of the task to suspend
;              OSTCBCur指向即将挂起的任务,而OSTCBHighRdy指向即将恢复的任务
;              OSTCBHighRdy  points to the OS_TCB of the task to resume
;*********************************************************************************************************
OSCtxSw
                                                                ; SAVE CURRENT TASK'S CONTEXT
    STMFD   SP!, {LR}                                           ;     Push return address
    ;LR中其实是任务切换时对应的PC值
    STMFD   SP!, {LR}
    STMFD   SP!, {R0-R12}                                       ;     Push registers
    MRS     R0, CPSR                                            ;     Push current CPSR
    TST     LR, #1                                              ;     See if called from Thumb mode
    ORRNE   R0, R0, #OS_CPU_ARM_CONTROL_THUMB                   ;     If yes, Set the T-bit
    STMFD   SP!, {R0}
    ;至此,在堆栈中保存环境的任务已经完成
    
    LDR     R0, ?OS_TCBCur                                      ; OSTCBCur->OSTCBStkPtr = SP;
    LDR     R1, [R0]
    STR     SP, [R1]
    LDR     R0, ?OS_TaskSwHook                                  ; OSTaskSwHook();
    MOV     LR, PC
    BX      R0
    LDR     R0, ?OS_PrioCur                                     ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, ?OS_PrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    LDR     R0, ?OS_TCBCur                                      ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, ?OS_TCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    LDR     SP, [R2]                                            ; SP = OSTCBHighRdy->OSTCBStkPtr;
                                                                ; RESTORE NEW TASK'S CONTEXT
    LDMFD   SP!, {R0}                                           ;    Pop new task's CPSR
    MSR     CPSR_cxsf, R0
    LDMFD   SP!, {R0-R12, LR, PC}                               ;    Pop new task's context
;*********************************************************************************************************
;                     PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
;                     中断级的任务切换
; Note(s) : 1) OSIntCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED
;
;           2) The pseudo-code for OSIntCtxSw() is:
;              a) OSTaskSwHook();
;              b) OSPrioCur             = OSPrioHighRdy;
;              c) OSTCBCur              = OSTCBHighRdy;
;              d) SP                    = OSTCBHighRdy->OSTCBStkPtr;
;              e) Restore the new task's context from the new task's stack
;              f) Return to new task's code
;
;           3) Upon entry:
;              OSTCBCur      points to the OS_TCB of the task to suspend
;              OSTCBHighRdy  points to the OS_TCB of the task to resume
;
;            OSIntCtxSw()和OSCtxSw()相似,区别是OSIntCtxSw()是在ISR中被调用的,ISR已经保存了CPU的寄存器,
;            所以不需要再此保存寄存器的值
;*********************************************************************************************************
OSIntCtxSw
    LDR     R0, ?OS_TaskSwHook                                  ; OSTaskSwHook();
    MOV     LR, PC
    BX      R0
    LDR     R0, ?OS_PrioCur                                     ; OSPrioCur = OSPrioHighRdy;
    LDR     R1, ?OS_PrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    LDR     R0, ?OS_TCBCur                                      ; OSTCBCur  = OSTCBHighRdy;
    LDR     R1, ?OS_TCBHighRdy
    LDR     R2, [R1]
    STR     R2, [R0]
    LDR     SP, [R2]                                            ; SP = OSTCBHighRdy->OSTCBStkPtr;
                                                                ; RESTORE NEW TASK'S CONTEXT
    LDMFD   SP!, {R0}                                           ;    Pop new task's CPSR
    MSR     CPSR_cxsf, R0
    LDMFD   SP!, {R0-R12, LR, PC}                               ;    Pop new task's context
;********************************************************************************************************
;                                        RESET EXCEPTION HANDLER
; 进入异常后,LR会指向下一条指令的地址,所以在压栈的时候,需要减去相应的值。
; 对于reset,svc,swi减去0,对于预取终止,irq,fiq减去4,对于数据中止和地址中止减去8
;********************************************************************************************************
OS_CPU_ARM_ExceptResetHndlr
                                                                ; LR offset to return from this exception:  0
                                                                ;  (there is no way to return from a RESET exception)
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_RESET                        ; Set exception ID to OS_CPU_ARM_EXCEPT_RESET
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                UNDEFINED INSTRUCTION EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptUndefInstrHndlr
                                                                ; LR offset to return from this exception:  0
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR                  ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                 SOFTWARE INTERRUPT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptSwiHndlr
                                                                ; LR offset to return from this exception:  0
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_SWI                          ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                   PREFETCH ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptPrefetchAbortHndlr
    SUB     LR, LR, #4                                          ; LR offset to return from this exception: -4
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT               ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                     DATA ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptDataAbortHndlr
    SUB     LR, LR, #8                                          ; LR offset to return from this exception: -8
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT                   ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                    ADDRESS ABORT EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptAddrAbortHndlr
    SUB     LR, LR, #8                                          ; LR offset to return from this exception: -8
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT                   ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                  INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptIrqHndlr
    SUB     LR, LR, #4                                          ; LR offset to return from this exception: -4
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_IRQ                          ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                               FAST INTERRUPT REQUEST EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptFiqHndlr
    SUB     LR, LR, #4                                          ; LR offset to return from this exception: -4
    STMFD   SP!, {R0-R12, LR}                                   ; Push working registers
    MOV     R3, LR                                              ; Save link register
    MOV     R0, #OS_CPU_ARM_EXCEPT_FIQ                          ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ
    B            OS_CPU_ARM_ExceptHndlr                         ; Branch to global exception handler
;********************************************************************************************************
;                                       GLOBAL EXCEPTION HANDLER
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr
    MRS     R1, SPSR                                            ; Save CPSR (i.e. exception's SPSR)
                                                                ; DETERMINE IF WE INTERRUPTED A TASK OR ANOTHER LOWER PRIORITY EXCEPTION
                                                                ;   SPSR.Mode = FIQ, IRQ, SVC, ABT, UND : Other exception
                                                                ;   SPSR.Mode = SYS                     : Task
                                                                ;   SPSR.Mode = USR                     : *unsupported state*
    AND     R2, R1, #OS_CPU_ARM_MODE_MASK                       ;   保留R1的低8位控制位
    CMP     R2,     #OS_CPU_ARM_MODE_SYS
    BNE     OS_CPU_ARM_ExceptHndlr_BreakExcept
;********************************************************************************************************
;                                  EXCEPTION HANDLER: TASK INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BreakTask
    MRS     R2, CPSR                                            ; Save exception's CPSR
    MOV     R4, SP                                              ; Save exception's stack pointer
                                                                ; Change to SYS mode & disable interruptions
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
                                                                ; SAVE TASK'S CONTEXT ONTO TASK'S STACK
    STMFD   SP!, {R3}                                           ;   Push task's PC
    STMFD   SP!, {LR}                                           ;   Push task's LR
    STMFD   SP!, {R5-R12}                                       ;   Push task's R12-R5
    LDMFD   R4!, {R5-R9}                                        ;   Move task's R4-R0 from exception stack to task's stack
    STMFD   SP!, {R5-R9}
    TST     R3, #1                                              ;   See if called from Thumb mode
    ORRNE   R1, R1, #OS_CPU_ARM_CONTROL_THUMB                   ;   If yes, Set the T-bit
    STMFD   SP!, {R1}                                           ;   Push task's CPSR (i.e. exception SPSR)
                                                                ; if (OSRunning == 1)
    LDR     R1, ?OS_Running
    LDRB    R1, [R1]
    CMP     R1, #1
    BNE     OS_CPU_ARM_ExceptHndlr_BreakTask_1
                                                                ; HANDLE NESTING COUNTER
    LDR     R3, ?OS_IntNesting                                  ;   OSIntNesting++;
    LDRB    R4, [R3]
    ADD     R4, R4, #1
    STRB    R4, [R3]
    LDR     R3, ?OS_TCBCur                                      ;   OSTCBCur->OSTCBStkPtr = SP;
    LDR     R4, [R3]
    STR     SP, [R4]
OS_CPU_ARM_ExceptHndlr_BreakTask_1
    MSR     CPSR_cxsf, R2                                       ; RESTORE INTERRUPTED MODE
    LDR     R1, ?OS_CPU_ExceptHndlr                             ; OS_CPU_ExceptHndlr();
    MOV     LR, PC
    BX      R1
                                                                ; Adjust exception stack pointer. This is needed because
                                                                ; exception stack is not used when restoring task context.
    ADD     SP, SP, #(14*4)
                                                                ; Change to SYS mode & disable interruptions.
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
                                                                ; Call OSIntExit(). This call MAY never return
                                                                ;  if a ready task with higher priority than
                                                                ;  the interrupted one is found.
    LDR     R0, ?OS_IntExit
    MOV     LR, PC
    BX      R0
                                                                ; RESTORE NEW TASK'S CONTEXT
    LDMFD   SP!, {R0}                                           ;    Pop new task's CPSR
    MSR     CPSR_cxsf, R0
    LDMFD   SP!, {R0-R12, LR, PC}                               ;    Pop new task's context
;********************************************************************************************************
;                               EXCEPTION HANDLER: EXCEPTION INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_ExceptHndlr_BreakExcept
    MRS     R2, CPSR                                            ; Save exception's CPSR
                                                                ; Change to SYS mode & disable interruptions
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
                                                                ; HANDLE NESTING COUNTER
    LDR     R3, ?OS_IntNesting                                  ;   OSIntNesting++;
    LDRB    R4, [R3]
    ADD     R4, R4, #1
    STRB    R4, [R3]
    MSR     CPSR_cxsf, R2                                       ; RESTORE INTERRUPTED MODE
    LDR     R3, ?OS_CPU_ExceptHndlr                             ; OS_CPU_ExceptHndlr();
    MOV     LR, PC
    BX      R3
                                                                ; Change to SYS mode & disable interruptions
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
                                                                ; HANDLE NESTING COUNTER
    LDR     R3, ?OS_IntNesting                                  ;   OSIntNesting--;
    LDRB    R4, [R3]
    SUB     R4, R4, #1
    STRB    R4, [R3]
    MSR     CPSR_cxsf, R2                                       ; RESTORE INTERRUPTED MODE
    LDMFD   SP!, {R0-R12, PC}^                                  ; Pull working registers and return from exception.
;*********************************************************************************************************
;                                     POINTERS TO VARIABLES
;*********************************************************************************************************
    DATA
?OS_Running:
    DC32    OSRunning
?OS_PrioCur:
    DC32    OSPrioCur
?OS_PrioHighRdy:
    DC32    OSPrioHighRdy
?OS_TCBCur:
    DC32    OSTCBCur
?OS_TCBHighRdy:
    DC32    OSTCBHighRdy
?OS_IntNesting:
    DC32    OSIntNesting
?OS_TaskSwHook:
    DC32    OSTaskSwHook
?OS_IntExit:
    DC32    OSIntExit
?OS_CPU_ExceptHndlr:
    DC32    OS_CPU_ExceptHndlr
    END
04-20 00:14