FreeRTOS操作系统移植[任务状态与信息查询]

目录

一、相关API函数解析

(1)优先级查询

(2)优先级设置函数

(3)获取系统中所有任务的任务状态信息

(4)单个任务状态信息获取

(5)获取任务个数

(6)任务句柄获取

(7)API总结

二、API在程序中的实际应用

(1)获取系统中所有任务的任务状态信息,并通过串口形式进行展示

(2)获取指定任务的状态信息


一、相关API函数解析

(1)优先级查询

uxTaskPriorityGet(),使用此函数前,应先将宏INCLUDE_uxTaskPriorityGet设置为1。函数原型;

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )PRIVILEGED_FUNCTION;

函数解析,对任意函数实现优先级查询,xTask 为对象句柄,返回值为优先级。

*INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. 

*Obtain the priority of any task.

#if ( INCLUDE_uxTaskPriorityGet == 1 )
	UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
	{
	TCB_t *pxTCB;
	UBaseType_t uxReturn;

		taskENTER_CRITICAL();    //进入临界区
		{
			/* If null is passed in here then it is the priority of the that
			called uxTaskPriorityGet() that is being queried. */
			pxTCB = prvGetTCBFromHandle( xTask );
			uxReturn = pxTCB->uxPriority;
		}
		taskEXIT_CRITICAL();    //退出临界区

		return uxReturn;
	}
#endif /* INCLUDE_uxTaskPriorityGet */

(2)优先级设置函数

vTaskPrioritySet(),用来改变某任务的优先级,用户层代码一般不使用,通常供FreeRTOS内核使用。

函数原型:

void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )

xTask为任务对象句柄,uxNewPriority为所新设的优先级。同样,使用此功能前先将宏INCLUDE_vTaskPrioritySet 设置为1。同时注意以下:任务将被悬挂

 * Suspend any task.  When suspended a task will never get any microcontroller
 * processing time, no matter what its priority.

#if ( INCLUDE_vTaskPrioritySet == 1 )
	void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
	{
	TCB_t *pxTCB;
	UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
	BaseType_t xYieldRequired = pdFALSE;

		configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
//......
    }

(3)获取系统中所有任务的任务状态信息

uxTaskGetSystemState()函数,任务状态信息保存在pxTaskStatusArray结构体指针,指向任务结构体,uxArraySize保存任务状态数组的大小。pulTotalRunTime 纪录保存系统总的运行时间。

函数原型:

UBaseType_t uxTaskGetSystemState
    ( TaskStatus_t * const pxTaskStatusArray, 
      const UBaseType_t uxArraySize, 
      uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION;

函数解析:

宏configUSE_TRACE_FACILITY和宏configUSE_STATS_FORMATTING_FUNCTIONS必须  

都被定义为1,以便此函数可用。

* This function will disable interrupts for its duration.   It is * not intended for normal application runtime use but as a debug aid.注意:此函数在其持续时间内是禁止中断的,通常作为调试辅助,不用于正常程序调用。configGENERATE_RUN_TIME_STATS设置为1,pulTotalRunTime 用于纪录保存系统总的运行时间。

vTaskGetRunTime()API可用来统计系统任务的运行时间信息,打印每个任务占用CPU资源的百分比,通过相关配置,configGENERATE_RUN_TIME_STATS 与configUSE_STATS_FORMATTING_FUNCTIONS 同时设置为非零,以便实现函数功能,vTaskGetRunTime在统计任务运行时间通过使用固定初始化分配的定时器/计时器来记录,并不是系统的滴答定时器等。

#define configGENERATE_RUN_TIME_STATS	        1                       
//为1时启用运行时间统计功能
#define configUSE_STATS_FORMATTING_FUNCTIONS	1                       
//与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
                                                                        //prvWriteNameToBuffer(),vTaskList(),
                                                                        //vTaskGetRunTimeStats()
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && 
    ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
	void vTaskGetRunTimeStats( char *pcWriteBuffer )

pcWriteBuffer是用来保存任务时间的存储区,前提是要保证存储区足够大。

API解析中提到以下:

* vTaskGetRunTimeStats() has a dependency on the sprintf() C library
* function that might bloat the code size, use a lot of stack, and
* provide different results on different platforms.  An alternative,
* tiny, third party, and limited functionality implementation of
* sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
* a file called printf-stdarg.c (note printf-stdarg.c does not provide
* a full snprintf() implementation!).

vTaskGetRunTimeStats()依赖于sprintf() C库函数可能会使代码膨胀,使用大量的堆栈,并且
在不同平台上提供不同的结果,是一种替代方法。主要用于演示应用程序的运行状态。

char RunTimeInfo[400];		//保存任务运行时间信息
vTaskGetRunTimeStats(RunTimeInfo);		//获取任务运行时间信息
printf("任务名\t\t\t运行时间\t运行所占百分比\r\n");
printf("%s\r\n",RunTimeInfo);
/*
任务名			运行时间	运行所占百分比
RunTimeStats_task  	1820		<1%
IDLE               	9596530		99%
task1_task         	19825		<1%
task2_task         	19825		<1%
Tmr Svc            	1		<1%
*/

 

(4)单个任务状态信息获取

另外获取优先级也可以使用vTaskGetInfo(),这个函数用于获取单个任务的状态信息。

vTaskGetInfo的函数原型:

void vTaskGetInfo( TaskHandle_t xTask, 
                   TaskStatus_t *pxTaskStatus, 
                   BaseType_t xGetFreeStackSpace, 
                   eTaskState eState )

FreeRTO操作系统中#define vTaskGetTaskInfo vTaskGetInfo。configUSE_TRACE_FACILITY设置为1,以便函数可用。

参数解析,xTask为任务对象句柄,pxTaskStatus为结构体变量,状态信息指向于此,xGetFreeStackSpace步骤跳过,指的是跳过TaskStatus_t 结构体中usStackhighWaterMark保存堆栈剩余大小,此过程需耗费CPU一定资源,通过将xGetFreeStackSpace设置为pdFALSE可实现跳过。eState被设置为eTaskState 类型,用于保存任务此时的运行状态,运行态/就绪态/阻塞态/挂起态。

任务当前的任务状态,也可以通过eTaskGetState来获取。

eTaskState eTaskGetState( TaskHandle_t xTask );

(5)获取任务个数

通过调用uxTaskGetNumberOfTasks()可以直接获取系统运行的任务个数。函数原型:

UBaseType_t uxTaskGetNumberOfTasks( void )
{
	/* A critical section is not required because the variables are of type
	BaseType_t. */
	return uxCurrentNumberOfTasks;
}

(6)任务句柄获取

通过将宏INCLUDE_xTaskGetHandle设置为1以此实现函数,xTaskGetHandle()可根据任务名pcNameToQuery 查询其对应的任务句柄。若返回为NULL说明该任务名不存在。

TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );

其他方式, xTaskGetCurrentTaskHandle获取当前任务的任务句柄,同样宏( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) 两者其一应也被设置为1,启用。

TaskHandle_t xTaskGetCurrentTaskHandle( void );

(7)API总结

 (来源于正点原子FreeRTOS开发手册)

FreeRTOS提供了大量API来查询任务的运行状态与信息,另外,关于内存操作,可参考如下:

void *pvPortMalloc( size_t xWantedSize );    //内存申请
/*申请失败会得到NULL*/
StatusArray=pvPortMalloc(ArraySize*sizeof(TaskStatus_t));    
//内存申请,StatusArray指向申请的内存地址首地址
void vPortFree( void *pv );                  //内存释放
vPortFree(StatusArray);	 //释放内存

二、API在程序中的实际应用

(1)获取系统中所有任务的任务状态信息,并通过串口形式进行展示

