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

首先从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中才依据优先级调度运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值