正点原子FreeRTOS(中)

Posted 行稳方能走远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正点原子FreeRTOS(中)相关的知识,希望对你有一定的参考价值。

目录

第十一章FreeRTOS 其他任务API 函数

前面几章我们花费了大量的精力来学习FreeRTOS 的任务管理,但是真正涉及到的与任务
相关的API 函数只有那么几个。但是FreeRTOS 还有很多与任务相关的API 函数,不过这些API
函数大多都是辅助函数了,本章我们就来看一下这些与任务相关的其他的API 函数。本章分为
如下几部分:
11.1 任务相关API 函数预览
11.2 任务相关API 函数详解
11.3 任务壮态查询API 函数实验
11.4 任务运行时间壮态统计实验

11.1 任务相关API 函数预览

先通过一个表11.1.1 来看一下这些与任务相关的其他API 函数都有哪些:

这些API 函数在FreeRTOS 官网上都有,如图11.1.2 所示:

11.2 任务相关API 函数详解

1、函数uxTaskPriorityGet()
此函数用来获取指定任务的优先级,要使用此函数的话宏INCLUDE_uxTaskPriorityGet 应
该定义为1,函数原型如下:

UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )

参数:
xTask:要查找的任务的任务句柄。
返回值:获取到的对应的任务的优先级。

2、函数vTaskPrioritySet()
此函数用于改变某一个任务的任务优先级,要使用此函数的话宏
INCLUDE_vTaskPrioritySet 应该定义为1,函数原型如下:

void vTaskPrioritySet( TaskHandle_t xTask,
						UBaseType_t uxNewPriority )

参数:
xTask:要查找的任务的任务句柄。
uxNewPriority: 任务要使用的新的优先级,可以是0~ configMAX_PRIORITIES – 1。
返回值:无。

3、uxTaskGetSystemState()
此函数用于获取系统中所有任务的任务壮态,每个任务的壮态信息保存在一个TaskStatus_t
类型的结构体里面,这个结构体里面包含了任务的任务句柄、任务名字、堆栈、优先级等信息,
要使用此函数的话宏configUSE_TRACE_FACILITY 应该定义为1,函数原型如下:

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

参数:
pxTaskStatusArray:指向TaskStatus_t 结构体类型的数组首地址,每个任务至少需要一个
TaskStatus_t 结构体,任务的数量可以使用函数
uxTaskGetNumberOfTasks()。结构体TaskStatus_t 在文件task.h 中有如下
定义:

typedef struct xTASK_STATUS

	TaskHandle_t xHandle; //任务句柄
	const char * pcTaskName; //任务名字
	UBaseType_t xTaskNumber; //任务编号
	eTaskState eCurrentState; //当前任务壮态,eTaskState 是一个枚举类型
	UBaseType_t uxCurrentPriority; //任务当前的优先级
	UBaseType_t uxBasePriority; //任务基础优先级
	uint32_t ulRunTimeCounter;//任务运行的总时间
	StackType_t * pxStackBase; //堆栈基地址
	uint16_t usStackHighWaterMark; //从任务创建以来任务堆栈剩余的最小大小,此
	//值如果太小的话说明堆栈有溢出的风险。
 TaskStatus_t;

uxArraySize: 保存任务壮态数组的数组的大小。
pulTotalRunTime: 如果configGENERATE_RUN_TIME_STATS 为1 的话此参数用来保存系
统总的运行时间。
返回值:统计到的任务壮态的个数,也就是填写到数组pxTaskStatusArray 中的个
数,此值应该等于函数uxTaskGetNumberOfTasks()的返回值。如果参数
uxArraySize 太小的话返回值可能为0。
4、函数vTaskGetInfo()
此函数也是用来获取任务壮态的,但是是获取指定的单个任务的壮态的,任务的壮态信息
填充到参数pxTaskStatus 中,这个参数也是TaskStatus_t 类型的。要使用此函数的话宏
configUSE_TRACE_FACILITY 要定义为1,函数原型如下:

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

参数:
xTask:要查找的任务的任务句柄。
pxTaskStatus: 指向类型为TaskStatus_t 的结构体变量。
xGetFreeStackSpace: 在结构体TaskStatus_t 中有个字段usStackHighWaterMark 来保存自任务
运行以来任务堆栈剩余的历史最小大小,这个值越小说明越接近堆栈溢
出,但是计算这个值需要花费一点时间,所以我们可以通过将
xGetFreeStackSpace 设置为pdFALSE 来跳过这个步骤,当设置为pdTRUE
的时候就会检查堆栈的历史剩余最小值。
eState: 结构体TaskStatus_t 中有个字段eCurrentState 用来保存任务运行壮态,
这个字段是eTaskState 类型的,这是个枚举类型,在task.h 中有如下定
义:

typedef enum

	eRunning = 0, //运行壮态
	eReady, //就绪态
	eBlocked, //阻塞态
	eSuspended, //挂起态
	eDeleted, //任务被删除
	eInvalid //无效
 eTaskState;

获取任务运行壮态会耗费不少时间,所以为了加快函数vTaskGetInfo()的执行
速度结构体TaskStatus_t 中的字段eCurrentState 就可以由用户直接赋值,
参数eState 就是要赋的值。如果不在乎这点时间,那么可以将eState 设置为
eInvalid,这样任务的壮态信息就由函数vTaskGetInfo()去想办法获取。
返回值:无。
5、函数xTaskGetApplicationTaskTag()
此函数用于获取任务的Tag(标签)值,任务控制块中有个成员变量pxTaskTag 来保存任务的
标签值。标签的功能由用户自行决定,此函数就是用来获取这个标签值的,FreeRTOS 系统内核
是不会使用到这个标签的。要使用此函数的话宏configUSE_APPLICATION_TASK_TAG 必须为
1,函数原型如下:

TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )

参数:
xTask:要获取标签值的任务对应的任务句柄,如果为NULL 的话就获取当前正在运
行的任务标签值。
返回值:任务的标签值。

6、函数xTaskGetCurrentTaskHandle()
此函数用于获取当前任务的任务句柄,其实获取到的就是任务控制块,在前面讲解任务创
建函数的时候说过任务句柄就是任务控制。如果要使用此函数的话宏
INCLUDE_xTaskGetCurrentTaskHandle 应该为1,函数原型如下:

TaskHandle_t xTaskGetCurrentTaskHandle( void )

参数:无
返回值:当前任务的任务句柄。
7、函数xTaskGetHandle()
此函数根据任务名字获取任务的任务句柄,在使用函数xTaskCreate()或xTaskCreateStatic()
创建任务的时候都会给任务分配一个任务名,函数xTaskGetHandle()就是使用这个任务名字来
查询其对应的任务句柄的。要使用此函数的话宏INCLUDE_xTaskGetHandle 应该设置为1,此
函数原型如下:

TaskHandle_t xTaskGetHandle( const char * pcNameToQuery )

参数:
pcNameToQuery:任务名,C 语言字符串。
返回值:
NULL:没有任务名pcNameToQuery 所对应的任务。
其他值:任务名pcNameToQuery 所对应的任务句柄
8、函数xTaskGetIdleTaskHandle()
此函数用于返回空闲任务的任务句柄,要使用此函数的话宏
INCLUDE_xTaskGetIdleTaskHandle 必须为1,函数原型如下:

TaskHandle_t xTaskGetIdleTaskHandle( void )

参数:无
返回值:空闲任务的任务句柄。

9、函数uxTaskGetStackHighWaterMark()
每个任务都有自己的堆栈,堆栈的总大小在创建任务的时候就确定了,此函数用于检查任
务从创建好到现在的历史剩余最小值,这个值越小说明任务堆栈溢出的可能性就越大!
FreeRTOS 把这个历史剩余最小值叫做“高水位线”。此函数相对来说会多耗费一点时间,所以
在代码调试阶段可以使用,产品发布的时候最好不要使用。要使用此函数的话宏
INCLUDE_uxTaskGetStackHighWaterMark 必须为1,此函数原型如下:

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )

参数:
xTask:要查询的任务的任务句柄,当这个参数为NULL 的话说明查询自身任务(即调用
函数uxTaskGetStackHighWaterMark()的任务)的“高水位线”。
返回值:任务堆栈的“高水位线”值,也就是堆栈的历史剩余最小值。

10、函数eTaskGetState()
此函数用于查询某个任务的运行壮态,比如:运行态、阻塞态、挂起态、就绪态等,返回
值是个枚举类型。要使用此函数的话宏INCLUDE_eTaskGetState 必须为1,函数原型如下:

eTaskState eTaskGetState( TaskHandle_t xTask )

参数:
xTask:要查询的任务的任务句柄。
返回值:返回值为eTaskState 类型,这是个枚举类型,在文件task.h 中有定义,前面讲解
函数vTaskGetInfo()的时候已经讲过了。

11、函数pcTaskGetName()
根据某个任务的任务句柄来查询这个任务对应的任务名,函数原型如下:

char *pcTaskGetName( TaskHandle_t xTaskToQuery )

参数:
xTaskToQuery:要查询的任务的任务句柄,此参数为NULL 的话表示查询自身任务(调
用函数pcTaskGetName())的任务名字
返回值:返回任务所对应的任务名。

12、函数xTaskGetTickCount()
此函数用于查询任务调度器从启动到现在时间计数器xTickCount 的值。xTickCount 是系统
的时钟节拍值,并不是真实的时间值。每个滴答定时器中断xTickCount 就会加1,一秒钟滴答
定时器中断多少次取决于宏configTICK_RATE_HZ。理论上xTickCount 存在溢出的问题,但是
这个溢出对于FreeRTOS 的内核没有影响,但是如果用户的应用程序有使用到的话就要考虑溢
出了。什么时候溢出取决于宏configUSE_16_BIT_TICKS,当此宏为1 的时候xTixkCount 就是
个16 位的变量,当为0 的时候就是个32 位的变量。函数原型如下:

TickType_t xTaskGetTickCount( void )

参数:无。
返回值:时间计数器xTickCount 的值。

13、函数xTaskGetTickCountFromISR()
此函数是xTaskGetTickCount()的中断级版本,用于在中断服务函数中获取时间计数器
xTickCount 的值,函数原型如下:

TickType_t xTaskGetTickCountFromISR( void )

参数:无。
返回值:时间计数器xTickCount 的值。

14、函数xTaskGetSchedulerState()
此函数用于获取FreeRTOS 的任务调度器运行情况:运行?关闭?还是挂起!要使用此函
数的话宏INCLUDE_xTaskGetSchedulerState 必须为1,此函数原型如下:

BaseType_t xTaskGetSchedulerState( void )

参数:无。
返回值:
taskSCHEDULER_NOT_STARTED:调度器未启动,调度器的启动是通过函数
vTaskStartScheduler() 来完成,所以在函数
vTaskStartScheduler() 未调用之前调用函数
xTaskGetSchedulerState()的话就会返回此值。
taskSCHEDULER_RUNNING:调度器正在运行。
taskSCHEDULER_SUSPENDED:调度器挂起。

15、函数uxTaskGetNumberOfTasks()
此函数用于查询系统当前存在的任务数量,函数原型如下:

UBaseType_t uxTaskGetNumberOfTasks( void )

参数:无。
返回值:当前系统中存在的任务数量,此值=挂起态的任务+阻塞态的任务+就绪态的任务
+空闲任务+运行态的任务。

16、函数vTaskList()
此函数会创建一个表格来描述每个任务的详细信息,如图11.2.1 所示

表中的信息如下:
Name:创建任务的时候给任务分配的名字。
State:任务的壮态信息,B 是阻塞态,R 是就绪态,S 是挂起态,D 是删除态。
Priority:任务优先级。
Stack:任务堆栈的“高水位线”,就是堆栈历史最小剩余大小。
Num:任务编号,这个编号是唯一的,当多个任务使用同一个任务名的时候可以通过此
编号来做区分。
函数原型如下:

void vTaskList( char * pcWriteBuffer )

参数:
pcWriteBuffer:保存任务壮态信息表的存储区。存储区要足够大来保存任务状态信息表。
返回值:无

17、函数vTaskGetRunTimeStats()
FreeRTOS 可以通过相关的配置来统计任务的运行时间信息,任务的运行时间信息提供了
每个任务获取到CPU 使用权总的时间。函数vTaskGetRunTimeStats()会将统计到的信息填充到
一个表里面,表里面提供了每个任务的运行时间和其所占总时间的百分比,如图11.2.2 所示:

函数vTaskGetRunTimeStats() 是一个很实用的函数,要使用此函数的话宏
configGENERATE_RUN_TIME_STATS 和configUSE_STATS_FORMATTING_FUNCTIONS 必须
都为1。如果宏configGENERATE_RUN_TIME_STATS 为1 的话还需要实现一下几个宏定义:
●portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),此宏用来初始化一个外设来
提供时间统计功能所需的时基,一般是定时器/计数器。这个时基的分辨率一定要比FreeRTOS
的系统时钟高,一般这个时基的时钟精度比系统时钟的高10~20 倍就可以了。
●portGET_RUN_TIME_COUNTER_VALUE()或者
portALT_GET_RUN_TIME_COUNTER_VALUE(Time),这两个宏实现其中一个就行
了,这两个宏用于提供当前的时基的时间值。
函数原型如下:

void vTaskGetRunTimeStats( char *pcWriteBuffer )

参数:
pcWriteBuffer:保存任务时间信息的存储区。存储区要足够大来保存任务时间信息。
返回值:无

18、函数vTaskSetApplicationTaskTag()
此函数是为高级用户准备的,此函数用于设置某个任务的标签值,这个标签值的具体函数
和用法由用户自行决定,FreeRTOS 内核不会使用这个标签值,如果要使用此函数的话宏
configUSE_APPLICATION_TASK_TAG 必须为1,函数原型如下:

void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
								TaskHookFunction_t pxHookFunction )

参数:
xTask:要设置标签值的任务,此值为NULL 的话表示设置自身任务的标签值。
pxHookFunction:要设置的标签值,这是一个TaskHookFunction_t 类型的函数指针,但是
也可以设置为其他值。
返回值:无

19、函数SetThreadLocalStoragePointer()
此函数用于设置线程本地存储指针的值,每个任务都有它自己的指针数组来作为线程本地
存储,使用这些线程本地存储可以用来在任务控制块中存储一些应用信息,这些信息只属于任
务自己的。线程本地存储指针数组的大小由宏
configNUM_THREAD_LOCAL_STORAGE_POINTERS 来决定的。如果要使用此函数的话宏
configNUM_THREAD_LOCAL_STORAGE_POINTERS 不能为0,宏的具体值是本地存储指针
数组的大小,函数原型如下:

void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
									BaseType_t xIndex,
									void * pvValue )

参数:
xTaskToSet:要设置线程本地存储指针的任务的任务句柄,如果是NULL 的话表示设置任
务自身的线程本地存储指针。
xIndex:要设置的线程本地存储指针数组的索引。
pvValue: 要存储的值。
返回值:无

20、函数GetThreadLocalStoragePointer()
此函数用于获取线程本地存储指针的值,如果要使用此函数的话宏
configNUM_THREAD_LOCAL_STORAGE_POINTERS 不能为0,函数原型如下:

void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
											BaseType_t xIndex )

参数:
xTaskToSet:要获取的线程本地存储指针的任务句柄,如果是NULL 的话表示获取任务自
身的线程本地存储指针。
xIndex:要获取的线程本地存储指针数组的索引。
返回值:获取到的线程本地存储指针的值。

11.3 任务壮态查询API 函数实验

11.3.1 实验程序设计

FreeRTOS 与任务相关的API 函数中有很多是与任务壮态或者信息查询有关的,比如函数
uxTaskGetSystemState()、vTaskGetInfo()、eTaskGetState()和vTaskList()。本实验我们就来学习这

些函数的使用方法。
1、实验目的
学习使用FreeRTOS 与任务壮态或者信息查询有关的API 函数,包括uxTaskGetSystemState()、
vTaskGetInfo()、eTaskGetState()和vTaskList()。
2、实验设计
本实验设计三个任务:start_task、led0_task 和query_task ,这三个任务的任务功能如下:
start_task:用来创建其他2 个任务。
led0_task :控制LED0 灯闪烁,提示系统正在运行。
query_task :任务壮态和信息查询任务,在此任务中学习使用与任务的壮态和信息查询有
关的API 函数。
实验需要一个按键KEY_UP,这四个按键的功能如下:
KEY_UP: 控制程序的运行步骤。
3、实验工程
FreeRTOS 实验11-1 FreeRTOS 任务壮态或信息查询。
4、实验程序与分析
●任务设置
实验中任务优先级、堆栈大小和任务句柄等的设置如下:

#define START_TASK_PRIO 	1 //任务优先级
#define START_STK_SIZE 		128 //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数

#define LED0_TASK_PRIO 2 //任务优先级
#define LED0_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Led0Task_Handler; //任务句柄
void led0_task(void *pvParameters); //任务函数

#define QUERY_TASK_PRIO 3 //任务优先级
#define QUERY_STK_SIZE 256 //任务堆栈大小
TaskHandle_t QueryTask_Handler; //任务句柄
void query_task(void *pvParameters); //任务函数
char InfoBuffer[1000]; //保存信息的数组

●main()函数

int main(void)

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
        delay_init(); //延时函数初始化
        uart_init(115200); //初始化串口
        LED_Init(); //初始化LED
        KEY_Init(); //初始化按键
        LCD_Init(); //初始化LCD
        POINT_COLOR = RED;
        LCD_ShowString(30,10,200,16,16,"ATK STM32F103/407");
        LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 11-1");
        LCD_ShowString(30,50,200,16,16,"Task Info Query");
        LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
        LCD_ShowString(30,90,200,16,16,"2016/11/25");
        //创建开始任务
        xTaskCreate((TaskFunction_t )start_task, //任务函数
                        (const char* )"start_task", //任务名称
                        (uint16_t )START_STK_SIZE, //任务堆栈大小
                        (void* )NULL, //传递给任务函数的参数
                        (UBaseType_t )START_TASK_PRIO, //任务优先级
                        (TaskHandle_t* )&StartTask_Handler); //任务句柄
        vTaskStartScheduler(); //开启任务调度


在main 函数中我们主要完成硬件的初始化,在硬件初始化完成以后创建了任务start_task()
并且开启了FreeRTOS 的任务调度。
●任务函数

//led0 任务函数
void led0_task(void *pvParameters)

        while(1)
        
                LED0=~LED0;
                vTaskDelay(500); //延时500ms,也就是500 个时钟节拍
        

