|
對于TCB控制塊我的理解是:
任務控制塊是記錄任務的優先級,狀態,堆棧指針等參數的一個鏈表,這個鏈表分為兩部分,一個叫做空閑鏈表,一個叫做當前任務鏈表,空閑鏈表是人物創建的時候去申請,得到后設置參數,設置完了就把這個鏈表加載到當前鏈表中,下面看看任務建立的時候是怎么做的!!
、、部分代碼,不相關的略去
psp = (void DT_XDATA *)OSTaskStkInit(task, ppdata, ptos, 0); /* Initialize the task's stack
err = OSTCBInit(prio, psp, (void DT_XDATA *)0, 0, 0, (void DT_XDATA *)0, 0);
第一個是用來獲得任務堆棧的基地址,任務堆棧這個東西,在開始的時候就建好了,其實就是個大數組,每個任務都有一個,當任務切換時這個數組用來存CPU相關的寄存器,比如累加器和8個寄存器,返回指針,任務的切換說白了就是人為的模仿了一次軟件中斷,
第二個用來獲取任務的TCB控制塊,并加載到當前任務控制塊列表,
主要看第二個函數,第一個就是對堆棧的一個分配,決定那個字節些什么,初始化,關鍵是第二個TCB的創建
程序如下:
OS_TCB DT_XDATA * ptcb;//定義一個TCB的結構指針
OS_ENTER_CRITICAL();//進入臨界代碼區
/* Get a free TCB from the free TCB list */
ptcb = OSTCBFreeList; //獲取一個空的TCB塊給PTCB
//判斷TCB是否用完?用完了返回錯誤70
if (ptcb != (OS_TCB DT_XDATA *)0) {
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
OS_EXIT_CRITICAL();//開中斷
ptcb->OSTCBStkPtr = ptos;//任務堆棧指針寫入 /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = (INT8U)prio; //任務優先級 /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY;//任務狀態這個表示準備好了 /* Task is ready to run */
ptcb->OSTCBDly = 0; //任務延時 /* Task is not delayed */
/* Pre-compute X, Y, BitX and BitY */
//把優先級分解,計算出在就緒表中的位置
ptcb->OSTCBY = prio >> 3;
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = prio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
OS_ENTER_CRITICAL();
/* OSTCBPrioTbl */
OSTCBPrioTbl[prio] = ptcb; //寫入OSTCBPrioTbl數組中對應的優先級的TCB指針地址
/* Link into TCB chain. insert to the first of chain */
ptcb->OSTCBNext = OSTCBList; //裝載下一個鏈表地址
ptcb->OSTCBPrev = (OS_TCB DT_XDATA *)0; //裝載先前指針
//如果 OSTCBList不為0 那么上一個指針就是當前的ptcb
if (OSTCBList != (OS_TCB DT_XDATA *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
//優先級寫入就緒表
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
這里面的就是TCB的創建!大體上分為以下幾個部分:
1,申請空鏈表
2.對申請到的空鏈表進行初始化,
3加載空鏈表到當前鏈表
4釋放下一個鏈表的位置,
這里又有4個結構指針是核心分別是
OS_TCB DT_XDATA * ptcb
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBFreeList;
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBList;
OS_EXT OS_TCB DT_XDATA * DT_XDATA OSTCBPrioTbl[OS_LOWEST_PRIO + 1];
第一個是中間指針變量,第二個是空鏈表,第三個是當前TCB表,第四個是對應優先級的TCB表位置
對他們的操作如下:
第一歩:
ptcb = OSTCBFreeList;
表示把指向空閑鏈表指針的地址給PTCB這個中間人
第二部:
ptcb->OSTCBStkPtr = ptos;//任務堆棧指針寫入 /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = (INT8U)prio; //任務優先級 /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY;//任務狀態這個表示準備好了 /* Task is ready to run */
ptcb->OSTCBDly = 0;
表示對空閑鏈表初始化操作
第三部:
OSTCBPrioTbl[prio] = ptcb;
表示把申請到的當前TCB控制塊的地址放到優先級里這樣使得優先級和對應的TCB對應起來,比如優先級是20,那么他就在20那個結構數組里
存入優先級為20的任務TCB控制塊,
第四部:
ptcb->OSTCBNext = OSTCBList;
ptcb->OSTCBPrev = (OS_TCB DT_XDATA *)0;
if (OSTCBList != (OS_TCB DT_XDATA *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
這一步表示下一個鏈表的地址是OSTCBList當前地址
并且吧當前申請到的TCB表寫回到當前鏈表中,這是個加載,而上一個是釋放
最后加載到入任務就緒表中就OK樂!!!!
|
|