uc/os中OSStart()函数分析

OSStart()函数分析

多任务的的启动是通过调用OSStart()实现的,而在启动uc/os之前至少需要建立一个应用任务。

OSStart()函数源码

void  OSStart (void)

{

    INT8U y;

    INT8U x;

    if (OSRunning == FALSE) {//参数检验,多任务尚未启动

        y             = OSUnMapTbl[OSRdyGrp];//这几句通过uc/os设定最高优先级查找算法找出当前最高优先级    

        x             = OSUnMapTbl[OSRdyTbl[y]];

        OSPrioHighRdy = (INT8U)((y << 3) + x);

        OSPrioCur     = OSPrioHighRdy;//第一次开始多任务调度,最高优先级任务运行,即当前优先级和最高优先级一样

        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; //通过最高优先级超找优先级TCB表获得最高优先级TCB

        OSTCBCur      = OSTCBHighRdy;//第一次启动,二者一样

        OSStartHighRdy();//调用启动函数,实质上是将任务栈中保存的值弹回到CPU寄存器中,然后执行中断返回自指令,中断返回指令强制执行任务代码

    }

}

Ø  OSStartHighRdy()永远不返回到OSStart()

Ø  OSSTART执行完后OSRunning为真,多任务已经启动

 

OSStartHighRdy()分析

void OSStartHighRdy(void)

{

    _OSStartHighRdy();//该是一个软中断,通过软中断调用来实现多任务的启动

    }

 

_OSStartHighRdy()分析

SoftwareInterrupt

        LDR     SP, StackSvc            //重新设置堆栈指针,此时处理器处于管理模式。此处设置是因为在后面新任务堆栈内容进入CPU寄存器的过程用,用新任务的堆栈指针覆盖了管理模式的指针

        STMFD   SP!, {R0-R3, R12, LR}//保存环境,LR内存放的软中断返回地址。

        MOV     R1, SP                  // R1指向参数存储位置

 

        MRS     R3, SPSR    //获得进入软中断前的CPSR

        TST     R3, #T_bit              //中断前是否是Thumb状态

        LDRNEH  R0, [LR,#-2]            //: 取得Thumb状态SWI

        BICNE   R0, R0, #0xff00

        LDREQ   R0, [LR,#-4]            //: 取得arm状态SWI

        BICEQ   R0, R0, #0xFF000000

                                        //r0 = SWI号,R1指向参数存储位置

        CMP     R0, #1

        LDRLO   PC, =OSIntCtxSw

        LDREQ   PC, =__OSStartHighRdy   //SWI 0x01为第一次任务切换

 

        BL      SWI_Exception

       

        LDMFD   SP!, {R0-R3, R12, PC}^//恢复寄存器

       

StackSvc           DCD     (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)

 

__OSStartHighRdy分析

        MSR     CPSR_c, #(NoInt | SYS32Mode)//进入系统模式

                                                //告诉uC/OS-II自身已经运行OSRunning==1

        LDR     R4, =OSRunning

        MOV     R5, #1

        STRB    R5, [R4]

 

        BL      OSTaskSwHook                    //调用钩子函数

 

        LDR     R6, =OSTCBHighRdy//获得存放最高优先级TCB地址的地址

        LDR     R6, [R6]//获得当前最高优先级TCB地址

        B       OSIntCtxSw_1//任务堆栈内容进入CPU,启动最高优先级任务

 

        AREA    SWIStacks, DATA, NOINIT,ALIGN=2

SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  //管理模式堆栈空间

 

OSIntCtxSw_1分析

 

OSIntCtxSw_1

                                                   

        LDR     R4, [R6] //获取新任务堆栈指针,此时指针指向栈底(压入了数据),此时处理器模式依然是管理模式

        ADD     SP, R4, #17*4 //17寄存器CPSR,OsEnterSum,R0-R12,LR,SP移动任务堆栈的指针,使的SP指向任务堆栈的栈顶(次数数据并未弹出)

        LDR     LR, [SP, #-8]//获得LR_USR,

        MSR     CPSR_c, #(NoInt | SVC32Mode)        //进入管理模式

        MOV     SP, R4        //设置堆栈指针,此处修改了管理模式的指针使得其指向新任务的堆栈栈底,此处修改了管理模式的堆栈指针,故在每一次进入软中断都要从新设置管理模式堆栈指针。

 

        LDMFD   SP!, {R4, R5}                       ;CPSR,OsEnterSum

                                                    ;恢复新任务的OsEnterSum

        LDR     R3, =OsEnterSum

        STR     R4, [R3]

   

        MSR     SPSR_cxsf, R5                       ;恢复CPSR

        LDMFD   SP!, {R0-R12, LR, PC }^             ;//此处LR其实是LR_SVC是没有什么实际作用的,只不过为了方便指针的自动移动而出栈PCLR_USR在前面已经恢复。

Ø  函数分析是基于LPC2200

Ø  任务栈内数据存放数据

 

任务堆栈
任务入栈的其他数据
PC
LR
R12
R11
R10
……
……
R3
R2
R1
R0
CPSR
OSEnterSum
空闲空间

 

 
 

你可能感兴趣的:(UC/OS-II)