//query 任务函数
void query_task(void *pvParameters)

        u32 TotalRunTime;
        UBaseType_t ArraySize,x;
        TaskStatus_t *StatusArray;
        //第一步:函数uxTaskGetSystemState()的使用
        printf("/********第一步:函数uxTaskGetSystemState()的使用**********/\\r\\n");
        ArraySize=uxTaskGetNumberOfTasks(); //获取系统任务数量(1)
        StatusArray=pvPortMalloc(ArraySize*sizeof(TaskStatus_t)); //申请内存(2)
        if(StatusArray!=NULL) //内存申请成功
        
                ArraySize=uxTaskGetSystemState((TaskStatus_t* )StatusArray, (3)
                                (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", (4)
                                        StatusArray[x].pcTaskName,
                                        (int)StatusArray[x].uxCurrentPriority,
                                        (int)StatusArray[x].xTaskNumber);
                
        
        vPortFree(StatusArray); //释放内存(5)
        printf("/**************************结束***************************/\\r\\n");
        printf("按下KEY_UP 键继续!\\r\\n\\r\\n\\r\\n");
        while(KEY_Scan(0)!=WKUP_PRES) delay_ms(10); //等待KEY_UP 键按下
        //第二步:函数vTaskGetInfo()的使用
        TaskHandle_t TaskHandle;
        TaskStatus_t TaskStatus;
        printf("/************第二步:函数vTaskGetInfo()的使用**************/\\r\\n");
        TaskHandle=xTaskGetHandle("led0_task"); //根据任务名获取任务句柄。(6)
        //获取LED0_Task 的任务信息
        vTaskGetInfo((TaskHandle_t )TaskHandle, //任务句柄(7)
                        (TaskStatus_t* )&TaskStatus, //任务信息结构体
                        (BaseType_t )pdTRUE, //允许统计任务堆栈历史最小剩余大小
                        (eTaskState )eInvalid); //函数自己获取任务运行壮态
        //通过串口打印出指定任务的有关信息。
        printf("任务名: %s\\r\\n",TaskStatus.pcTaskName); (8)
                printf("任务编号: %d\\r\\n",(int)TaskStatus.xTaskNumber);
        printf("任务壮态: %d\\r\\n",TaskStatus.eCurrentState);
        printf("任务当前优先级: %d\\r\\n",(int)TaskStatus.uxCurrentPriority);
        printf("任务基优先级: %d\\r\\n",(int)TaskStatus.uxBasePriority);
        printf("任务堆栈基地址: %#x\\r\\n",(int)TaskStatus.pxStackBase);
        printf("任务堆栈历史剩余最小值:%d\\r\\n",TaskStatus.usStackHighWaterMark);
        printf("/**************************结束***************************/\\r\\n");
        printf("按下KEY_UP 键继续!\\r\\n\\r\\n\\r\\n");
        while(KEY_Scan(0)!=WKUP_PRES) delay_ms(10); //等待KEY_UP 键按下
        //第三步:函数eTaskGetState()的使用
        eTaskState TaskState;
        char TaskInfo[10];
        printf("/***********第三步:函数eTaskGetState()的使用*************/\\r\\n");
        TaskHandle=xTaskGetHandle("query_task"); //根据任务名获取任务句柄。(9)
        TaskState=eTaskGetState(TaskHandle); //获取query_task 任务的任务壮态(10)
        memset(TaskInfo,0,10); //数组清零
        switch((int)TaskState) (11)
        
                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;
        
        printf("任务壮态值:%d,对应的壮态为:%s\\r\\n",TaskState,TaskInfo); (12)
        printf("/**************************结束**************************/\\r\\n");
        printf("按下KEY_UP 键继续!\\r\\n\\r\\n\\r\\n");
        while(KEY_Scan(0)!=WKUP_PRES) delay_ms(10); //等待KEY_UP 键按下
        //第四步:函数vTaskList()的使用
        printf("/*************第三步:函数vTaskList()的使用*************/\\r\\n");
        vTaskList(InfoBuffer); //获取所有任务的信息(13)
        printf("%s\\r\\n",InfoBuffer); //通过串口打印所有任务的信息(14)
        while(1)
        
                LED1=~LED1;
                vTaskDelay(1000); //延时1s,也就是1000 个时钟节拍
        

(1)、使用函数uxTaskGetNumberOfTasks()获取当前系统中的任务数量,因为要根据任务数
量给任务信息数组StatusArray 分配内存。注意,这里StatusArray 是个指向TaskStatus_t 类型的
指针,但是在使用的时候会把他当作一个数组来用。
(2)、调用函数pvPortMalloc()给任务信息数组StatusArray 分配内存,数组是TaskStatus_t 类以上是关于正点原子FreeRTOS(中)的主要内容,如果未能解决你的问题,请参考以下文章

正点原子FreeRTOS

正点原子FreeRTOS(下)

正点原子FreeRTOS(下)

使用HAL对STM32F407ZGT6单片机移植FreeRTOS(参考正点原子)

FreeRTOS 系统时钟节拍和时间管理

FreeRTOS-06任务运行时间信息统计