SMARTARM2200 ADS工程在IAR EWARM 5.3上的移植(2)-uCOSII移植代码分析

uCOS移植代码主要位于工程路径下的\uCOS-II\Ports\ARM\Generic\IAR\os_cpu_a.asm(在uC-CPU下有个cpu_a.s,里面定义了OS_CPU_SR_Save和OS_CPU_SR_Restore,但实际上未用到,用到的是os_cpu_a.asmOS_CPU_SR_Save和OS_CPU_SR_Restore来进行开关中断)

这里就os_cpu_a.asm里的主要几个函数进行简单分析.更加详细的内容可参考邵贝贝译的《嵌入式实时操作系统uCOS-II》(第二版)

1.开关中断

;********************************************************************************************************
;                                  CRITICAL SECTION METHOD 3 FUNCTIONS
;
; 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.
;
;这是开关中断方式3的实现方式,先是保存CPSR值(最终保存到变量cpu_sr),然后禁止中断,最后返回

OS_CPU_SR_Save
    MRS     R0, CPSR
    ORR     R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS                 ; Set IRQ and FIQ bits in CPSR to disable all interrupts.
    MSR     CPSR_c, R1
    BX       LR                                                  ; Disabled, return the original CPSR contents in R0.


OS_CPU_SR_Restore
    MSR     CPSR_c, R0
    BX        LR

//在cpu.h中定义了开关中断的宏

#define  OS_CRITICAL_METHOD    3


#if      OS_CRITICAL_METHOD == 3
//未定义OS_CPU_INT_DIS_MEAS_EN,OS_CPU_IntDisMeasStart()是用来中断计时的,未用到
#if      OS_CPU_INT_DIS_MEAS_EN > 0

#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();  \
                               OS_CPU_IntDisMeasStart();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_IntDisMeasStop();   \
                               OS_CPU_SR_Restore(cpu_sr);}

#else

//实际用到的定义

#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}
#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}

#endif

#endif

2.然后就是任务切换,运行最高优先级任务的例程,如OSStartHighRdy,OSCtxSw,OSIntCtxSw,以OSStartHighRdy为例,主要都是进行push/pop stack,PC指针的切换.

 ;********************************************************************************************************
;                                           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 SVC mode.
    MSR     CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC)

    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
    MOV     LR, PC
    BX      R0

    LDR     R0, =OSRunning                                          ; OSRunning = TRUE;
    MOV     R1, #1
    STRB    R1, [R0]

                                                                                  ; SWITCH TO HIGHEST PRIORITY TASK:
    LDR     R0, =OSTCBHighRdy                                    ;    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,
    MSR     SPSR_cxsf, R0

    LDMFD   SP!, {R0-R12, LR, PC}^                            ;    Pop new task's context.

3.异常/中断处理
接下来实现了在cstartp.s引用的几个异常处理函数

OS_CPU_ARM_ExceptUndefInstrHndlr
OS_CPU_ARM_ExceptSwiHndlr
OS_CPU_ARM_ExceptPrefetchAbortHndlr
OS_CPU_ARM_ExceptDataAbortHndlr
OS_CPU_ARM_ExceptAddrAbortHndlr
OS_CPU_ARM_ExceptFiqHndlr
;以OS_CPU_ARM_ExceptFiqHndlr为例:
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     R2, 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.
;然后跳转到OS_CPU_ARM_ExceptHndlr
OS_CPU_ARM_ExceptHndlr
    MRS     R1, SPSR           ; Save CPSR (i.e. exception's SPSR).

                                        ; DETERMINE IF WE INTERRUPTED A TASK/IRQ OR ANOTHER LOWER PRIORITY EXCEPTION:
                                        ;   SPSR.Mode = SVC                :  task or IRQ handled in SVC mode,
                                        ;   SPSR.Mode = FIQ, IRQ, ABT, UND :  other exceptions,
                                        ;   SPSR.Mode = USR                : *unsupported state*.
    AND     R3, R1, #OS_CPU_ARM_MODE_MASK
    CMP     R3,     #OS_CPU_ARM_MODE_SVC
    BNE     OS_CPU_ARM_ExceptHndlr_BrkExcept
;如果不是SVC模式进入OS_CPU_ARM_ExceptHndlr_BrkExcept否则进入OS_CPU_ARM_ExceptHndlr_BrkTask,最终都会进入bsp.c中的OS_CPU_ExceptHndlr进行实际的处理
;另一个异常处理就是OS_CPU_ARM_ExceptIrqHndlr,进行完堆栈保存等处理后也会进入OS_CPU_ExceptHndlr,该函数位于bsp.c,这里实际只进行了对IRQ的处理,实际的中断函数都是通过这里实现的,自带的注释已经很详细就不细述了.

void  OS_CPU_ExceptHndlr (CPU_INT32U  except_id)
{
    CPU_FNCT_VOID  pfnct;


    if (except_id == OS_CPU_ARM_EXCEPT_IRQ) {

        pfnct = (CPU_FNCT_VOID)VICVectAddr;          /* Read the interrupt vector from the VIC  */
        while (pfnct != (CPU_FNCT_VOID)0) {             /* Make sure we don't have a NULL pointer  */
          (*pfnct)();                                             /* Execute the ISR for the interrupting device */
            VICVectAddr = 1;                                        /* Acknowlege the VIC interrupt */
            pfnct = (CPU_FNCT_VOID)VICVectAddr;     /* Read the interrupt vector from the VIC */
        }

    } else {

                                                    /* Infinite loop on other exceptions.  */
                                                    /* Should be replaced by other behavior (reboot, etc.)  */
        while (DEF_TRUE) {
            ;
        }
    }
}

 

发表于 @ 2009年08月25日

posted on 2010-03-19 15:26  shevsten  阅读(726)  评论(0编辑  收藏  举报