网站首页

人工智能P2P分享搜索全网发布信息网站地图标签大全

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

实时操作系统FreeRTOS应用之任务调试信息获取

时间:2022-06-08 09:12

人气:

作者:admin

标签: STM32  操作系统  FreeRTOS 

导读:FreeRTOS任务调试信息获取可以很好的作为前期开发调试使用,用于查询各个任务间的堆栈空间利用率,运行状态,CPU利用率等信息。...

1.任务相关函数

1.1获取任务状态函数vTaskGetInfo()

void vTaskGetInfo( TaskHandle_t xTask,TaskStatus_t * pxTaskStatus,

BaseType_t xGetFreeStackSpace, eTaskState eState );

函数功能:获取指定任务的状态,任务状态信息保存在pxTaskStatus中。
使用此函数需要configUSE_TRACE_FACILITY == 1
形参:
xTask 要获取的任务句柄
pxTaskStatus 任务信息结构体变量
xGetFreeStackSpace 常设置为pdTRUE,用来检测堆栈空间历史剩余最小值。值越小说明越近堆栈溢出。
eState 保存任务运行状态。获取任务运行状态时间比较长,为了加快vTaskGetInfo函数执行可直接将 TaskStatus_t中的字段eCurrentState就可以由用户直接赋值,参数eState就是要赋的值。若不考 虑时间因素,可以直接将eState设置为eInvalid,这样任务状态信息就由函数vTaskGetInfo去获取。
返回值 无。

任务信息结构体TaskStatus_t

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; //任务堆栈基地址
configSTACK_DEPTH_TYPE usStackHighWaterMark;//从任务创建以来任务堆栈剩余的最小值,值越小接近 0越有溢出风险
} TaskStatus_t;

任务状态 eTaskState

typedef enum
{
eRunning = 0, //运行状态
eReady, //就绪
eBlocked, //阻塞
eSuspended, //挂起
eDeleted, //删除
eInvalid //无效
} eTaskState;

1.2 查询每个任务运行时间vTaskGetRunTimeStats()

