IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> FreeRTOS-任务运行时间统计 -> 正文阅读

[嵌入式]FreeRTOS-任务运行时间统计

FreeRTOS-任务运行时间统计

引入

  • 上一章节中我们讲述了任务信息获取,我们已经能够获取绝大部分任务信息了,但是任务还有一个很重要的信息,那就是运行时间。如果我们知道了每个任务的运行时间和占比我们就可以更合理的分配任务。在统计运行时间前,我们还需要做一些准备工作。
  • 我们已经知道了FreeRTOS是有一个系统时钟的,但是这个系统时钟的时基是以1ms(个人配置)为周期的,对于一些耗时小于1ms的任务是不能很好地统计的,所以我们还需要额外提供一个更加精确地时基,一般是系统时钟的20-30倍。在单片机中,利用定时器中断可以很容易提供一个固定周期的时基,因此我们需要配置一个定时器产生33.3us-50us的时钟脉冲(这里我们配置周期为50us)。下面逐步讲述这些配置步骤。

配置步骤

FreeRTOSConfig.h文件配置

  • 首先需要将configGENERATE_RUN_TIME_STATS = 1,启用运行时间统计功能。编译文件。
    在这里插入图片描述

  • 可见,报了很多错误。错误提示如下:

    • If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
    • If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information.
  • 上面错误提示意思是,如果刚刚我们定义的configGENERATE_RUN_TIME_STATS 这个宏被置1后,那么portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 这个宏也需要被定义,并且该宏能够调用一个函数去启动一个定时器来提供时基。另一个的意思是我们还需要定义一个portGET_RUN_TIME_COUNTER_VALUE,该宏是一个变量,用以记录定时器中断次数。

  • 在了解上面的错误提示之后,接下来我们在FreeRTOS.h文件中补充相关定义如下:
    在这里插入图片描述

  • 其中FreeRTOSRunTimeTicks为定义的一个变量(在timer.c文件中定义,变量名可以自己定义),用以记录定时器中断次数,其定义如下:

    unsigned long long FreeRTOSRunTimeTicks = 0;
  • ConfigureTimerForRunTimeStats()为定义的定时器初始化函数,也被定义在timer.c文件中(函数名可以自己定义)。系统会自动调用该函数初始化时基。

精准时基配置

  • 下面是定时器配置的代码。
volatile unsigned long long FreeRTOSRunTimeTicks = 0;


void ConfigureTimerForRunTimeStats(void)
{
	TIM_TimeBaseInitTypeDef		TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef					NVIC_InitStruct;		
	
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up ;
	TIM_TimeBaseInitStruct.TIM_Period = 36-1;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 100-1;

	TIM_TimeBaseInit (TIM2,&TIM_TimeBaseInitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init (&NVIC_InitStruct);
	
	TIM_ITConfig (TIM2,TIM_IT_Update,ENABLE);
	TIM_ClearITPendingBit (TIM2,TIM_IT_Update);
	TIM_Cmd (TIM2,ENABLE);
}


void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus (TIM2,TIM_IT_Update) == SET)
	{
		FreeRTOSRunTimeTicks++;
	}
		TIM_ClearITPendingBit (TIM2,TIM_IT_Update);
}

  • 这里使用stm32f103的定时器2,将其周期配置为50us,中断优先级为1,不受FreeRTOS的管理。完成上述步骤后,函数声明和变量声明通过extern关键字引用到FreeRTOSConfig.h文件中。再次编译,无误。

测试

vTaskGetRunTimeStats()

  • 该函数既可以获取每个任务运行时间,也可以自动计算每个任务的运行时间占比,函数声明如下:
void vTaskGetRunTimeStats( char *pcWriteBuffer )
  • 该函数很简单,只有字符指针这一个输入参数,该输入参数需要用户自己定义,调用该函数后,只需要将字符指针中的值打印出来即可得到任务运行时间信息。用法示例:
char InfoBuffer[200];
void runTim_task(void* pvParameters)
{
	while(1)
	{
		if ( (keyFlag&0x01) == 0x01)
		{
			vTaskGetRunTimeStats(InfoBuffer);
			printf("%s\r\n",InfoBuffer);
		}
		vTaskDelay(1000);
	}
}

运行结果如下:
在这里插入图片描述
第一列为任务名称,第二列为函数运行时间,第三列为运行时间占比。

vTaskGetInfo()

  • 上一章节中我们使用vTaskGetInfo()获取了除ulRunTimeCounter以外所有的任务信息,这一章节因为补充了相关宏定义以及时基,我们同样可以使用该函数获取任务运行时间。用法示例如下:

void runTim_task(void* pvParameters)
{
	TaskStatus_t TaskStatus;
	while(1)
	{
		if ( (keyFlag&0x01) == 0x01)
		{
			vTaskGetInfo(KeyTask_Handler,&TaskStatus,pdTRUE,eInvalid);
			printf("Key Task Run Time Counter = %d\r\n",TaskStatus.ulRunTimeCounter);
			vTaskGetRunTimeStats(InfoBuffer);
			printf("%s\r\n",InfoBuffer);
		}
		vTaskDelay(1000);
	}
}
  • 这里我们只获取了KeyTask任务运行时间,运行结果如下:
    在这里插入图片描述
    可见两个函数获取的计数值是一样的。

vGetSystemState()

  • 与 vTaskGetInfo()可以获得任务运行时间,那么vGetSystemState()同样也可以,并且该函数还可以获得系统总运行时间。用法示例如下:

void runTim_task(void* pvParameters)
{
	u8 i=0;
	TaskStatus_t TaskStatus;
	
	TaskStatus_t*  TaskStatusArray;
	UBaseType_t ArraySize;
	uint32_t* TotalRunTime;
	ArraySize = uxTaskGetNumberOfTasks();
	TaskStatusArray = pvPortMalloc(sizeof(TaskStatus_t)* ArraySize);
	TotalRunTime = pvPortMalloc(sizeof(uint32_t));
	
	while(1)
	{
		if ( (keyFlag&0x01) == 0x01)
		{
			vTaskGetInfo(KeyTask_Handler,&TaskStatus,pdTRUE,eInvalid);
			printf("Key Task Run Time Counter = %d\r\n",TaskStatus.ulRunTimeCounter);
			uxTaskGetSystemState(TaskStatusArray,ArraySize,TotalRunTime);
			printf("System Total Run Time=%d\r\n",*TotalRunTime);
			for (i=0; i<ArraySize-1;i++)
			{
				printf("%s\t%d\r\n",TaskStatusArray[i].pcTaskName,TaskStatusArray[i].ulRunTimeCounter);
			}
			vTaskGetRunTimeStats(InfoBuffer);
			printf("%s\r\n",InfoBuffer);
		}
		vTaskDelay(1000);
	}
}


运行结果如下:
在这里插入图片描述
因为任务运行时间统计是在runTim_task函数中进行的,所以除了runTim_task对应的时间项不同外,其他均相同。

到这里我们就将FreeRTOS中所有获取任务状态信息的函数讲述完了,主要就是vTaskGetInfo()、uxTaskGetSystemState()、vTaskGetRunTimeStats()这三个函数。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-06 11:19:00  更:2021-09-06 11:19:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:37:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码