?? ucos-ii源碼分析.c
字號:
uC/OS-II源碼分析
在這里我不想分模塊來慢慢分析這個OS的行為,我們從CPU的執行順序來看吧,這樣也許清晰一些,并且我們暫時拋棄那些Event/MailBox、信號量等元素,還是先看看作為一個OS核心的Task Schedule部分內容吧。
首先從main函數開始,下面是uC/OS-II main函數的大致流程:
main(){
OSInit();
TaskCreate(...);
OSStart();
}
首先是調用OSInit進行初始化,然后使用TaskCreate創建幾個進程/Task,最后調用OSStart,操作系統就開始運行了。
OSInit
最先看看OSInit完成哪些初始化:
void OSInit (void)
{
#if OS_VERSION >= 204
OSInitHookBegin(); /* Call port specific initialization code */
#endif
OS_InitMisc(); /* Initialize miscellaneous variables */
OS_InitRdyList(); /* Initialize the Ready List */
OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
OS_InitEventList(); /* Initialize the free list of OS_EVENTs */
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FlagInit(); /* Initialize the event flag structures */
#endif
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
OS_MemInit(); /* Initialize the memory manager */
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
OS_QInit(); /* Initialize the message queue structures */
#endif
OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0
OS_InitTaskStat(); /* Create the Statistic Task */
#endif
#if OS_VERSION >= 204
OSInitHookEnd(); /* Call port specific init. code */
#endif
#if OS_VERSION >= 270 && OS_DEBUG_EN > 0
OSDebugInit();
#endif
}
OS_InitMisc()完成的是一些其其他他的變量的初始化:
OSIntNesting = 0; /* Clear the interrupt nesting counter */
OSLockNesting = 0; /* Clear the scheduling lock counter */
OSTaskCtr = 0; /* Clear the number of tasks */
OSRunning = FALSE; /* Indicate that multitasking not started */
OSCtxSwCtr = 0; /* Clear the context switch counter */
OSIdleCtr = 0L; /* Clear the 32-bit idle counter */
其中包括:中斷嵌套標志OSIntNesting,調度鎖定標志OSLockNesting,OS標志OSRunning等。OSRunning在這里設置為FALSE,在后面OSStartHighRdy中會被設置為TRUE表示OS開始工作。
OS_InitRdyList()初始化就緒Task列表:
static void OS_InitRdyList (void)
{
INT8U i;
INT8U *prdytbl;
OSRdyGrp = 0x00; /* Clear the ready list */
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)); /* Clear all the TCBs */
OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */
ptcb1 = &OSTCBTbl[0];
ptcb2 = &OSTCBTbl[1];
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */
ptcb1->OSTCBNext = ptcb2;
#if OS_TASK_NAME_SIZE > 1
ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
ptcb1++;
ptcb2++;
}
ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */
#if OS_TASK_NAME_SIZE > 1
ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OSTCBList = (OS_TCB *)0; /* TCB lists initializations */
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)); /* Clear the event table */
pevent1 = &OSEventTbl[0];
pevent2 = &OSEventTbl[1];
for (i = 0; i < (OS_MAX_EVENTS - 1); i++) { /* Init. list of free EVENT control blocks */
pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent1->OSEventPtr = pevent2;
#if OS_EVENT_NAME_SIZE > 1
pevent1->OSEventName[0] = '?'; /* Unknown name */
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]; /* Only have ONE event control block */
OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED;
OSEventFreeList->OSEventPtr = (OS_EVENT *)0;
#if OS_EVENT_NAME_SIZE > 1
OSEventFreeList->OSEventName[0] = '?'; /* Unknown name */
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, /* No arguments passed to OS_TaskIdle() */
&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack */
OS_IDLE_PRIO, /* Lowest priority level */
OS_TASK_IDLE_ID,
&OSTaskIdleStk[0], /* Set Bottom-Of-Stack */
OS_TASK_IDLE_STK_SIZE,
(void *)0, /* No TCB extension */
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */
其實Idle Task的初始化很簡單就是調用OSTaskCrete系列的函數創建一個Task, OSTaskCreate我們后面再做進一步分析。
初始化State Task也是類似調用OSTaskCreate系列函數創建Stat Task。這里只是創建了該Task的各個結構還沒有真正運行該Task,直到OSStart中才依據優先級調度運行。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -