OS_CORE.C(11)

OS_SchedNew(void)找到将要运行的最高优先级任务函数

和任务调度函数OS_Sched(void):

/*
*********************************************************************************************************
*                              FIND HIGHEST PRIORITY TASK READY TO RUN
*								找到将要运行的最高优先级任务
* Description: This function is called by other uC/OS-II services to determine the highest priority task
*              that is ready to run.  The global variable 'OSPrioHighRdy' is changed accordingly.
*描述:	该功能被其他服务调用,用来决定将要运行的最高优先级任务是什么。全局变量OSPrioHighRdy相应改变。
* Arguments  : none
*参数:无
* Returns    : none
*返回值:无
* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
*              2) Interrupts are assumed to be disabled when this function is called.
	注释:	1)该功能是内部函数,你的应用程序不能调用。
			2)当这个功能被调用的时候不能被中断(原子函数)
*********************************************************************************************************
*/

static  void  OS_SchedNew(void)				/*找到将要被调度的任务*/
{
#if OS_LOWEST_PRIO <= 63u                   /*优先级<=63,支持64位任务*/
	INT8U   y;

	y = OSUnMapTbl[OSRdyGrp];				
	OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]);/*计算最高优先级任务的优先级*/
#else                                            /* We support up to 256 tasks支持256个任务 */
	INT8U     y;
	OS_PRIO  *ptbl;								/*ptb1是指向事件控制块的指针*/

	if ((OSRdyGrp & 0xFFu) != 0u)				/*如果就绪组不为0*/
	{				
		y = OSUnMapTbl[OSRdyGrp & 0xFFu];		/*y为在表中查到的数*/
	}
	else {
		y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u;/*将y置为8*/
	}
	ptbl = &OSRdyTbl[y];
	if ((*ptbl & 0xFFu) != 0u)					/*计算出优先级*/
	{
		OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]);
	}
	else 
	{
		OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u);
	}
#endif
}

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                              SCHEDULER
*												调度
* Description: This function is called by other uC/OS-II services to determine whether a new, high
*              priority task has been made ready to run.  This function is invoked by TASK level code
*              and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling).
*描述:该功能被其他服务调用,用来决定是否一个新的、高优先级任务已经准备好运行了。任务级的调度是由函数OSSched()完成的。
		中断级的调度是由另一个函数OSIntExt()完成的).
* Arguments  : none
*参数:无
* Returns    : none
*返回值:无
* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
*              2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock())
注释:		1)该功能为内部函数,你的应用程序不能调用
			2) 给调度器上锁用于禁止任务调度 (查看 OSSchedLock()函数)
*********************************************************************************************************
*/

void  OS_Sched(void)				/*任务调度函数*/
{
#if OS_CRITICAL_METHOD == 3u        /*中断函数被设定为模式3*/
	OS_CPU_SR  cpu_sr = 0u;
#endif

	OS_ENTER_CRITICAL();								/*关中断*/
	if (OSIntNesting == 0u) {                          /*如果所有的中断都完成了 */
		if (OSLockNesting == 0u) {                     /* 并且调度器没有被锁 */
			OS_SchedNew();								/*找到要运行的任务*/
			OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];	/*为实现任务切换,OSTCBHighRdy必须指向优先级最高的那个任务控制块OS_TCB,
														这是通过将以OSPrioHighRdy为下标的OSTCBPrioTbl[]数组中的那个元素赋给OSTCBHighRdy来实现的*/
			if (OSPrioHighRdy != OSPrioCur) {          /*找到最高优先级任务后,函数检查这个优先级最高的任务是否是当前正在运行的任务,
													   以避免不必要的任务调度,多花时间*/
				#if OS_TASK_PROFILE_EN > 0u
								OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task      */
				#endif
				OSCtxSwCtr++;                          /*任务切换计数值加1,统计切换次数 */
				OS_TASK_SW();                          /*进行实际的任务交换 */
			}
		}
	}
	OS_EXIT_CRITICAL();								/*开中断*/
}

这两个函数中让人费解的还是计算优先级那一块。回头看了(9)中介绍的有关知识,感觉描述的还是不够清楚。有时间重新梳理一下,尽量描述详尽。

 OS_StrLen(INT8U *psrc)确定一个ASCII字符串的长度的函数:

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                DETERMINE THE LENGTH OF AN ASCII STRING
*									确定一个ASCII字符串的长度
* Description: This function is called by other uC/OS-II services to determine the size of an ASCII string
*              (excluding the NUL character).
*描述:该功能被其他服务调用,用来确定一个ASCII字符串的长度,包括最后的null字符。
* Arguments  : psrc     is a pointer to the string for which we need to know the size.
*参数:					--psrc指向字符串
* Returns    : The size of the string (excluding the NUL terminating character)
*返回值:	返回字符串的大小(包括最后空终止字符)。
* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
*              2) The string to check must be less than 255 characters long.
	注释: 1)该功能是内部函数,你的应用程序不能调用它;
			2)要确定的字符串必须小于255字符。
*********************************************************************************************************
*/

#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) || (OS_TMR_CFG_NAME_EN > 0u)
INT8U  OS_StrLen(INT8U *psrc)
{
	INT8U  len;

	len = 0u;				/*刚开始初始化len为0*/
	while (*psrc != OS_ASCII_NUL) /*字符串没有到结尾*/
	{
		psrc++;				/*指针后移*/
		len++;				/*长度加1*/
	}	
	return (len);			/*返回长度len*/
}
#endif

这个函数不需要多说。


 OS_TaskIdle(void *p_arg)空闲任务函数:

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                              IDLE TASK
*												空闲任务
* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks
*              executes because they are ALL waiting for event(s) to occur.
*描述: 这个函数是uC/OS-II内部函数,uC/OS-II总要建立一个空闲任务,这个任务在没有其它任务进入就绪态时投入运行。
这个空闲任务永远设为最低优先级,即OS_LOWEST_PRIO.空闲任务不可能被应用软件删除。
* Arguments  : none
*参数:无
* Returns    : none
*返回值:无
* Note(s)    : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be
*                 enabled for at least a few instructions.  On some processors (ex. Philips XA), enabling
*                 and then disabling interrupts didn't allow the processor enough time to have interrupts
*                 enabled before they were disabled again.  uC/OS-II would thus never recognize
*                 interrupts.
*              2) This hook has been added to allow you to do such things as STOP the CPU to conserve
*                 power.
	注释:1)OSTaskIdleHook()......(自行百度)
		  2)让CPU执行STOP指令,从而进入低功耗模式,当应用系统由电池供电时,这种方式特别有用。
*********************************************************************************************************
*/

void  OS_TaskIdle(void *p_arg)
{
#if OS_CRITICAL_METHOD == 3u                     /* 中断号设置为3 */
	OS_CPU_SR  cpu_sr = 0u;
#endif

	p_arg = p_arg;                               /*赋值给自己本身,防止编译器出现错误*/
	for (;;) {
		OS_ENTER_CRITICAL();					/*关中断*/
		OSIdleCtr++;							/*空闲任务数量加1*/
		OS_EXIT_CRITICAL();						/*开中断*/
		OSTaskIdleHook();                        /* 调用用户自定义的钩子函数 */
	}
}

空闲任务函数主要是统计空闲任务数量,调用用户自定义的钩子函数。

OS_TaskStatStkChk(void)检查所有的任务堆栈函数:

/*$PAGE*/
/*2018/2/9
*********************************************************************************************************
*                                      CHECK ALL TASK STACKS
*										检查所有的任务堆栈
* Description: This function is called by OS_TaskStat() to check the stacks of each active task.
*描述:该功能被OS_TaskStat()统计任务调用,用来家产每个活跃的任务的堆栈
* Arguments  : none
*参数:无
* Returns    : none
返回值:无
*********************************************************************************************************
*/

#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
void  OS_TaskStatStkChk(void)
{
	OS_TCB      *ptcb;
	OS_STK_DATA  stk_data;
	INT8U        err;
	INT8U        prio;


	for (prio = 0u; prio <= OS_TASK_IDLE_PRIO; prio++) 
	{
		err = OSTaskStkChk(prio, &stk_data);	/*检测任务是否有问题*/
		if (err == OS_ERR_NONE)					/*如果没问题*/
		{
			ptcb = OSTCBPrioTbl[prio];			/*从优先级为0的任务开始检查*/
			if (ptcb != (OS_TCB *)0) 
			{                              
				if (ptcb != OS_TCB_RESERVED)	/*确定任务是有效任务*/
				{                      
					#if OS_TASK_PROFILE_EN > 0u
						#if OS_STK_GROWTH == 1u/*向下增长方式,就是从高地址向低地址增长,栈顶在高地址端。*/
								ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize;/*改变栈底指针位置*/
						#else
								ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize;/*改变栈底指针位置*/
						#endif
						ptcb->OSTCBStkUsed = stk_data.OSUsed;            /* 存储已经使用的字节数*/
					#endif
				}
			}
		}
	}
}
#endif
上面的:

