先上流程图
A/B分别代表OS_EXIT_CRITICAL() OS_ENTER_CRITICAL()
然后可能会问,最后的 OS_EXIT_CRITICAL(), 为什么会对应A1/A2呢
于是,上源码,微长,分段上
1 INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt) 2 { 3 OS_TCB *ptcb; 4 #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ 5 OS_CPU_SR cpu_sr = 0; 6 #endif 7 8 9 10 OS_ENTER_CRITICAL(); 11 ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */ 12 if (ptcb != (OS_TCB *)0) { 13 OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */ 14 OS_EXIT_CRITICAL();
这里可以看到A1和B1(如果ptcb不是指向NULL的话),但如果ptcb指向NULL呢?
另外,说一句,我只是为了方便分析把这个函数分尸了……其实这个if后面的内容才刚刚开始……
keep going!
1 ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */ 2 ptcb->OSTCBPrio = prio; /* Load task priority into TCB */ 3 ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */ 4 ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ 5 ptcb->OSTCBDly = 0; /* Task is not delayed */ 6 7 #if OS_TASK_CREATE_EXT_EN > 0 8 ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */ 9 ptcb->OSTCBStkSize = stk_size; /* Store stack size */ 10 ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */ 11 ptcb->OSTCBOpt = opt; /* Store task options */ 12 ptcb->OSTCBId = id; /* Store task ID */ 13 #else 14 pext = pext; /* Prevent compiler warning if not used */ 15 stk_size = stk_size; 16 pbos = pbos; 17 opt = opt; 18 id = id; 19 #endif 20 21 #if OS_TASK_DEL_EN > 0 22 ptcb->OSTCBDelReq = OS_ERR_NONE; 23 #endif 24 25 #if OS_LOWEST_PRIO <= 63 26 ptcb->OSTCBY = (INT8U)(prio >> 3); /* Pre-compute X, Y, BitX and BitY */ 27 ptcb->OSTCBX = (INT8U)(prio & 0x07); 28 ptcb->OSTCBBitY = (INT8U)(1 << ptcb->OSTCBY); 29 ptcb->OSTCBBitX = (INT8U)(1 << ptcb->OSTCBX); 30 #else 31 ptcb->OSTCBY = (INT8U)((prio >> 4) & 0xFF); /* Pre-compute X, Y, BitX and BitY */ 32 ptcb->OSTCBX = (INT8U) (prio & 0x0F); 33 ptcb->OSTCBBitY = (INT16U)(1 << ptcb->OSTCBY); 34 ptcb->OSTCBBitX = (INT16U)(1 << ptcb->OSTCBX); 35 #endif
第二块代码即是流程图所说的,设置TCB中的各个域(现在想先弄清结构问题,暂不具体分析是哪些域)。
1 #if (OS_EVENT_EN) 2 ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */ 3 #if (OS_EVENT_MULTI_EN > 0) 4 ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events */ 5 #endif 6 #endif 7 8 #if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0) 9 ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */ 10 #endif 11 12 #if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) 13 ptcb->OSTCBMsg = (void *)0; /* No message received */ 14 #endif 15 16 #if OS_TASK_PROFILE_EN > 0 17 ptcb->OSTCBCtxSwCtr = 0L; /* Initialize profiling variables */ 18 ptcb->OSTCBCyclesStart = 0L; 19 ptcb->OSTCBCyclesTot = 0L; 20 ptcb->OSTCBStkBase = (OS_STK *)0; 21 ptcb->OSTCBStkUsed = 0L; 22 #endif 23 24 #if OS_TASK_NAME_SIZE > 1 25 ptcb->OSTCBTaskName[0] = '?'; /* Unknown name at task creation */ 26 ptcb->OSTCBTaskName[1] = OS_ASCII_NUL; 27 #endif
这一块是关于事件操作的代码,在后面的章节里会提到,这里无视。
1 OSTCBInitHook(ptcb); 2 3 OSTaskCreateHook(ptcb); /* Call user defined hook */
神奇的hook()函数,钩子函数,书上说与windows的钩子函数性质相同,但我没学过win下的编程;
1 OS_ENTER_CRITICAL(); 2 OSTCBPrioTbl[prio] = ptcb; 3 ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ 4 ptcb->OSTCBPrev = (OS_TCB *)0; 5 if (OSTCBList != (OS_TCB *)0) { 6 OSTCBList->OSTCBPrev = ptcb; 7 } 8 OSTCBList = ptcb; 9 OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ 10 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; 11 OSTaskCtr++; /* Increment the #tasks counter */ 12 OS_EXIT_CRITICAL(); 13 return (OS_ERR_NONE); 14 } 15 OS_EXIT_CRITICAL(); 16 return (OS_ERR_TASK_NO_MORE_TCB); 17 }
这是这个函数的最后一块内容
可以看到A2和B2内包着设置任务优先级指针表和设置就绪表和就绪组的代码;
最后还有一个OS_EXIT_CRITICAL(),就是对应A1的_ENTER_;
也许我的流程图有点歧义,但没准这样记得更清楚= =?
至此这个任务控制块的初始函数已经拆分完毕。