这里涉及到了两个函数:
OSTaskStkInit()在os_cpu_c.c文件中
/* ********************************************************************************************************* * INITIALIZE A TASK'S STACK(初始化一个任务堆栈) * * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the * stack frame of the task being created. This function is highly processor specific. *(这个函数既可以被OSTaskCreate()调用也可以被OSTaskCreateExt()调用,来在任务被创建之前初始化堆栈,这个函数高度依赖于处理器) * Arguments : task Pointer to the task code. * //任务代码的指针 * p_arg Pointer to a user supplied data area that will be passed to the task * when the task first executes. * //指向用户提供的数据区域的指针,该数据区域将在任务首次执行时传递给任务。 * ptos Pointer to the top of stack. It is assumed that 'ptos' points to the * highest valid address on the stack. * //指向任务堆栈的栈顶,假设‘ptos’指向了堆栈有效地址的最高地址 * opt Options used to alter the behavior of OSTaskStkInit(). * (see uCOS_II.H for OS_TASK_OPT_???). * //用来修改OSTaskStkInit()的行为 * Returns : Always returns the location of the new top-of-stack' once the processor registers have * been placed on the stack in the proper order. * //只要以正确的顺序将处理器寄存器放置在堆栈上,就始终返回新堆栈顶部的位置。 ********************************************************************************************************* */ OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) { OS_TASK_STK *p_stk; /* Load stack pointer */ p_stk = (OS_TASK_STK *)((char *)ptos - sizeof(OS_TASK_STK)); //因为始终假设ptos指向了栈顶,所以将ptos强转成指向1字节的指针,然后减去任务堆栈的size,使ptos指向堆栈的栈底 //即ptos此时指向了任务堆栈这个结构体的首地址 //OS_STK 为CPU_INT32U(unsigned int)类型,因为这个源代码是适配win32的,所以此时可以认为ptos仅仅是指向unsigned int类型的指针,最后强转成了OS_TASK_STK 类型 p_stk->TaskArgPtr = p_arg; p_stk->TaskOpt = opt; p_stk->Task = task; p_stk->ThreadHandle = NULL; p_stk->ThreadID = 0u; p_stk->TaskState = STATE_NONE; p_stk->SignalPtr = NULL; p_stk->InitSignalPtr = NULL; p_stk->Terminate = DEF_FALSE; p_stk->OSTCBPtr = NULL; return ((OS_STK *)p_stk); //虽然指针各种强转,但是指针真正指向的地址是不会变的,因为指针始终是4个字节,强转类型,只不过决定了指针在读取内容的时候一次读取的字节数 }OS_TCBInit()在os_core.c文件中
/* ********************************************************************************************************* * INITIALIZE TCB(初始化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()). *(此函数是uC/OS-II的内部函数,当一个任务被创建的时候用来初始化TCB) * 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. * //是指向任务堆栈顶部的指针,假设已将CPU寄存器放置在堆栈中。 请注意,栈顶对应于OS_STK_GROWTH设置为1的“高”内存位置,如果OS_STK_GROWTH设置为0则对应的“低”内存位置。请注意,栈增长是特定于CPU的。 * pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by * 'OSTaskCreate()'. * //是指向任务堆栈栈底的指针,当使用OSTaskCreate()的时候传递的是空值 * id is the task's ID (0..65535) * //是此任务的ID * 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()'. * //是堆栈的大小,(是以堆栈单元来说的)如果堆栈单元是INT8U的话,那么这个堆栈就包含了stk_size个字节,如果堆栈单元是INT32U的话,那么堆栈的大小就是4*stk_size个字节大小,堆栈单元由#define常数OS_STK建立,该常数特定于CPU。如果使用OSTaskCreate()来创建任务,那么这个参数为0 * 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(). * //是用户提供的指向内存区域的指针,用来扩展TCB,这个地方允许你存储浮点寄存器的内容,MMU寄存器的内容,或者任何你认为在上下文切换的时候有用的东西。你甚至可以为每个任务取一个名字,然后用这个扩展块来存储这个名字。在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. * //没有额外的TCB * Note : This function is INTERNAL to uC/OS-II and your application should not call it. * //这个函数是uC/OS-II的内部函数,你的应用程序不能够调用它 ********************************************************************************************************* */ 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 == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #if OS_TASK_REG_TBL_SIZE > 0u INT8U i; #endif #if OS_TASK_CREATE_EXT_EN > 0u //是否允许使用扩展块 #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) INT8U j; #endif #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 */ 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 = 0u; /* Task is not delayed */ #if OS_TASK_CREATE_EXT_EN > 0u 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 > 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); //是否允许使用事件 #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 //是否允许使用任务名字 #if OS_TASK_NAME_EN > 0u ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; #endif #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); //TCB初始化完毕后的钩子函数 OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = ptcb;//设置优先级列表 OS_EXIT_CRITICAL(); OSTaskCreateHook(ptcb); /* Call user defined hook */ //任务创建完成后的钩子函数 #if OS_TASK_CREATE_EXT_EN > 0u #if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) for (j = 0u; j < OS_TLS_TBL_SIZE; j++) { ptcb->OSTCBTLSTbl[j] = (OS_TLS)0; } OS_TLS_TaskCreate(ptcb); /* Call TLS hook */ #endif #endif OS_ENTER_CRITICAL(); //插入到就绪链表,就绪链表为双向链表,ucos中所有的链表操作都是从表头进行插入 ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ 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 */ //任务数加一 OS_TRACE_TASK_READY(ptcb); OS_EXIT_CRITICAL(); return (OS_ERR_NONE); } OS_EXIT_CRITICAL(); return (OS_ERR_TASK_NO_MORE_TCB); }