OS_STK_DATA  stk_data;
这个语句中,解释一下OS_STK_DATA结构体,方便大家理解:

/*
*2018/1/30
*********************************************************************************************************
*                                            TASK STACK DATA
*												任务堆栈数据
*********************************************************************************************************
*/

#if OS_TASK_CREATE_EXT_EN > 0u
typedef struct os_stk_data {
    INT32U  OSFree;                    /* Number of free bytes on the stack  堆栈中未使用的字节数                          */
    INT32U  OSUsed;                    /* Number of bytes used on the stack  堆栈中已使用的字节数                          */
} OS_STK_DATA;
#endif

 OS_TaskStat(void *p_arg)统计任务函数:

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                            STATISTICS TASK
*												统计任务
* Description: This task is internal to uC/OS-II and is used to compute some statistics about the
*              multitasking environment.  Specifically, OS_TaskStat() computes the CPU usage.
*              CPU usage is determined by:
*描述:这个任务是uc/os-ii内部任务,并且被用来计算一些关于多任务环境的统计数据。最关键的是用OS_TaskStat()函数计算CPU的使用率
*                                          OSIdleCtr
*                 OSCPUUsage = 100 * (1 - ------------)     (units are in %)
*                                         OSIdleCtrMax
*		cpu的使用率=100*(1-空闲任务数/设定的空闲任务总数)
* Arguments  : parg     this pointer is not used at this time.
*参数:					--parg:这个时候不使用parg
* Returns    : none
*返回值:	无
* Notes      : 1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
*                 next higher priority, OS_TASK_IDLE_PRIO-1.
*              2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
*              3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the
*                 maximum value for the idle counter.
	注释:	1) uC/OS-II已经将空闲任务的优先级设为最低,即OS_LOWEST_PR10,统计任务的优先级设为次低,OS_LOWEST_PR10-1.
			2)你可以通过设置配置禁用该任务 #define OS_TASK_STAT_EN to 0.
			3)你必须有至少0.2s(2个时钟节拍)的延迟来使系统能够为空闲任务计数器设置最大值
*********************************************************************************************************
*/

#if OS_TASK_STAT_EN > 0u
void  OS_TaskStat(void *p_arg)					/*任务统计函数*/
{
#if OS_CRITICAL_METHOD == 3u                   /*将中断类型设置为3*/
	OS_CPU_SR  cpu_sr = 0u;
#endif

	p_arg = p_arg;                             /*自己给自己赋值,防止编译出现错误*/
	while (OSStatRdy == OS_FALSE)				/*如果统计任务状态不是就绪的,通过延迟函数OSTimeDly()等待*/
	{	
		OSTimeDly(2u * OS_TICKS_PER_SEC / 10u);  /* Wait until statistic task is ready*/
	}
	OSIdleCtrMax /= 100uL;						/*将最大空闲计数值对100求整*/
	if (OSIdleCtrMax == 0uL)					/*如果最大空闲计数值为0*/
	{
		OSCPUUsage = 0u;						/*CPU使用率为0*/
		#if OS_TASK_SUSPEND_EN > 0u				/*如果允许任务挂起*/
				(void)OSTaskSuspend(OS_PRIO_SELF);/*调用任务挂起函数(参数为自身的优先级)*/
		#else									/*不允许任务挂起*/
		for (;;) 
		{
			OSTimeDly(OS_TICKS_PER_SEC);		/*就通过延迟函数进行等待*/
		}
		#endif
	}

	for (;;) 
	{
		OS_ENTER_CRITICAL();				/*关中断*/
		OSIdleCtrRun = OSIdleCtr;           /*将此时统计的空闲计数值赋给OSIdleCtrRun这个临时变量*/
		OSIdleCtr = 0uL;                    /*将OSIdleCtr重新设置为0,然后进行下一秒钟的计数*/
		OS_EXIT_CRITICAL();					/*开中断*/
		OSCPUUsage = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);			/*计算CPU的使用率*/
		OSTaskStatHook();                        /*执行用户自定义的钩子函数*/
		#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)
				OS_TaskStatStkChk();                     /*任务堆栈检测*/
		#endif
		OSTimeDly(OS_TICKS_PER_SEC / 10u);       /*调用延迟函数OSTimeDly()将自身延时1个时钟节拍以停止自身的运行*/
	}
}
#endif

在这个函数中想解释一下几点:

1.任务统计函数中最主要的几个语句是:

OSIdleCtrMax /= 100uL;						/*将最大空闲计数值对100求整*/
OSIdleCtrRun = OSIdleCtr;           /*将此时统计的空闲计数值赋给OSIdleCtrRun这个临时变量*/
OSIdleCtr = 0uL;                    /*将OSIdleCtr重新设置为0,然后进行下一秒钟的计数*/
OSCPUUsage = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax);			/*计算CPU的使用率*/

2.在这个函数中:解释一下下面这个语句:

OSIdleCtrMax /= 100uL;						/*将最大空闲计数值对100求整*/

大家可能看到这个语句时和我有着同样的疑问:为什么要对100取整?有什么必要性?

 这里将最大值除以100是为了之后的计算。若是不除100,根据前面提到的公式来的话, OSIdleCtr / OSIdleCtrMax这里我们希望得到的是一个浮点数,也就是一个小于1的小数,但是因为OSIdleCtr、OSIdleCtrMax 都是整数,且OSIdleCtr < OSIdleCtrMax,则两个数相除就必定为0,则OSCPUUsage 始终会等于100。所以先OSIdleCtrMax /100,然后再OSIdleCtrRun / OSIdleCtrMax,这个结果就不会是一个小于0的数,这个时候就不会出现始终等于0的情况 。同时在算数逻辑上100 - OSIdleCtrRun / OSIdleCtrMax=100 -OSIdleCtrRun *100/ OSIdleCtrMax = 100(1 -OSIdleCtrRun / OSIdleCtrMax )。这样计算能够接近数学运算的结果。

3.第三个关于这个函数的疑问是:在for循环最后的一行语句:

OSTimeDly(OS_TICKS_PER_SEC / 10u);       /*调用延迟函数OSTimeDly()将自身延时1个时钟节拍以停止自身的运行*/

我们知道这个语句是延迟函数。但是这里为什么要用呢?

实际上,OSTimeDly()函数可以看作一个延时函数,但是它真正的内涵是将CPU让给其他的任务。将自身的任务延时,在OSTimeDly(Ticks)这段时间内调用OS_Sched()函数找出任务就绪列表中优先级最高的任务并将当前CPU切换到该任务。

关于这个函数就介绍到这里。


OS_TCBInit(INT8U    prio, OS_STK  *ptos,OS_STK  *pbos,INT16U   id,INT32U   stk_size,void    *pext,INT16U   opt)

初始化TCB函数:

/*$PAGE*/
/*2018/2/9
*********************************************************************************************************
*                                            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()).
*描述:该功能是内部函数,当有任务被创建时(详情见OSTaskCreate()函数和OSTaskCreateExt()函数),该函数被用来初始化任务控制块,
* Arguments  : prio          is the priority of the task being created
*参数:						--prio是被创建任务的优先级
*              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.
*							--ptos:假设CPU寄存器被堆栈占用,ptos就是指向栈顶的指针。
								注意:如果内存增长方式被设定为1(从高地址到低地址),那么ptos(栈顶)指向的是高地址;
								相反,如果增长方式被设定为0(从低地址到高地址),那么ptos(栈顶)指向的是低地址。
								具体是什么增长方式取决于不同的CPU
*              pbos          is a pointer to the bottom of stack.  A NULL pointer is passed if called by
*                            'OSTaskCreate()'.
*							--pbos:指向栈底的指针。如果是使用OSTaskCreate()创建任务,pbos被设定为null空。
*              id            is the task's ID (0..65535)
*							--id是栈的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()'.
*							--stk_size:是栈的大小(或者准确讲师栈单元的大小)。
										如果栈单元是8位的,stk_size值得就是8位可以表示的字节大小(2的8次方字节)。
										如果栈单元室32位的,这个栈就有4*stk_size字节这么大。
										栈单元是通过 #define constant OS_STK来定义的。与CPU类型相关
*              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().
*							--pext扩展指针:指向用户可使用的内存单元,该内存单元是为了扩大任务控制块。
										这样可以存储浮点数寄存器、MMU寄存器或者其他在上下文交换时可用的寄存器中的内容。
										甚至可以设定每个任务的名称,并将该名称存储在TCB扩展中。
*              opt           options as passed to 'OSTaskCreateExt()' or,
*                            0 if called from 'OSTaskCreate()'.
*							--opt:如果是OSTaskCreateExt()调用,代表OS_TCB的选择项,如果是OSTaskCreate()调用,opt为0
* 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.
*返回值:OS_ERR_NONE:调用成功返回该值
		OS_ERR_TASK_NO_MORE_TCB:如果没有空闲的TCB了,任务不能被创建,返回该值
* 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;				/*指向TCB的指针*/
#if OS_CRITICAL_METHOD == 3u        /*将中断类型设置为3*/
	OS_CPU_SR  cpu_sr = 0u;
