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中才依據優先級調度運行。
OK,到這里OSInit算高一個段落了,我們接著回到main往下看。
總結
以上是生活随笔為你收集整理的uC/OS-II源码分析(总体思路一)(的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汽水音乐怎么看历史播放
- 下一篇: uC/OS-II源码分析(总体思路 二)