void vTaskGetRunTimeStats( char * pcWriteBuffer )
形参
pcWriteBuffer --- 保存任务时间信息的存储区,存储区要足够大来保存该信息
函数功能
查询每个任务的运行时间。使用此函数需要( configGENERATE_RUN_TIME_STATS == 1 ) && (configUSE_STATS_FORMATTING_FUNCTIONS>0)&&(configSUPPORT_DYNAMIC_ALLOCATION == 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这二者实现其中一个,这两个宏用于提供当前时基的时间值。

1.3 查询任务详细信息vTaskList()

void vTaskList( char * pcWriteBuffer )
形参:
char * pcWriteBuffer -- 保存任务状态信息。

函数功能:查询任务任务详细信息,使用此函数( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )&&( configSUPPORT_DYNAMIC_ALLOCATION == 1 )。
表信息包括任务名称、任务状态、优先级、堆栈剩余空间大小、任务编号
任务状态: 运行状态(X)、阻塞(B)、就绪(R)、删除(D)、挂起(S)
任务编号:这个编码每个任务都是唯一的,当多个任务使用同一任务名时可以通过此编号来区分。

2 示例

2.1 创建任务

#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);         //任务函数

#define Quer_TASK_PRIO 2     //任务优先级
#define Quer_STK_SIZE 128      //任务堆栈大小
TaskHandle_t QuerTask_Handler; //任务句柄
void Query_task(void);          //任务函数
int main()
{
	Beep_Init();//蜂鸣器初始化
	LED_Init();//LED初始化
	KEY_Init();
	Usart1_Init(115200);//串口1初始化
	/*创建任务*/
	xTaskCreate((TaskFunction_t)start_task,//任务函数
							(const char *)"start_task",//任务名称	
							(uint16_t)START_STK_SIZE,//堆栈大小
							NULL,           //传递给任务函数的参数
							(UBaseType_t)START_TASK_PRIO,//任务优先级
							(TaskHandle_t *)&StartTask_Handler//任务句柄
							);
	vTaskStartScheduler();     //开启任务调度		
}
/*开始任务函数*/
void start_task(void *pvParameters)
{
	taskENTER_CRITICAL();  //进入临界区
	//创建LED0任务
	xTaskCreate( (TaskFunction_t  )LED0_task,//任务函数
				(const char    *)"LED0_task",//任务名称
				 (uint16_t)LED0_STK_SIZE,//堆栈大小
					NULL,           //传递给任务函数的参数
				 (UBaseType_t   )LED0_TASK_PRIO,//任务优先级
				 (TaskHandle_t *)&LED0Task_Handler);//任务句柄
	xTaskCreate(  (TaskFunction_t )Query_task,//任务函数
				(const char    *)"Query_task",//任务名称
				(uint16_t )Quer_STK_SIZE,//堆栈大小
				NULL,           //传递给任务函数的参数
				(UBaseType_t    )Quer_TASK_PRIO,//任务优先级
				(TaskHandle_t  *)&QuerTask_Handler);//任务句柄
	vTaskDelete(StartTask_Handler); //删除开始任务	
	taskEXIT_CRITICAL();            //退出临界区						
}

2.2 任务1 程序正常运行LED指示灯

void LED0_task(void)
{
	while(1)
	{
		LED1=!LED1;
		Delay_Ms(500);
	}
}

2.3 任务2:通过按键查询任务状态

char RunTimeInfo[400];//保存任务信息
void Query_task(void)//任务函数
{
	u8 key;
	TaskStatus_t task_info;//保存任务信息
	while(1)
	{
		key=KEY_GetVal();
		if(key==1)//获取任务运行时间,任务运行时间FreeRTOSRunTimeTicks*50us
		{
			memset(RunTimeInfo,0,400);
			vTaskGetRunTimeStats(RunTimeInfo);//获取每个任务运行时间
			printf("%s\r\n",RunTimeInfo);
		}
		if(key==2)//获取任务状态
		{
			vTaskGetInfo(NULL,&task_info,pdTRUE,eInvalid);//获取当前任务状态
			printf("task name:%s\r\n",task_info.pcTaskName);//任务名
			printf("task num:%ld\r\n",task_info.xTaskNumber);//任务编号
			printf("task stat:%d\r\n",task_info.eCurrentState);//任务状态
			printf("task baseaddr:%p\r\n",task_info.pxStackBase);//任务堆栈基地址
			printf("task priority:%ld\r\n",task_info.uxBasePriority);//任务基础优先级
			printf("tast now priority:%ld\r\n",task_info.uxCurrentPriority);//任务当前优先级
			printf("tast memory size:%d\r\n",task_info.usStackHighWaterMark);//任务历史剩余堆栈最小空间
			printf("tast time:%d\r\n",task_info.ulRunTimeCounter);//任务运行总时间	
		}
		if(key==3)//查询任务详细信息
		{
			memset(RunTimeInfo,0,400);
			vTaskList(RunTimeInfo);//获取任务状态信息
			printf("%s\r\n",RunTimeInfo);
		}
		Delay_Ms(10);
	}
}

2.4 获取任务运行时间

(1)获取任务运行时间时需要提供时间基准,要设置相应的宏,在FreeRTOSconfig.h中

#define configGENERATE_RUN_TIME_STATS	   1     //为1时启用运行时间统计功能 
#define configUSE_STATS_FORMATTING_FUNCTIONS   1
#define configSUPPORT_DYNAMIC_ALLOCATION     1        //支持动态内存申请

(2)提供相应时间基准函数,在timer.h中。
设置时间基准函数用户只需要产生时基单元,设置好相关的宏,不需要用户调用。在设置时间基准需要保证该时间基准的频率高于FreeRTOS系统频率,要是系统频率的10~20倍。
本示例的FreeRTOS系统频率为configTICK_RATE_HZ ( ( TickType_t ) 1000 ) ,也就是FreeRTOS系统时间为1ms,所以获取任务运行时间的时间基准为50us。

/*******用于给FreeRTOS计算任务运行时间提供时间基准*******/
volatile unsigned long long FreeRTOSRunTimeTicks;
void ConfigureTimeForRunTimeStas(void)//不需要用户调用,只需实现功能即可
{
	FreeRTOSRunTimeTicks=0;
	Tim1_Init(72,50);//初始化定时器1,周期50us,cnt+1时间为1us
}
void TIM1_UP_IRQHandler(void)
{
	if(TIM1->SR&1<<0)
	{
		FreeRTOSRunTimeTicks++;//运行时间统计基数计数器+1
	}
	TIM1->SR=0;//清除标志	
}

(3)通过#define进行宏定义,给获取任务时间函数vTaskGetRunTimeStats()提供时间基准接口。在FreeRTOSconfig.h中。

//用于给获取任务函数提供时间基准
#defineportCONFIGURE_TIMER_FOR_RUN_TIME_STATS()  ConfigureTimeForRunTimeStas() 
//用于提供当前时间基准变量 unsigned long long类型
#define portGET_RUN_TIME_COUNTER_VALUE()  FreeRTOSRunTimeTicks 

获取任务运行时间

pYYBAGKXDs6ADoxkAABt65t6uA0899.png

2.5 获取指定任务信息

获取指定任务信息需要设置宏configUSE_TRACE_FACILITY == 1,在FreeRTOSconfig.h中。

#define configUSE_TRACE_FACILITY	1       //为1启用可视化跟踪调试

执行结果:

pYYBAGKXD0GAasBxAAArvYnoq50322.png

2.6 列表方式获取任务详细信息

列表方式获取任务详细信息设置宏,FreeRTOSconfig.h中。

#define configUSE_TRACE_FACILITY	1       //为1启用可视化跟踪调试
#define configUSE_STATS_FORMATTING_FUNCTIONS	1 
#define configSUPPORT_DYNAMIC_ALLOCATION     1      //支持动态内存申请

执行结果:

pYYBAGKXD42AH4zYAAAUVxt7oEw075.png

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信