/*
*********************************************************************************************************
* INITIALIZE TCB
*
* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when
* a task is created (see OSTaskCreate() and OSTaskCreateExt()).
*
* Arguments : prio is the priority of the task being created
*
* ptos is a pointer to the task's top-of-stack assuming that the CPU registers
* have been placed on the stack. Note that the top-of-stack corresponds to a
* 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory
* location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU
* specific.
*
* pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by
* 'OSTaskCreate()'.
*
* id is the task's ID (0..65535)
*
* stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us
* then, 'stk_size' contains the number of bytes for the stack. If the stack
* units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack
* units are established by the #define constant OS_STK which is CPU
* specific. 'stk_size' is 0 if called by 'OSTaskCreate()'.
*
* pext is a pointer to a user supplied memory area that is used to extend the task
* control block. This allows you to store the contents of floating-point
* registers, MMU registers or anything else you could find useful during a
* context switch. You can even assign a name to each task and store this name
* in this TCB extension. A NULL pointer is passed if called by OSTaskCreate().
*
* opt options as passed to 'OSTaskCreateExt()' or,
* 0 if called from 'OSTaskCreate()'.
*
* Returns : OS_ERR_NONE if the call was successful
* OS_ERR_TASK_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task cannot
* be created.
*
* Note : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
if (ptcb != (OS_TCB *)0) {
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
//空任务链表更新 指向TCB的双向链接的后链接 我认为是FreeList 指向了原本那个TCB块的后面一个TCB块,
//即移除一个TCB给OSTCBList*/
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */
ptcb->OSTCBPrio = prio; /* Load task priority into TCB */
ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
ptcb->OSTCBDly = 0; /* Task is not delayed */
#if OS_TASK_CREATE_EXT_EN > 0
ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */
ptcb->OSTCBStkSize = stk_size; /* Store stack size */
ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */
ptcb->OSTCBOpt = opt; /* Store task options */
ptcb->OSTCBId = id; /* Store task ID */
#else
pext = pext; /* Prevent compiler warning if not used */
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
#endif
#if OS_TASK_DEL_EN > 0
ptcb->OSTCBDelReq = OS_ERR_NONE;
#endif
#if OS_LOWEST_PRIO <= 63
ptcb->OSTCBY = (INT8U)(prio >> 3); /* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBBitY = (INT8U)(1 << ptcb->OSTCBY);
ptcb->OSTCBX = (INT8U)(prio & 0x07);
ptcb->OSTCBBitX = (INT8U)(1 << ptcb->OSTCBX);
#else
ptcb->OSTCBY = (INT8U)((prio >> 4) & 0xFF);/* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBBitY = (INT16U)(1 << ptcb->OSTCBY);
ptcb->OSTCBX = (INT8U)(prio & 0x0F);
ptcb->OSTCBBitX = (INT16U)(1 << ptcb->OSTCBX);
#endif
#if OS_EVENT_EN
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */
#endif
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
ptcb->OSTCBMsg = (void *)0; /* No message received */
#endif
#if OS_TASK_PROFILE_EN > 0
ptcb->OSTCBCtxSwCtr = 0L; /* Initialize profiling variables */
ptcb->OSTCBCyclesStart = 0L;
ptcb->OSTCBCyclesTot = 0L;
ptcb->OSTCBStkBase = (OS_STK *)0;
ptcb->OSTCBStkUsed = 0L;
#endif
#if OS_TASK_NAME_SIZE > 1
ptcb->OSTCBTaskName[0] = '?'; /* Unknown name at task creation */
ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OSTCBInitHook(ptcb);
OSTaskCreateHook(ptcb); /* Call user defined hook */
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb; //见OSTaskCreate的
if (OSTCBPrioTbl[prio] == (OS_TCB *)0)
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */
将OSTCBList指向的那个TCB地址赋给ptcb->OSTCBNext(刚才从FreeList中移除的那个TCB的Next)
//即让下图的1优先级的tcb ->next = 3优先级的tcb
ptcb->OSTCBPrev = (OS_TCB *)0;
//如图prev前指针是指向NULL//0优先级tcb prev = 0
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
//如下图 假如原先OSTCBList指向OSTCBPrio=1的那个TCB,即OSTCBList != (OS_TCB *)0
//让OSTCBList->OSTCBPrev////(OSTCBPrio=1的那个TCB的OSTCBPrev)=刚才从FreeList中移除的那个TCB
}
OSTCBList = ptcb;
// //OSTCBList由原来指向OSTCBPrio=1的那个TCB改为指向OSTCBPrio=3的那个TCB
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NO_MORE_TCB);
}
OS_EXT OS_TCB *OSTCBCur; /* Pointer to currently running TCB */
OS_EXT OS_TCB *OSTCBFreeList; /* Pointer to list of free TCBs */
OS_EXT OS_TCB *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R */
OS_EXT OS_TCB *OSTCBList; /* Pointer to doubly linked list of TCBs */
OS_EXT OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1];/* Table of pointers to created TCBs */
OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs */