FreeRTOS任务函数 - 4统计任务运行时间信息

1 任务运行时间信息统计函数

FreeRTOS 提供了一个用于统计系统中任务运行时间信息的函数vTaskGetRunTimeStats()。该函数的原型如下。

void vTaskGetRunTimeStats( char *pcWriteBuffer );

参数说明如下。
pcWriteBuffer:       保存任务运行时间信息的存储区。
返回值:无。

使用 vTaskGetRunTimeStats()函数需要将宏 configGENERATE_RUN_TIME_STATS、configUSE_TRACE_FACILITY 及 configUSE_STATS_FORMATTING_FUNCTIONS都设置为1,同时用户还需在FreeRTOSConfig.h头文件中实现如下两个宏。
pOrtCONFIGURE_TIMIER_FOR_RUN_TIMESTATS():用于初始化任务运行时间信息统计功能的时间基准。时间基准一般使用定时器来提供,并且要求这个定时器的精度是系统时钟节拍精度的10倍以上。

portGET_RUN_TIME_COUNTER_VALUE():用于获取统计任务运行时间信息的计数器值,利用这个计数值来计算各任务运行时间百分比。
注意 :使用vTaskGetRunTimeStats()函数会降低系统的实时性。一般用于代码调式阶段。

2 任务运行时间信息统计示例

本示例在任务状态信息获取示例的基础上,增加任务运行时间信息统计功能。通过appStartTask()函数,创建3个FreeRTOS任务。
任务1的任务函数为Led0Task(),其功能是使LEDO每秒闪烁1次,优先级为3。
任务2的任务函数为Led1Task(),其功能是使LED1每秒闪烁2次,优先级为2。

任务3的任务函数为getTaskInfo(),其功能是当Key1按键被按下时,获取所有任务状态信息并通过串口发送;当Key1按键被按下时,获取所有任务运行时间信息并通过串口发送,优先级为4。

2.1 配置时间基准

要使用任务运行时间信息统计功能,需要一个精度是系统时钟节拍精度10倍以上的时间基准。本示例使用基本定时器TIM2来提供这个时间基准。
代码配置:


#include "stm32f10x.h"                  // Device header
#include "Timer.h"

volatile unsigned long long ullTimerCount = 0;   //用于任务运行时间信息统计的计数器

void Timer_Init(){
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	TIM_InternalClockConfig(TIM2);//开启内部时钟
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period=100 -1 ;//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler=90 -1 ;//PSC
	
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//中断使能  更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2,ENABLE);//开启定时器
	
}


在定时中断中添加任务运行时间信息统计值加1的代码。

void TIM2_IRQHandler(void){

	if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==SET)
	{
	
		ullTimerCount++;  //任务运行时间信息统计值加1
			
		
		TIM_ClearFlag(TIM2,TIM_FLAG_Update);
		
	}

}

2.2 配置任务运行时间信息统计功能

 开启任务运行时间信息统计功能,需要设计一些宏,并实现2个用于初始化计数器及获取统计值的宏。

#define configUSE_TRACE_FACILITY                            1
#define configUSE_STATS_FORMATTING_FUNCTIONS                1
#define configGENERATE_RUN_TIME_STATS                       1

//用于初始化计数器以及获取统计值的宏
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()						(ullTimerCount = 0)					
#define portGET_RUN_TIME_COUNTER_VALUE()										ullTimerCount

2.3 任务函数

/**********************************************************************
函 数 名:Led0Task
形    参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
优 先 级:	3
**********************************************************************/
static void Led0Task(void *pvParameters)
{
	uint32_t testArray[128] ;						//任务中的局部变量

	while(1)
	{
		
		GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_4)));	//LED0闪烁
		
		vTaskDelay(pdMS_TO_TICKS(500));//每秒闪1次
		
		
	}
}
/**********************************************************************
函 数 名:Led1Task

形    参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
优 先 级:	2
**********************************************************************/
static void Led1Task(void *pvParameters)
{
	uint32_t testArray[128] = {0};						//任务中的局部变量

	
	while(1)
	{
		
		
		GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_5)));  //LED1闪烁
		
		vTaskDelay(pdMS_TO_TICKS(250));//每秒闪2次
	
	}	
}
/**********************************************************************
函 数 名:getTaskInfo
功能说明:获取任务状态信息并通过串口发送
形    参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
优 先 级:	1
**********************************************************************/
void getTaskInfo(void *pvParameters)
{
	char pcTaskInfo[800];   //用于保存任务状态信息
	uint8_t ucKeyValue = 0;
	while(1)
	{
		ucKeyValue = Key_getNum();
		if(ucKeyValue == 1)
		{
			vTaskList(pcTaskInfo);
			printf("任务名 	任务状态 	优先级 	剩余堆栈大小 任务号 \r\n");
			printf("%s\r\n",pcTaskInfo);
		}else if(ucKeyValue == 2)
		{
				vTaskGetRunTimeStats(pcTaskInfo);
				printf("任务名\t\t运行时间\t\t百分比\t\t \r\n");
				printf("%s\r\n",pcTaskInfo);
		}
		vTaskDelay(pdMS_TO_TICKS(100)); //阻塞100ms
	}
}

2.4 任务创建

/**********************************************************************
函 数 名:appStartTask
功能说明:任务开始函数,用于创建其他函数并且开启调度器
形    参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
**********************************************************************/
void appStartTask(void)
{
		taskENTER_CRITICAL();   /*进入临界段,关中断*/
		xTaskCreate(Led0Task,"Led0Task",256,NULL,3,&Led0TaskHandle);
		xTaskCreate(Led1Task,"Led1Task",256,NULL,2,&Led1TaskHandle);
		xTaskCreate(getTaskInfo,"getTaskInfo",512,NULL,4,&tskInfoTaskHandle);
		taskEXIT_CRITICAL(); 	/*退出临界段,关中断*/
		vTaskStartScheduler();/*开启调度器*/
}

2.5 下载测试

yH5BAAAAAAALAAAAAAOAA4AAAIMhI+py+0Po5y02qsKADs=wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

图中的运行时间不是真是任务运行时间,再乘以时间基准才是真实的任务运行时间,本例要乘120us。

3 总结

任务管理是FreeRTOS的核心功能,FreeRTOS提供了很多任务函数,比较常用的任务函数有延时函数,优先级控制函数,任务状态信息以及任务运行时间信息获取函数等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值