现在的位置: 首页 > 综合 > 正文

uC/OS-II源码分析(总体思路一)(

2014年11月09日 ⁄ 综合 ⁄ 共 5076字 ⁄ 字号 评论关闭

 

首先从main函数开始,下面是uC/OS-II main函数的大致流程:

main(){

 OSInit();

 TaskCreate(...);

 OSStart();

}

首先是调用OSInit进行初始化,然后使用TaskCreate创建几个进程/Task,最后调用OSStart,操作系统就开始运行了。

 

OSInit

 

最先看看OSInit完成哪些初始化:

void  OSInit (void)

{

#if OS_VERSION >= 204

    OSInitHookBegin();                                          

#endif

    OS_InitMisc();                                              

    OS_InitRdyList();                                           

    OS_InitTCBList();                                           

    OS_InitEventList();                                         

#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)

    OS_FlagInit();                                              

#endif

#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)

    OS_MemInit();                                               

#endif

#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)

    OS_QInit();                                                 

#endif

    OS_InitTaskIdle();                                          

#if OS_TASK_STAT_EN > 0

    OS_InitTaskStat();                                          

#endif

#if OS_VERSION >= 204

    OSInitHookEnd();                                            

#endif

#if OS_VERSION >= 270 && OS_DEBUG_EN > 0

    OSDebugInit();

#endif

}

OS_InitMisc()完成的是一些其其他他的变量的初始化:

    OSIntNesting  = 0;                                    

    OSLockNesting = 0;                                    

    OSTaskCtr     = 0;                                    

    OSRunning     = FALSE;                                

   

    OSCtxSwCtr    = 0;                                    

    OSIdleCtr     = 0L;                                   

其中包括:中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS标志OSRunning等。OSRunning在这里设置为FALSE,在后面OSStartHighRdy中会被设置为TRUE表示OS开始工作。

OS_InitRdyList()初始化就绪Task列表:

static  void  OS_InitRdyList (void)

{

    INT8U    i;

    INT8U   *prdytbl;

    OSRdyGrp      = 0x00;                                 

    prdytbl       = &OSRdyTbl[0];

    for (i = 0; i < OS_RDY_TBL_SIZE; i++) {

        *prdytbl++ = 0x00;

    }

    OSPrioCur     = 0;

    OSPrioHighRdy = 0;

    OSTCBHighRdy  = (OS_TCB *)0;                                

    OSTCBCur      = (OS_TCB *)0;

}

首先将OSRdyTbl[]数组中全部初始化0,同时将OSPrioCur/OSTCBCur初始化为0,OSPrioHighRdy/OSTCBHighRdy也初始化为0,这几个变量将在第一个OSSchedule中被赋予正确的值。

OS_InitTCBList()这个函数看名称我们就知道是初始化TCB列表。

static  void  OS_InitTCBList (void)

{

    INT8U    i;

    OS_TCB  *ptcb1;

    OS_TCB  *ptcb2;

    OS_MemClr((INT8U *)&OSTCBTbl[0],     sizeof(OSTCBTbl));     

    OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); 

    ptcb1 = &OSTCBTbl[0];

    ptcb2 = &OSTCBTbl[1];

    for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { 

        ptcb1->OSTCBNext = ptcb2;

#if OS_TASK_NAME_SIZE > 1

        ptcb1->OSTCBTaskName[0] = '?';                          

        ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;

#endif

        ptcb1++;

        ptcb2++;

    }

    ptcb1->OSTCBNext = (OS_TCB *)0;                             

#if OS_TASK_NAME_SIZE > 1

    ptcb1->OSTCBTaskName[0] = '?';                              

    ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;

#endif

    OSTCBList               = (OS_TCB *)0;                      

    OSTCBFreeList           = &OSTCBTbl[0];

}

这里完成的工作很简单,首先把整个数组使用OSTCBNext指针连接成链表链起来,然后将OSTCBList初始化为0,也就是还没有TCB,因为还没有Task产生,OSTCBFreeList指向OSTCBTbl[]数组的第一个表示所有TCB都处于Free状态。

OS_InitEventList()初始化Event列表。

static  void  OS_InitEventList (void)

{

#if OS_EVENT_EN && (OS_MAX_EVENTS > 0)

#if (OS_MAX_EVENTS > 1)

    INT16U     i;

    OS_EVENT  *pevent1;

    OS_EVENT  *pevent2;

    OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl));

    pevent1 = &OSEventTbl[0];

    pevent2 = &OSEventTbl[1];

    for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {            

        pevent1->OSEventType    = OS_EVENT_TYPE_UNUSED;

        pevent1->OSEventPtr     = pevent2;

#if OS_EVENT_NAME_SIZE > 1

        pevent1->OSEventName[0] = '?';                     

        pevent1->OSEventName[1] = OS_ASCII_NUL;

#endif

        pevent1++;

        pevent2++;

    }

    pevent1->OSEventType            = OS_EVENT_TYPE_UNUSED;

    pevent1->OSEventPtr             = (OS_EVENT *)0;

#if OS_EVENT_NAME_SIZE > 1

    pevent1->OSEventName[0]         = '?';                 

    pevent1->OSEventName[1]         = OS_ASCII_NUL;

#endif

    OSEventFreeList                 = &OSEventTbl[0];

#else

    OSEventFreeList                 = &OSEventTbl[0];      

    OSEventFreeList->OSEventType    = OS_EVENT_TYPE_UNUSED;

    OSEventFreeList->OSEventPtr     = (OS_EVENT *)0;

#if OS_EVENT_NAME_SIZE > 1

    OSEventFreeList->OSEventName[0] = '?';                 

    OSEventFreeList->OSEventName[1] = OS_ASCII_NUL;

#endif

#endif

#endif

}

同样将EventTbl[]数组中的OSEventType都初始化为OS_EVENT_TYPE_UNUSED。

OS_InitTaskIdle(),中间我们跳过其他的如Mem等的初始化,看看Idle Task的初始化。

    (void)OSTaskCreateExt(OS_TaskIdle,

                          (void *)0,                                

                          &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],

                          OS_IDLE_PRIO,                             

                          OS_TASK_IDLE_ID,

                          &OSTaskIdleStk[0],                        

                          OS_TASK_IDLE_STK_SIZE,

                          (void *)0,                                

                          OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

其实Idle Task的初始化很简单就是调用OSTaskCrete系列的函数创建一个Task, OSTaskCreate我们后面再做进一步分析。

初始化State Task也是类似调用OSTaskCreate系列函数创建Stat Task。这里只是创建了该Task的各个结构还没有真正运行该Task,直到OSStart中才依据优先级调度运行。

OK,到这里OSInit算高一个段落了,我们接着回到main往下看。

抱歉!评论已关闭.