目录
(1)获取系统中所有任务的任务状态信息,并通过串口形式进行展示
一、相关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); //通过串口打印所有任务的信息