阅读 32

OS_CORE.C(10)

今天看os_core.c文件中的各种初始化函数。

OS_EventWaitListInit(OS_EVENT *pevent)初始化事件控制块的等待列表:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                 INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST
*									初始化事件控制块的等待列表
* Description: This function is called by other uC/OS-II services to initialize the event wait list.
*描述:该功能被其他uc/os-ii服务调用,用来初始化事件的等待列表。
* Arguments  : pevent    is a pointer to the event control block allocated to the event.
*参数:					--pevent是一个指向事件控制块的指针
* Returns    : none
*返回值:无
* Note       : This function is INTERNAL to uC/OS-II and your application should not call it.
注释:该功能是内部函数,你的应用程序不能调用
*********************************************************************************************************
*/
#if (OS_EVENT_EN)								/*允许生成事件*/
void  OS_EventWaitListInit(OS_EVENT *pevent)	/*调用初始化事件等待列表函数*/
{
	INT8U  i;

	pevent->OSEventGrp = 0u;                     /*将事件组初始化为0*/
	for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) 
	{
		pevent->OSEventTbl[i] = 0u;				/*将事件表全部初始化为0*/
	}
}
#endif
复制代码

\

OS_InitEventList(void)初始化事件控制块的空闲列表:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                             INITIALIZATION
*                           INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS
*							初始化事件控制块的空闲列表
* Description: This function is called by OSInit() to initialize the free list of event control blocks.
*描述:该功能被初始化函数 OSInit()调用,用来初始化事件控制块的空闲列表
* Arguments  : none
*参数:无
* Returns    : none
返回值:无
*********************************************************************************************************
*/

static  void  OS_InitEventList(void)				
{
#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
#if (OS_MAX_EVENTS > 1u)					/*最大事件数不止1个,用循环处理*/
	INT16U     ix;
	INT16U     ix_next;
	OS_EVENT  *pevent1;						/*第一个指向事件控制块的指针*/
	OS_EVENT  *pevent2;						/*第二个指向事件控制块的指针*/

	OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table 将事件表从内存中清理掉*/
	for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++)  /* Init. list of free EVENT control blocks初始化事件控制块的空闲列表*/
	{       
		ix_next = ix + 1u;									
		pevent1 = &OSEventTbl[ix];							/*pevent1指向ix个ECB*/
		pevent2 = &OSEventTbl[ix_next];						/*pevent2指向下一个ECB*/
		pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;		/*将事件的类型设置为无使用类型*/
		pevent1->OSEventPtr = pevent2;						/*将OSEvenPtr指向下一个元素(ECB)*/
		#if OS_EVENT_NAME_EN > 0u									/*如果事件控制块被命名,设置为未命名*/
				pevent1->OSEventName = (INT8U *)(void *)"?";		/*未命名就用“?”表示*/
		#endif
	}
	pevent1 = &OSEventTbl[ix];								/*对数组的最后一个进行处理*/
	pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;			
	pevent1->OSEventPtr = (OS_EVENT *)0;					/*最后的OSEventPtr指针指向0,作为结束*/
	#if OS_EVENT_NAME_EN > 0u									/*如果最后一个事件也有名称,设置为未命名*/
		pevent1->OSEventName = (INT8U *)(void *)"?"; 
	#endif
		OSEventFreeList = &OSEventTbl[0];						/*最后事件空闲列表的指针指向事件表的首地址*/
#else
	OSEventFreeList = &OSEventTbl[0];       /*如果只有一个事件控制块,就不需要循环了,直接进行处理*/
	OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED;
	OSEventFreeList->OSEventPtr = (OS_EVENT *)0;
#if OS_EVENT_NAME_EN > 0u
	OSEventFreeList->OSEventName = (INT8U *)"?";  
#endif
#endif
#endif
}
复制代码

\

其中:在循环体内使用两个指针,如下所示:

ix_next = ix + 1u;									
		pevent1 = &OSEventTbl[ix];							/*pevent1指向ix个ECB*/
		pevent2 = &OSEventTbl[ix_next];						/*pevent2指向下一个ECB*/
		pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;		/*将事件的类型设置为无使用类型*/
		pevent1->OSEventPtr = pevent2;						/*将OSEvenPtr指向下一个元素(ECB)*/
复制代码

\

个人认为是想通过EventPtr指针将所有的事件控制块链接起来。

这个函数,最主要的是设置时间的类型 (初始化为UNUSED)。

此外,

OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table 将事件表从内存中清理掉*/
	for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++)  /* Init. list of free EVENT control blocks初始化事件控制块的空闲列表*/
	{       
		ix_next = ix + 1u;									
		pevent1 = &OSEventTbl[ix];							/*pevent1指向ix个ECB*/
		pevent2 = &OSEventTbl[ix_next];						/*pevent2指向下一个ECB*/
		pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;		/*将事件的类型设置为无使用类型*/
		pevent1->OSEventPtr = pevent2;						/*将OSEvenPtr指向下一个元素(ECB)*/
		#if OS_EVENT_NAME_EN > 0u									/*如果事件控制块被命名,设置为未命名*/
				pevent1->OSEventName = (INT8U *)(void *)"?";		/*未命名就用“?”表示*/
		#endif
	}
复制代码

\

刚开始对这几行语句有些疑问:内存已经把OSEventTb1清理掉了,怎么后面for循环中还能用?

后来认为是内存清理的是具体的数据,但是地址还保留着。下面是对地址进行的相关操作。主要是设置了事件的类型,改了名字,并且重新建立了表的链接。

\

OS_InitMisc(void)初始化各种变量:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                             INITIALIZATION
*                                    INITIALIZE MISCELLANEOUS VARIABLES
*										初始化各种变量
* Description: This function is called by OSInit() to initialize miscellaneous variables.
*描述:该功能被OSInit()调用,用来初始化各种变量
* Arguments  : none
*参数:无
* Returns    : none
返回值:无
*********************************************************************************************************
*/

static  void  OS_InitMisc(void)
{
#if OS_TIME_GET_SET_EN > 0u				/*如果可以生成OS_TIME_GET_SET()函数*/
	OSTime = 0uL;                       /* Clear the 32-bit system clock将时钟设为0。清除32位系统时钟*/
#endif

	OSIntNesting = 0u;                  /* Clear the interrupt nesting counter将中断嵌套数初始化为0*/
	OSLockNesting = 0u;                 /* Clear the scheduling lock counter将调度锁数目初始化为0*/

	OSTaskCtr = 0u;                    /* Clear the number of tasks将任务的数目初始化为0*/

	OSRunning = OS_FALSE;              /* Indicate that multitasking not started将OSRunning设置为false,说明多任务没有开始*/

	OSCtxSwCtr = 0u;                   /* Clear the context switch counter将上下文切换次数初始化为0*/
	OSIdleCtr = 0uL;                   /* Clear the 32-bit idle counter将空闲节拍计数值初始化为0*/

#if OS_TASK_STAT_EN > 0u			   /*如果有任务统计*/
	OSIdleCtrRun = 0uL;				  /*将已运转的空闲数初始化为0*/
	OSIdleCtrMax = 0uL;				  /*将空闲节拍最大值初始化为0*/
	OSStatRdy = OS_FALSE;             /* Statistic task is not ready将统计任务的状态设置为为准备好(false)*/
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
	OSSafetyCriticalStartFlag = OS_FALSE;  /* Still allow creation of objects */
#endif
}
复制代码

\

OS_InitRdyList(void)初始化就绪列表:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                             INITIALIZATION
*                                       INITIALIZE THE READY LIST
*											初始化就绪列表
* Description: This function is called by OSInit() to initialize the Ready List.
*描述:该功能被OSInit()调用,用来初始化就绪列表
* Arguments  : none
*参数:无
* Returns    : none
返回值:无
*********************************************************************************************************
*/
static  void  OS_InitRdyList(void)				      /*初始化就绪列表*/
{
	INT8U  i;

	OSRdyGrp = 0u;                                    /*将就绪列表组清除为0*/
	for (i = 0u; i < OS_RDY_TBL_SIZE; i++)				
	{
		OSRdyTbl[i] = 0u;						      /*将就绪表初始化为0*/
	}	

	OSPrioCur = 0u;									  /*将当前任务的优先级设置为0*/
	OSPrioHighRdy = 0u;								  /*最高优先级任务的优先级设置为0*/

	OSTCBHighRdy = (OS_TCB *)0;						  /*就绪列表中,指向最高优先级TCB的指针设置为0*/
	OSTCBCur = (OS_TCB *)0;							  /*指向当前任务控制块的指针设置为0*/
}	
复制代码

\

这个函数中,个人认为很需要搞清楚各个变量代表的含义究竟是什么。不然后面会出现混乱和误用。

\

OS_InitTCBList(void)初始化任务控制块的空闲列表:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                             INITIALIZATION
*                            INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS
*								初始化任务控制块的空闲列表
* Description: This function is called by OSInit() to initialize the free list of OS_TCBs.
*描述:该功能被OSInit()调用,用来初始化OS_TCB的空闲列表
* Arguments  : none
*参数:无
* Returns    : none
返回值:无
*********************************************************************************************************
*/

static  void  OS_InitTCBList(void)					/*初始化任务控制块的空闲列表*/
{
	INT8U    ix;
	INT8U    ix_next;
	OS_TCB  *ptcb1;									/*第一个指向TCB的指针*/
	OS_TCB  *ptcb2;									/*第二个指向TCB的指针*/

	OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl));      /* Clear all the TCBs 将所有的TCB从内存中清除掉*/
	OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));  /* Clear the priority table将优先级表从内存中清除掉*/
	for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++)/*初始化TCB的空闲列表*/
	{    
		ix_next = ix + 1u;
		ptcb1 = &OSTCBTbl[ix];						/*ptcb1指向TCB表的第ix个*/
		ptcb2 = &OSTCBTbl[ix_next];					/*ptcb2指向下一个*/
		ptcb1->OSTCBNext = ptcb2;					/*通过TCBNext指针将该表的每一项建立连接*/
#if OS_TASK_NAME_EN > 0u							/*如果有名字,设置为未命名*/
		ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; 
#endif
	}
	ptcb1 = &OSTCBTbl[ix];							/*处理最后一个T*/
	ptcb1->OSTCBNext = (OS_TCB *)0;                
