声明及感谢: 跟随正点原子资料学习, 在此作为学习的记录和总结
环境 keil , stm32f103
API函数预览:
uxTaskPriorityGet():查询某个任务的优先级
vTaskPrioritySet():改变某个任务的任务优先级
uxTaskGetSystemState():获取系统中任务状态
vTaskGetInfo():获取某个任务信息
xTaskGetApplicationTaskTag():获取某个任务的标签(Tag)值
xTaskGetCurrentTaskHandle():获取当前正在运行的任务的任务句柄
xTaskGetHandle():根据任务名字查找某个任务的句柄
xTaskGetIdleTaskHandle():获取空闲任务的任务句柄
uxTaskGetStackHighWaterMark():获取任务的堆栈的历史剩余最小值,FreeRTOS 中叫做“高水位线”
eTaskGetState():获取某个任务的壮态,这个壮态是 eTaskState 类型
pcTaskGetName():获取某个任务的任务名字
xTaskGetTickCount():获取系统时间计数器值
xTaskGetTickCountFromISR():在中断服务函数中获取时间计数器值
xTaskGetSchedulerState():获取任务调度器的状态,开启或未开启
uxTaskGetNumberOfTasks():获取当前系统中存在的任务数量
vTaskList():以一种表格的形式输出当前系统中所有任务的详细信息
vTaskGetRunTimeStats():获取每个任务的运行时间
vTaskSetApplicationTaskTag():设置任务标签(Tag)值
SetThreadLocalStoragePointer():设置线程本地存储指针
GetThreadLocalStoragePointer():获取线程本地存储指针
1. UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ) // 获取某个任务的优先级
参数: xTask 传入任务句柄
unsigned portBASE_TYPE Priority;
Priority = uxTaskPriorityGet(Led0Task_Handler);
// 打印 Priority 即可看到 Led0Task_Handler 任务的优先级
2. vTaskPrioritySet()
设置任务的优先级
vTaskPrioritySet(Led0Task_Handler, 10);
// 给 Led0Task_Handler 任务句柄的任务设置优先级为10;
// 可以使用步骤1查看任务修改后的优先级.
3.uxTaskGetSystemState
// 获取系统所有任务的状态.
u32 TotalRunTime; // 系统总运行时间
UBaseType_t ArraySize,x; //
TaskStatus_t *StatusArray;
ArraySize = uxTaskGetNumberOfTasks(); // 获取系统任务数量
StatusArray = pvPortMalloc(ArraySize*sizeof(TaskStatus_t)); // 申请内存
if(StatusArray!=NULL) // 内存申请成功
{
ArraySize=uxTaskGetSystemState((TaskStatus_t* )StatusArray, // 任务信息存储区域地址
(UBaseType_t )ArraySize, // 任务信息数组大小
(uint32_t* )&TotalRunTime); // 系统运行总时间
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); // 任务编号, 由任务创建先后顺序决定
}
}
可以看出任务的信息主要类型 主要看 TaskStatus_t 类型的结构体成员. 观察成员, 即可 知道可以了解什么信息.
注意,这个函数仅用来调试用,调用此函数会挂起所有任务,直到函数最后才恢复挂起的任务,因此任务可能被挂起很长时间。在文件FreeRTOSConfig.h中,宏configUSE_TRACE_FACILITY必须设置为1,此函数才有效。
4.vTaskGetInfo():获取某个任务信息
/*
* TaskHandle_t xTaskGetHandle( const char *pcNameToQuery )
* void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus,
* BaseType_t xGetFreeStackSpace, eTaskState eState )
*/
TaskHandle_t TaskHandle;
TaskStatus_t TaskStatus;
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",(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);
// 实验现象
任务名: led0_task
任务编号: 4
任务壮态: 2
任务当前优先级: 2
任务基优先级: 2
任务堆栈基地址: 0x200012e8
任务堆栈历史剩余最小值: 108
5.eTaskGetState
// 获取某个任务的状态
eTaskState TaskState;
TaskState=eTaskGetState(TaskHandle); // 传参是 任务句柄
返回值为 此枚举类型
typedef enum
{
eRunning = 0, // 运行
eReady, // 就绪
eBlocked, // 阻塞
eSuspended, // 暂停
eDeleted, // 删除
eInvalid // 无效的
} eTaskState;
6.vTaskList():
以一种表格的形式输出当前系统中所有任务的详细信息
char InfoBuffer[1000];
vTaskList(InfoBuffer); // 获取系统任务的信息保存在InfoBuffer 数组中
打印 InfoBuffer 会看到如下信息
query_task R 3 192 5
IDLE R 0 108 2
led0_task B 2 108 4
Tmr Svc S 31 236 3
信息中每一列代表含义
任务名称 任务状态 任务优先级 任务剩余堆栈大小 任务编号
使用此功能需要 将这两个宏定义
configUSE_TRACE_FACILITY 1
configUSE_STATS_FORMATTING_FUNCTIONS 1
最后 在任务状态中
R 表示 就绪
B 表示 阻塞
S 表示 暂停
7.xTaskGetHandle()
// 根据任务名称获取任务句柄
TaskHandle_t TaskHandle;
TaskHandle=xTaskGetHandle(“query_task”); // 参数传入任务名称 ,返回值 为任务句柄
8.vTaskGetRunTimeStats
统计任务的运行时间信息
要使用此函数的话需要将
configGENERATE_RUN_TIME_STATS 和 configUSE_STATS_FORMATTING_FUNCTIONS
的宏定义定为1.
需要实现 两个宏
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
portGET_RUN_TIME_COUNTER_VALUE()
// 首先注意这两个宏虽然不需要传参数, 但是需要括号的。
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 这个宏用来初始化时间统计功能所需的时基, 一般是定时器/计数器。
这个时钟时基比系统时钟高10~20倍。
portGET_RUN_TIME_COUNTER_VALUE 这个宏 是当前时基的值。
示例:
宏定义设置
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ConfigureTimeForRunTimeStats() // 定时器3 提供时间统计的时基, 频率为20K 即周期为50us
#define portGET_RUN_TIME_COUNTER_VALUE() FreeRTOSRunTimeTicks // 获取时间统计值 ,一个全局变量
宏定义实现
// FreeRTOS时间统计所有的节拍计数器
volatile unsigned long long FreeRTOSRunTimeTicks; // 使用 unsigned long long 防止溢出
// 初始化TIM3使其为FreeRTOS的时间统计提供时基
void ConfigureTimeForRunTimeStats(void)
{
// 定时器3初始化, 定时器时钟为72M, 分频系数为72-1,所以定时器3的频率
// 为72/72=1M , 自动重装载为50-1,那么定时器周期就是50us
FreeRTOSRunTimeTicks=0;
TIM3_Int_Init(50-1,72-1); //³õʼ»¯TIM3
}
// 定时器3中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) // 溢出中断
{
FreeRTOSRunTimeTicks++; // 计数器自增
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); // 清除中断标志位
}
具体使用
// 在任务中使用
void RunTimeStats_task(void *pvParameters)
{
u8 key=0;
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
memset(RunTimeInfo,0,400); // 信息缓冲区清理
vTaskGetRunTimeStats(RunTimeInfo); // 获取任务运行时间信息
printf("%s\r\n",RunTimeInfo); // 打印出信息
}
vTaskDelay(10); // 延时10ms
}
}
// 串口输出信息
一共三列, 分别表示 任务名称, 任务运行时间。 运行所占百分比
在运行时间中,需要将其值 * 时基
vTaskGetRunTimeStats 此功能只能在调式阶段使用, 因为实现此功能较占系统时间。