OS_TCBInit是创建任务函数OSTaskCreateExt时调用的一个函数。"OS_TCBInit"时与系统内核紧密相关的一个函数。
OS_TCBInit和OS_InitTCBList区别:OS_InitTCBList主要是初始化TCB链表。"OS_InitTCBList"函数体内容相当于将TCB链表复位。
OS_TCBInit是在创建任务时初始化一个任务的TCB,要将优先级、堆栈等信息初始化。"OS_TCBInit"函数体内容相当于对任务的TCB里面对应的内容落实到具体的参数上。
OS_TCBInit(void)函数位于os_core.c文件的第1917行。
INT8U OS_TCBInit (INT8U prio,
OS_STK *ptos,
OS_STK *pbos,
INT16U id,
INT32U stk_size,
void *pext,
INT16U opt)
1.第一个参数prio 任务的优先级。
这个参数是从"OSTaskCreateExt"函数参数中传递下来的。
2.第二个参数ptos 指向栈顶的指针。
创建任务中利用"OSTaskStkInit"初始化堆栈得到栈顶的指针psp,将该指针传递给OS_TCBInit函数的参数。
这个参数和pbos一样 根据栈的增长方向" OS_STK_GROWTH "来决定。
3.第三个参数pbos 指向栈底的指针
4.第四个参数id 任务ID号
5.第五个参数stk_size
堆栈大小,就是分配堆栈空间(定义堆栈数组)的大小。
6.第六个参数pext
pext指向用户提供的内存(指针)。
7.第七个参数opt
用户操作选项参数
"OS_TCBInit"函数的参数基本是继承"OSTaskCreateExt"函数的参数。从这里可以看出"OS_TCBInit"函数才是创建任务的重要函数。
OS_TCBInit函数体内容详解
OS_TCBInit的参数其实传递进来的参数保存在TCB链表中用于保存一个任务重要的信息,具体如下:
OS_ENTER_CRITICAL(); //进临界区(关中断)
ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list获取空TCB指针*/
if (ptcb != (OS_TCB *)0) { //如果缓冲区有空余TCB,这个TCB将被初始化
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list更新空TCB列表指针(指向下一空TCB)*/
OS_EXIT_CRITICAL(); //出临界区(开中断)
ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB当前PTCB栈顶的指针(输入)*/
ptcb->OSTCBPrio = prio; /* Load task priority into TCB往TCB装入任务优先级(输入)*/
ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run任务准备好运行(就绪态)*/
ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status 清除PEND状态*/
ptcb->OSTCBDly = 0u; /* Task is not delayed任务不延时*/
#if OS_TASK_CREATE_EXT_EN > 0u //若创建任务扩展功能
ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension存储TCB扩展指针*/
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存储任务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 > 0u //若允许删除任务
ptcb->OSTCBDelReq = OS_ERR_NONE;
#endif
#if OS_LOWEST_PRIO <= 63u /* Pre-compute X, Y 预处理任务优先级 */
ptcb->OSTCBY = (INT8U)(prio >> 3u);
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
#else /* Pre-compute X, Y */
ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu);
ptcb->OSTCBX = (INT8U) (prio & 0x0Fu);
#endif
/* Pre-compute BitX and BitY */
ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
(1)链表节点及参数
OSTCBFreeList是当前空闲TCB链表,相当于每初始化一个任务就要将OSTCBFreeList指向下一个没有使用的Freelist,保证每次创建任务的时候有OSTCBFreeList可用。
if (ptcb != (OS_TCB *)0) 这个条件就是判断还有没有空闲TCB链表,如果没有空闲TCB链表就返回"错误"。
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list更新空TCB列表指针(指向下一空TCB链表)*/
下面就是其他参数赋值(堆栈、优先级、任务状态就绪等)。
(2)任务参数
这里的任务参数是传递过来的参数信息,归为到对应的空间,也就是参数赋值。
ptcb->OSTCBDelReq = OS_ERR_NONE; 任务可以删除(当使能了删除任务功能,在创建任务之后就可以删除创建的任务)。
#if (OS_EVENT_EN)
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event将事件控制块指向空*/
#if (OS_EVENT_MULTI_EN > 0u)
ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events将任务多事件控制块指向空*/
#endif
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag将事件标志节点指向空*/
#endif
#if (OS_MBOX_EN > 0u) || ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))
ptcb->OSTCBMsg = (void *)0; /* No message received 将消息指向空*/
#endif
#if OS_TASK_PROFILE_EN > 0u
ptcb->OSTCBCtxSwCtr = 0uL; /* Initialize profiling variables初始化(性能分析)变量*/
ptcb->OSTCBCyclesStart = 0uL;
ptcb->OSTCBCyclesTot = 0uL;
ptcb->OSTCBStkBase = (OS_STK *)0;
ptcb->OSTCBStkUsed = 0uL;
#endif
(1)优先级
UCOS优先级实现其功能具体的部分使用了"优先级表",查找优先级的算法为ucos优先级调度算法。
(2)事件
需要结合事件(信号量、消息邮箱等)分析。
(3)性能分析参数
"性能分析"就是对系统运行的性能,CPU使用率等分析。OS_TaskIdle空闲任务时 函数体中有一条语句:OSIdleCtr++;也就是统计空闲任务的计数次数。
3.
#if OS_TASK_REG_TBL_SIZE > 0u /* Initialize the task variables初始化任务变量*/
for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) {
ptcb->OSTCBRegTbl[i] = 0u;
}
#endif
OSTCBInitHook(ptcb);
OSTaskCreateHook(ptcb); /* Call user defined hook */
OS_ENTER_CRITICAL(); //进临界区(关中断)
OSTCBPrioTbl[prio] = ptcb; /*更新TCB优先级列表*/
ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain调用用户定义的HOOK函数*/
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0) { //如果不是首次创建任务
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run使任务进入"就绪"状态*/
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++; /* Increment the #tasks counter任务计数器+1*/
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NO_MORE_TCB);
}
上部分的"准备"工作完成之后,就剩下"就绪"工作了。
OSTCBInitHook(ptcb) 和 OSTaskCreateHook(ptcb); 这两个函数一般成对出现,是用户自己的HOOK函数,用户自己要实现某些功能就写在这里。
OSTCBPrioTbl[prio] = ptcb; /*更新TCB优先级列表*/ 这条语句将该任务在TCB表中有一个对应的位置。
ptcb->OSTCBNext = OSTCBList; 指向TCB链表。
OSTaskCtr++; 任务也有一个统计计数的变量。