Freertos学习:04-任务的调试函数

--- title: rtos-freertos-04-任务的调试函数 EntryName: rtos-freertos-04-task-debug date: 2020-06-22 08:49:06 categories: tags: - debug - freertos ---

章节概述:

任务应用函数是一组辅助类函数,一般用于调试信息输出、获取任务句柄、获取任务状态、操作任务标签值等等。

概览

uxTaskPriorityGet():查询某个任务的优先级
vTaskPrioritySet():改变某个任务的任务优先级
uxTaskGetSystemState():获取系统中任务状态
vTaskGetInfo():获取某个任务信息
xTaskGetApplicationTaskTag():获取某个任务的标签(Tag)值
xTaskGetCurrentTaskHandle():获取当前正在运行的任务的任务句柄
xTaskGetHandle():根据任务名字查找某个任务的句柄
xTaskGetIdleTaskHandle():获取空闲任务的任务句柄
uxTaskGetStackHighWaterMark():获取任务的堆栈的历史剩余最小值,FreeRTOS 中叫做“高水位线”
eTaskGetState():获取某个任务的壮态,这个壮态是 eTaskState 类型
pcTaskGetName():获取某个任务的任务名字
xTaskGetTickCount():获取系统时间计数器值
xTaskGetTickCountFromISR():在中断服务函数中获取时间计数器值
xTaskGetSchedulerState():获取任务调度器的壮态,开启或未开启
uxTaskGetNumberOfTasks():获取当前系统中存在的任务数量
vTaskList():以一种表格的形式输出当前系统中所有任务的详细信息
vTaskGetRunTimeStats():获取每个任务的运行时间
vTaskSetApplicationTaskTag():设置任务标签(Tag)值
SetThreadLocalStoragePointer():设置线程本地存储指针
GetThreadLocalStoragePointer():获取线程本地存储指针

获取任务系统状态

UBaseType_t uxTaskGetSystemState(
    TaskStatus_t * constpxTaskStatusArray,
    const UBaseType_tuxArraySize,
    unsigned long * constpulTotalRunTime );

描述:该函数向TaskStatus_t结构体填充相关信息,系统中每一个任务的信息都可以填充到TaskStatus_t结构体数组中,数组大小由uxArraySize指定。

在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必须设置为1,此函数才有效。

参数解析:

  • pxTaskStatusArray:指向TaskStatus_t类型的结构体数组。这个数组至少要包含1个元素。RTOS控制的任务数量可以使用API函数uxTaskGetNumberOfTasks()获取。
  • uxArraySize:参数pxTaskStatusArray指向的数组大小,也就是该数组的索引数目。
  • pulTotalRunTime:如果在文件FreeRTOSConfig.h中设置宏configGENERATE_RUN_TIME_STATS为1,则该函数将总运行时间写入*pulTotalRunTime中。pulTotalRunTime可以设置为NULL,表示忽略总运行时间。

返回值:被填充的TaskStatus_t结构体数量。这个值应该等于通过调用API函数uxTaskGetNumberOfTasks()返回的值,但如果传递给uxArraySize参数的值太小,则返回0。

注意:注意,这个函数仅用来调试用,调用此函数会挂起所有任务,直到函数最后才恢复挂起的任务,因此任务可能被挂起很长时间。

结构体TaskStatus_t定义如下:

typedef struct xTASK_STATUS
{
   /* 任务句柄*/
   TaskHandle_t xHandle;
 
   /* 指针,指向任务名*/
   const signed char *pcTaskName;
 
   /* 任务ID,是一个独一无二的数字*/
   UBaseType_t xTaskNumber;
 
   /* 任务当前的状态(运行、就绪、挂起等等)*/
   eTaskState eCurrentState;
 
   /* 任务运行(或继承)的优先级。*/
   UBaseType_t uxCurrentPriority;
 
   /* 当任务因继承而改变优先级时,该变量保存任务最初的优先级。仅当configUSE_MUTEXES定义为1有效。*/
   UBaseType_t uxBasePriority;
 
   /* 分配给任务的总运行时间。仅当宏configGENERATE_RUN_TIME_STATS为1时有效。*/
   unsigned long ulRunTimeCounter;
 
   /* 从任务创建起,堆栈剩余的最小数量,这个值越接近0,堆栈溢出的可能越大。 */
   unsigned short usStackHighWaterMark;
}TaskStatus_t;

例子:

/*本例演示如是使用uxTaskGetSystemState()函数来获取运行时间信息,并将其转化为程序员更易识别的字符格式,这些转化后的字符保存到pcWriteBuffer中。*/
void vmyTaskGetRunTimeStats()
{
   TaskStatus_t*pxTaskStatusArray;
   volatileUBaseType_t uxArraySize, x;
   unsignedlong ulTotalRunTime, ulStatsAsPercentage;

 
   /* 获取任务总数目*/
  uxArraySize = uxTaskGetNumberOfTasks ();
 
   /*为每个任务的TaskStatus_t结构体分配内存,也可以静态的分配一个足够大的数组 */
  pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ));
 
   if(pxTaskStatusArray != NULL )
   {
      /*获取每个任务的状态信息 */
     uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, 
                                        uxArraySize, 
                                        NULL);//&ulTotalRunTime );
 
      /* 百分比计算 */
     //ulTotalRunTime /= 100UL;
 
      /* 避免除零错误 */
      if(1)//ulTotalRunTime > 0 )
      {
         /* 将获得的每一个任务状态信息部分的转化为程序员容易识别的字符串格式*/
        for( x = 0; x < uxArraySize; x++ )
         {
           /* 计算任务运行时间与总运行时间的百分比。*/
           //ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter /ulTotalRunTime;
 
           if(1) // ulStatsAsPercentage > 0UL )
           {
              sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n",
                                pxTaskStatusArray[ x ].pcTaskName,
                                pxTaskStatusArray[ x ].ulRunTimeCounter,
                                ulStatsAsPercentage );
           }
           else
           {
              /* 任务运行时间不足总运行时间的1%*/
              sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n",
                                pxTaskStatusArray[ x ].pcTaskName,
                                 pxTaskStatusArray[x ].ulRunTimeCounter );
           }
         }
      }
 
      /* 释放之前申请的内存*/
     vPortFree( pxTaskStatusArray );
   }
}

获取当前任务句柄

TaskHandle_t xTaskGetCurrentTaskHandle(void );

描述:

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetCurrentTaskHandle必须设置为1,此函数才有效。

参数解析:

返回值: 返回当前任务(调用该函数的任务)的句柄。

获取空闲任务句柄

TaskHandle_t xTaskGetIdleTaskHandle(void );

描述:

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetIdleTaskHandle必须设置为1,此函数才有效。

返回值:返回空闲任务句柄。空闲任务在RTOS调度器启动时自动创建。

获取任务堆栈最大使用深度

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

描述:获取任务的堆栈的历史剩余最小值,FreeRTOS 中叫做“高水位线”。

任务的堆栈空间会随着任务执行以及中断处理而增长或缩小。该函数可以返回任务启动后的最小剩余堆栈空间。换句话说,可以间接估算出一个任务最多需要多少堆栈空间。

在文件FreeRTOSConfig.h中,宏INCLUDE_uxTaskGetStackHighWaterMark 必须设置成1,此函数才有效。

参数解析:

xTask:任务句柄。NULL表示查看当前任务的堆栈使用情况。

返回值:返回最小剩余堆栈空间,以字为单位。比如一个32为架构处理器,返回值为1表示有4字节堆栈空间没有使用过。如果返回值为0,则任务很可能已经发生了堆栈溢出。

例子:

void vTask1( void * pvParameters )
{
    UBaseType_t uxHighWaterMark;

    /* 入口处检测一次 */
    uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );

    for( ;; )
    {
        /* 正常调用函数 */
        vTaskDelay( 1000 );

        /* 测量堆栈使用情况 */
        uxHighWaterMark =uxTaskGetStackHighWaterMark( NULL );
    }
}

获取任务状态

eTaskState eTaskGetState( TaskHandle_txTask );

描述:返回一个枚举类型的任务状态值。

在文件FreeRTOSConfig.h中,宏INCLUDE_eTaskGetState必须设置为1,此函数才有效。

参数解析:

xTask:任务句柄

返回值:

返回值 状态
eReady 就绪
eRunning 运行
eBlocked 阻塞
eSuspended 挂起
eDeleted 删除

获取任务描述内容

char * pcTaskGetTaskName( TaskHandle_txTaskToQuery );

描述:获取任务的名称。

在文件FreeRTOSConfig.h中,宏INCLUDE_pcTaskGetTaskName必须设置成1,此函数才有效。

参数解析:xTaskToQuery:任务的句柄。NULL表示获取当前任务的描述内容指针。

返回值:一个指针,指向任务名称字符串。