#if OS_TASK_NAME_EN > 0u
	ptcb1->OSTCBTaskName = (INT8U *)(void *)"?";    
#endif
	OSTCBList = (OS_TCB *)0;                       /*将任务控制块列表进行初始化*/
	OSTCBFreeList = &OSTCBTbl[0];					/*将TCB空闲列表的指针指向TCB表的首地址*/
}
复制代码

初始化空闲列表和初始化就绪列表很相似。不赘述。

以上是CORE.C文件中有关初始化的内容。总结为下图:

\

\

OS_MemClr(INT8U  *pdest,INT16U  size)清理内存:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                        CLEAR A SECTION OF MEMORY
*											清理内存某些部分
* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM.
*描写:该功能被其他服务调用,用来清除RAM中一段连续块。
* Arguments  : pdest    is the start of the RAM to clear (i.e. write 0x00 to)
*参数:					--pdest是RAM中要清除的块的开始地址
*              size     is the number of bytes to clear.
*						--size是要清除的大小。
* Returns    : none
*返回值:无
* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.
*              2) Note that we can only clear up to 64K bytes of RAM.  This is not an issue because none
*                 of the uses of this function gets close to this limit.
*              3) The clear is done one byte at a time since this will work on any processor irrespective
*                 of the alignment of the destination.
	注释:	1)该功能为内部函数,你的应用程序不能调用。
			2)需要注意我们只能清理RAM中的64KB。其他部分不能清理。不过这也不是什么问题,因为一般不会邻近这个限制区。
			3)清理的时候一次只能清理一个字节。因为这样的话不用考虑目标的排列方式,与处理器无关,移植性更高。
*********************************************************************************************************
*/

void  OS_MemClr(INT8U  *pdest,		/*清理内存*/
	INT16U  size)
{
	while (size > 0u) {
		*pdest++ = (INT8U)0;		/*指针置为0*/
		size--;						/*大小最后也置为0*/
	}
}
复制代码

\

关于内存的管理,这里总结介绍一下:wenku.baidu.com/view/51e6f4…

OS_MemClr()函数:

  • 用于对指定内存中的数据进行清零操作。
  • 最大只允许清除内存中64KB的字节的数据。用户不必担心数据量不满足要求的问题,因为这个功能的应用没有一个能接近这个限制。
  • 该功能一个时间点只能清除一个字节的数据,这是为了在任何程序上移植该程序时都能对准内存位置。当然,如果确定了处理器类型,可以修改该函数,提高代码的效率。

\

\

\

第三个图也可以和上文TCB的空闲列表函数很好的联系起来。都是类似的。

其他相关的内存管理没有介绍。因为还没有涉及到相关函数。涉及到再说。

\

 OS_MemCopy(INT8U  *pdest,INT8U  *psrc,INT16U  size)内存复制函数:\

/*$PAGE*/
/*2018/2/8
*********************************************************************************************************
*                                        COPY A BLOCK OF MEMORY
*											复制内存块
* Description: This function is called by other uC/OS-II services to copy a block of memory from one
*              location to another.
*描述:该功能被其他服务调用,用来将内存块从某个位置复制到另一个位置。
* Arguments  : pdest    is a pointer to the 'destination' memory block
*参数:					--pdest指向目的内存块的指针
*              psrc     is a pointer to the 'source'      memory block
*						--psrc指向源内存块的指针
*              size     is the number of bytes to copy.
*						--size:要复制的内容的大小
* Returns    : none
*返回值:无
* Notes      : 1) This function is INTERNAL to uC/OS-II and your application should not call it.  There is
*                 no provision to handle overlapping memory copy.  However, that's not a problem since this
*                 is not a situation that will happen.
*              2) Note that we can only copy up to 64K bytes of RAM
*              3) The copy is done one byte at a time since this will work on any processor irrespective
*                 of the alignment of the source and destination.
	注释:	1)该功能为内部函数,你的应用程序不能调用。没有提供处理重复内存复制的方法。不过没什么问题,因为这种情况不会发生。
			2)我们只能复制RAM的64KB。
			3)我们一个时间点只能复制一个字节。
*********************************************************************************************************
*/

void  OS_MemCopy(INT8U  *pdest,
	INT8U  *psrc,
	INT16U  size)
{
	while (size > 0u) {
		*pdest++ = *psrc++;			/*从源内存块复制到目标内存块*/
		size--;
	}
}
复制代码


\

文章分类
代码人生
文章标签