细说STM32单片机FreeRTOS任务管理API函数vTaskList()的使用方法

目录

一、函数vTaskList()

[1、 函数说明](#1、 函数说明)

2、返回的字符串表格说明

3、函数的使用方法

[二、 vTaskList()的应用示例](#二、 vTaskList()的应用示例)

1、示例功能、项目设置

2、软件设计

(1)main.c

(2)freertos.c

(3)FreeRTOSConfig.h

三、运行与调试


一、函数vTaskList()

1、 函数说明

函数vTaskList()是内核信息统计用途的API函数,用于返回内核中所有任务的字符串列表信息,包括每个任务的名称、状态、优先级、高水位值、任务编号等。其原型定义如下:

cpp 复制代码
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

	void vTaskList( char * pcWriteBuffer )
	{
	TaskStatus_t *pxTaskStatusArray;
	UBaseType_t uxArraySize, x;
	char cStatus;
    //此处省去1万言

	}

#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */

参数pcWriteBuffer是预先创建的一个字符数组的指针,用于存储返回的字符串信息。这个字符数组必须足够大,FreeRTOS不会检查这个数组的大小。这个函数的使用示例代码如下:

cpp 复制代码
char infoBuffer[300];
vTaskList(infoBuffer);

返回的数据存储在字符数组infoBuffer中,使用了"\t""\n"等转义字符,以便用表格方式显示。

2、返回的字符串表格说明

函数vTaskList()返回的是一个用字符串表达的表格。例如:

cpp 复制代码
Task_LED1		\tx\t8\t50\t2\r\n
Tmr Svc		    \tR\t2\t246\t4\r\n
IDLE			\tR\t0\t118\t3\r\n
Task_ADC		\tB\t24\t134\t1\r\n\0

其中,每行字符串的第1列是任务名称,这里除了用户的两个任务Task_LED1和Task_ADC,还有系统自动创建的空闲任务IDLE和定时器服务任务Tmr Svc。

其中,每行字符串的第2列是用"\t"分隔的多个参数,依次为状态、优先级、栈空间高水位值和任务编号。

其中的第2列,任务状态用字母表示,各字母的意义如下:

  • X,运行状态,也就是调用函数vTaskList()的任务的状态。
  • B,阻塞状态。
  • R,就绪状态。
  • S,挂起状态,或无限等待时间的阻塞状态。
  • D,被删除的任务,但是空闲任务还没有释放其使用的内存。

例如,对于上图中的任务Task_LED1,其状态字符串是"\tX\t8\t50\t2\r\n",表示它处于运行状态,优先级为8,栈空间高水位值为50,任务编号为2。

3、函数的使用方法

vTaskList()的代码实现用到了函数sprintf(),会使编译后的应用的大小明显增大。所以,函数一般只在调试时使用,不要在发布版本里使用。要使用这个函数,需要将以下3个参数都设置为1。如果不这样操作,编译器会警告。

  • configUSE_TRACE_FACILITY,默认值为1,可在CubeMX里设置。
  • configUSE_STATS_FORMATTING_FUNCTION,默认值为0,可在CubeMX里设置。
  • configSUPPORT_DYNAMIC_ALLOCATION,默认值为1,不能在CubeMX里设置。

修改FreeRTOSConfig.h,定义宏,覆盖FreeRTOS.h相关的宏定义:

cpp 复制代码
//vTaskList()
#define configUSE_TRACE_FACILITY	1
#define configUSE_STATS_FORMATTING_FUNCTIONS	1
#define configSUPPORT_DYNAMIC_ALLOCATION	1

二、 vTaskList()的应用示例

使用本文作者写的其他文章作为本文示例的参考文章,项目背景、项目配置完全相同。特别地,创建的FreeRTOS任务完全相同。项目的软件设计大部分相同。

参考文章:细说STM32单片机FreeRTOS任务管理API函数及多任务编程的实现方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/147249948?spm=1011.2415.3001.5331

1、示例功能、项目设置

与参考文章相同。

2、软件设计

(1)main.c

与参考文章相同。

(2)freertos.c

下面的任务函数代码,CubeMX自动生成函数框架,手动重写函数体:

cpp 复制代码
/* USER CODE BEGIN Header_AppTask_info */
/**
* @brief Function implementing the Task_info thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_AppTask_info */
void AppTask_info(void *argument)
{
	/* USER CODE BEGIN AppTask_info */
	///*----------获取单个任务信息----------*/
	//TaskHandle_t taskHandle=xTaskGetCurrentTaskHandle();				///<获取当前任务句柄
	TaskHandle_t taskHandle=xTaskGetIdleTaskHandle();					///<获取空闲任务句柄
	//TaskHandle_t taskHandle=xTaskGetHandle("Task_ADC");				///<通过任务名称获取句柄
	//TaskHandle_t taskHandle=Task_ADCHandle;							///<直接使用句柄变量
 
	TaskStatus_t taskInfo;												///<任务信息
	BaseType_t getFreeStackSpace=pdTRUE;								///<是否获取高水位值
	eTaskState taskState=eInvalid;										///<当前任务状态
	vTaskGetInfo(taskHandle, &taskInfo, getFreeStackSpace, taskState);	///<获取任务信息
	taskENTER_CRITICAL();												///<开始临界代码段,禁止任务调度
 
	printf("Task_Info: Show task info and get it by vTaskGetInfo(). \r\n");
 
	printf("Task Name       = %s\r\n",taskInfo.pcTaskName);
	printf("Task Number     = %ld\r\n",taskInfo.xTaskNumber);
	printf("Task State      = %d\r\n",taskInfo.eCurrentState);
	printf("Task Priority   = %ld\r\n",taskInfo.uxCurrentPriority);
	printf("High Water Mark	= %d\r\n\r\n",taskInfo.usStackHighWaterMark);
 
	///*----------获取每个任务的高水位值----------*/
	printf("Task_Info: Get High Water Mark of tasks. \r\n");
 
	taskHandle=xTaskGetIdleTaskHandle();
	UBaseType_t  hwm=uxTaskGetStackHighWaterMark(taskHandle);
	printf("Idle Task	= %ld\r\n",hwm);
 
	taskHandle=Task_ADCHandle;
	hwm=uxTaskGetStackHighWaterMark(taskHandle);
	printf("Task_ADC 	= %ld\r\n",hwm);
 
	taskHandle=Task_infoHandle;
	hwm=uxTaskGetStackHighWaterMark(taskHandle);
	printf("Task_Info 	= %ld\r\n\r\n",hwm);
 
	///*----------获取内核信息----------*/
	printf("Task_Info: Get Kernel Info. \r\n");
	UBaseType_t  taskNum=uxTaskGetNumberOfTasks();		            ///<获取任务数量
	printf("uxTaskGetNumberOfTasks() = %ld\r\n\r\n",taskNum);
 
	char infoBuffer[300];
	vTaskList(infoBuffer);											///<返回字符串表格,用/t/n制表
	printf("vTaskList: \r\n");
	printf("TaskName     Status Priority HighLevel Index\r\n");
	printf("%s\r\n",infoBuffer);
 
	taskEXIT_CRITICAL();											///<结束临界代码段,允许任务调度
 
 
	UBaseType_t loopCount=0;
	/* Infinite loop */
	for(;;)
	{
		loopCount++;
		HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_6);					   ///<PA6=LED1 flashing
		vTaskDelay(pdMS_TO_TICKS(3000));
 
		if (loopCount==10)										   ///<循环10次后退出
			break;
		printf("Task_Info is deleted,and then only Task_ADC is running. \r\n\r\n");
		vTaskDelete(NULL);										   ///<删除任务自身
	}
	/* USER CODE END AppTask_info */
}

其它部分的代码与参考项目完全相同。

(3)FreeRTOSConfig.h

使用一些函数,如函数xTaskGetIdleTaskHandle()时,可能会出现编译错误,显示这个函数未定义。这是因为在源程序tasks.c中,这个函数有个预编译条件,只有当参数INCLUDE_xTaskGetldleTaskHandle值为1时,才编译这个函数。CubeMX中没有这个参数的对应设置项,而文件FreeRTOS.h中,这个参数的默认值为0。我们需要将这个参数的值修改为1,但是要注意,不能在文件FreeRTOS.h中直接修改这个参数的值,而要在文件FreeRTOSConfig.h的用户代码沙箱段内,重新定义这个宏,即下面的代码:

cpp 复制代码
​
/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
//xTaskGetIdleTaskHandle()
#define INCLUDE_xTaskGetIdleTaskHandle 1

//vTaskList()
#define configUSE_TRACE_FACILITY	1
#define configUSE_STATS_FORMATTING_FUNCTIONS	1
#define configSUPPORT_DYNAMIC_ALLOCATION	1

/* USER CODE END Defines */

​

这个沙箱段在文件FreeRTOSConfig.h中的最下方,就是用于重新定义一些无法在CubeMX中可视化设置的参数,用于替换其在文件FreeRTOS.h中的默认定义。

三、运行与调试

构建项目后,将其下载到开发板上并运行,可以在串口助手上看到各种信息。任务Task_ADC周期性地通过ADC3采集电压值,并在串口助手上显示;任务Task_Info读取的信息在串口助手上显示,LED1闪烁几次后,任务Task_Info被删除,LED1不再闪烁,修改延迟时间会小小改变删除任务的效果。这个结果与参考文章的结果相同。

不同于参考文章,本示例的运行结果还包含主要考察的函数vTaskList()的应用效果:

相关推荐
照海19Gin25 分钟前
数据结构中的宝藏秘籍之广义表
c语言·数据结构·算法
加点油。。。。44 分钟前
C语言高频面试题——strcpy与memcpy区别
c语言·开发语言
光算科技1 小时前
服务器在国外国内用户访问慢会影响谷歌排名吗?
运维·服务器·c++
大炮筒1 小时前
CPPlist初识
数据结构·c++·list
电子艾号哲1 小时前
Vscode开发STM32标准库
ide·vscode·stm32
双叶8361 小时前
(51单片机)LCD显示数据存储(DS1302时钟模块教学)(LCD1602教程)(独立按键教程)(延时函数教程)(I2C总线认识)(AT24C02认识)
c语言·数据库·单片机·嵌入式硬件·mongodb·51单片机·nosql
那就摆吧1 小时前
数据结构-栈
android·java·c语言·数据结构
L_09071 小时前
【C】初阶数据结构10 -- 希尔排序
c语言·数据结构·排序算法
wutianxin02 小时前
硬件测试项之电源纹波的测量和纹波的要求、纹波的抑制
嵌入式硬件·硬件工程
格里姆肖2 小时前
HAL库通过FATFS和SDIO+DMA写入SD卡数据错误
c语言·stm32·单片机