#endif
#if OS_TASK_REG_TBL_SIZE > 0u
	INT8U      i;
#endif

	OS_ENTER_CRITICAL();			/*关中断*/
	ptcb = OSTCBFreeList;           /*ptcb指针指向空闲TCB列表,来获得一个空闲的TCB*/
	if (ptcb != (OS_TCB *)0)		/*如果ptcb不为0,即还有空闲的TCB*/
	{
		OSTCBFreeList = ptcb->OSTCBNext;        /* Update pointer to free TCB list更新一下空闲TCB列表指针(起始指针后移一个)*/
		OS_EXIT_CRITICAL();						/*关中断*/
		ptcb->OSTCBStkPtr = ptos;               /*将栈顶指针存储在ptch中的OSTCBStkPtr */
		ptcb->OSTCBPrio = prio;                 /*将优先级存储在OSTCBPrio中*/
		ptcb->OSTCBStat = OS_STAT_RDY;          /*将TCB的状态设置为就绪态*/
		ptcb->OSTCBStatPend = OS_STAT_PEND_OK;  /* Clear pend status将挂起状态设置为OS_STAT_PEND_OK*/
		ptcb->OSTCBDly = 0u;                     /* Task is not delayed无任务延迟,直接执行*/

		#if OS_TASK_CREATE_EXT_EN > 0u			/*如果创建的是扩展型任务,存储有关的信息*/
				ptcb->OSTCBExtPtr = pext;       
				ptcb->OSTCBStkSize = stk_size;  
				ptcb->OSTCBStkBottom = pbos;   
				ptcb->OSTCBOpt = opt;           
				ptcb->OSTCBId = id;             
		#else									/*不是扩展型任务*/
				pext = pext;                  /*pext只针对扩展型任务,所以这里自己给自己赋值,防止编译出错*/
				stk_size = stk_size;
				pbos = pbos;
				opt = opt;
				id = id;
		#endif

		#if OS_TASK_DEL_EN > 0u
				ptcb->OSTCBDelReq = OS_ERR_NONE;/*将删除TCB的请求设置为OS_ERR_NONE*/
												/*如果可以删除任务本身,可以从每个OS_TCB中节省出一个布尔量*/
		#endif

		/*提前进行相关计算,为了节省CPU的操作事件*/
		#if OS_LOWEST_PRIO <= 63u                                   
				ptcb->OSTCBY = (INT8U)(prio >> 3u);
				ptcb->OSTCBX = (INT8U)(prio & 0x07u);
		#else                                                            
				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;         /* 如果不打算在应用程序中使用各类事件,OS_TCB中OSTCBEventPt就不会出现
															  任务就不会被挂起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消息数设为0*/
		#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 *)"?";/*初始化TCB任务名称*/
		#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);					/*初始化钩子函数*/

		OSTaskCreateHook(ptcb);                 /* Call user defined hook调用用户自定义的钩子函数*/

		OS_ENTER_CRITICAL();					/*关中断*/
		OSTCBPrioTbl[prio] = ptcb;				
		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;         /*通过掩码计算就绪组号*/
		OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;/*通过掩码计算在就绪表中的位置*/
		OSTaskCtr++;                         /* 任务数目加1*/
		OS_EXIT_CRITICAL();					/*开中断*/
		return (OS_ERR_NONE);
	}
	OS_EXIT_CRITICAL();						/*开中断*/
	return (OS_ERR_TASK_NO_MORE_TCB);
}

相关介绍:http://blog.csdn.net/m0_37411189/article/details/72967962

解析在创建任务时对该任务控制块的初始化过程(三步走):

  1. 被创建任务从空闲任务控制链表(OSTCBFreeList)中获取一个任务控制块 

2.用任务的属性对任务控制块各个成员进行赋值


3.把这个任务控制块链入到任务控制块链表(OSTCBList),并在任务就绪表中登记该任务


个人感觉源代码读起来有些费神,但是这三个图表现的很清楚。

到这里,OS_CORE.C文件读完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

allein_STR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值