UBaseType_t ArraySize;                  //定义长整型变量
TaskStatus_t *StatusArray;              //定义任务型指针
/*
typedef struct xTASK_STATUS    //结构体
{
	TaskHandle_t xHandle;			
	const char *pcTaskName;			
	UBaseType_t xTaskNumber;	
	eTaskState eCurrentState;		
	UBaseType_t uxCurrentPriority;	
	UBaseType_t uxBasePriority;		
	uint32_t ulRunTimeCounter;		
	StackType_t *pxStackBase;		
	uint16_t usStackHighWaterMark;
} TaskStatus_t;
*/
ArraySize = uxTaskGetNumberOfTasks();		//获取系统任务数量
StatusArray = pvPortMalloc(ArraySize*sizeof(TaskStatus_t));
/*按照系统中的任务数量,申请内存合适的内存单元*/
if(StatusArray != NULL)					//内存申请成功
{
/*ArraySize指针指向任务信息存储数组,由于uxTaskGetSystemState查询的是整个
系统的任务信息,多任务时,StatusArray相当于指向结构体组*/

	ArraySize = uxTaskGetSystemState((TaskStatus_t* 	)StatusArray, 	
									 (UBaseType_t		)ArraySize, //任务信息存储数组大小
								     (uint32_t*		)&TotalRunTime);//保存系统总的运行时间
		printf("TaskName\t\tPriority\t\tTaskNumber\t\t\r\n");
		for(x=0;x<ArraySize;x++)
		{
			//通过串口打印出获取到的系统任务的有关信息,比如任务名称、
			//任务优先级和任务编号。
			printf("%s\t\t%d\t\t\t%d\t\t\t\r\n",				
					StatusArray[x].pcTaskName,
					(int)StatusArray[x].uxCurrentPriority,
					(int)StatusArray[x].xTaskNumber);
			
		}
}
vPortFree(StatusArray);	//释放之前申请的内存

(2)获取指定任务的状态信息

TaskHandle=xTaskGetHandle("led0_task");			//根据任务名获取任务句柄。

//获取LED0_Task的任务信息

vTaskGetInfo((TaskHandle_t	)TaskHandle, 		//任务句柄
				 (TaskStatus_t*	)&TaskStatus, 		//任务信息结构体
				 (BaseType_t	)pdTRUE,			//允许统计任务堆栈历史最小剩余大小
			     (eTaskState	)eInvalid);			//函数自己获取任务运行壮态
//通过串口打印出指定任务的有关信息

printf("任务名:                %s\r\n",TaskStatus.pcTaskName);
printf("任务壮态:              %d\r\n",TaskStatus.eCurrentState);
printf("任务当前优先级:        %d\r\n",(int)TaskStatus.uxCurrentPriority);
printf("任务编号:              %d\r\n",(int)TaskStatus.xTaskNumber);
TaskHandle=xTaskGetHandle("query_task");		//根据任务名获取任务句柄
TaskState=eTaskGetState(TaskHandle);			//获取query_task任务的任务壮态
/*
TaskState 为枚举型
typedef enum
{
	eRunning = 0,	/* A task is querying the state of itself, so must be running. */
	eReady,			/* The task being queried is in a read or pending ready list. */
	eBlocked,		/* The task being queried is in the Blocked state. */
	eSuspended,		/* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
	eDeleted,		/* The task being queried has been deleted, but its TCB has not yet been freed. */
	eInvalid			/* Used as an 'invalid state' value. */
} eTaskState;
{
		case 0:
			sprintf(TaskInfo,"Running");
			break;
		case 1:
			sprintf(TaskInfo,"Ready");
			break;
		case 2:
			sprintf(TaskInfo,"Suspend");
			break;
		case 3:
			sprintf(TaskInfo,"Delete");
			break;
		case 4:
			sprintf(TaskInfo,"Invalid");
			break;
}
*/
vTaskList(InfoBuffer);							//获取所有任务的信息
printf("%s\r\n",InfoBuffer);					//通过串口打印所有任务的信息

版权声明:本文为m0_63741844原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。