获取系统节拍次数

volatile TickType_t xTaskGetTickCount(void );

描述:

这个函数不能在ISR中调用;用volatile TickType_t xTaskGetTickCountFromISR( void )代替

返回值:返回从vTaskStartScheduler函数调用后的系统时钟节拍次数。

获取调度器状态

BaseType_t xTaskGetSchedulerState( void);

描述:获取调度器当前状态。

在文件FreeRTOSConfig.h中,宏INCLUDE_xTaskGetSchedulerState或configUSE_TIMERS必须定义为1,此函数才有效。

返回值:返回值是以下常量之一(定义在task.h)

  • taskSCHEDULER_NOT_STARTED(未启动)
  • taskSCHEDULER_RUNNING(正常运行)
  • taskSCHEDULER_SUSPENDED(挂起)

获取任务总数

UBaseType_t uxTaskGetNumberOfTasks(void );

描述:获取RTOS内核当前管理的任务总数。

返回值: 返回RTOS内核当前管理的任务总数。

包含所有就绪、阻塞和挂起状态的任务。对于一个删除的任务,如果它的堆栈空间还没有被空闲任务释放掉,则这个被删除的任务也含在计数值中。

获取所有任务详情

void vTaskList( char *pcWriteBuffer );

描述:将每个任务的状态、堆栈使用情况等以字符的形式保存到参数pcWriteBuffer指向的区域。vTaskList()函数调用usTaskGetSystemState()函数,然后将得到的信息格式化为程序员易读的字符形式。输出的内容例子如下图所示,图中State一栏中,B表示阻塞、R表示就绪、D表示删除(等待清除内存)、S表示挂起或阻塞。

在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS必须定义为1,此函数才有效。

参数解析:保存信息的缓冲区(格式为ASCII);要足够大,以容纳生成的报告,每个任务大约需要40个字节。

注意:调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。

获取任务运行时间

void vTaskGetRunTimeStats( char*pcWriteBuffer );

描述:用于统计每个任务的运行时间。

参数解析:保存任务的运行时间信息(格式为ASCII);要足够大,以容纳生成的报告,每个任务大约需要40个字节。

注意:调用这个函数会挂起所有任务,这一过程可能持续较长时间,因此本函数仅在调试时使用。

要使用这个函数必须满足一些条件,那就是必须有一个用于时间统计的定时器或计数器,这个定时器或计数器的精度要至少大于10倍的系统节拍周期。

这个定时器或计数器的配置以及获取定时时间是由两个宏定义实现的,这两个宏一般在文件FreeRTOSConfig.h中定义。

  • 配置定时器或计数器的宏为portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),
  • 获取定时时间的宏为portGET_RUN_TIME_COUNTER_VALUE。

必须在文件FreeRTOSConfig.h中将宏configGENERATE_RUN_TIME_STATS和configUSE_STATS_FORMATTING_FUNCTIONS设置为1,此API函数才有效。

例子:

char RunTimeInfo[400];      //保存任务运行时间信息

//FreeRTOS时间统计所用的节拍计数器
volatile unsigned long long FreeRTOSRunTimeTicks;

//初始化TIM3使其为FreeRTOS的时间统计提供时基
void vConfigureTimeForRunTimeStats(void)
{
    //定时器3初始化,定时器时钟为72M,分频系数为72-1,所以定时器3的频率
    //为72M/72=1M,自动重装载为50-1,那么定时器周期就是50us
    FreeRTOSRunTimeTicks = 0;
    TIM3_Int_Init(50-1,72-1);   //初始化TIM3,包括对应的中断代码
}

unsigned long long getRunTimeCounterValue(void)
{
    return FreeRTOSRunTimeTicks;
}

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
    {
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
        FreeRTOSRunTimeTicks++;
    }
}

void RunTimeStats_task(void *pvParameters)
{
    while(1)
    {
        {
            memset(RunTimeInfo,0,400);              //信息缓冲区清零
            vTaskGetRunTimeStats(RunTimeInfo);      //获取任务运行时间信息
            printf("任务名\t\t\t运行时间\t运行所占百分比\r\n");
            printf("%s\r\n",RunTimeInfo);
        }
        vTaskDelay(2000);
    }
}

在文件FreeRTOSConfig.h中,定义下列代码:

extern void vConfigureTimerForRunTimeStats( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() getRunTimeCounterValue()
posted @ 2020-06-22 08:49  schips  阅读(1417)  评论(0编辑  收藏  举报