44 freertosCPU利用频率统计

本文档详细介绍了如何在FreeRTOS操作系统中实现CPU利用率的统计。通过配置定时器,设置全局变量并在定时器中断中自增,结合FreeRTOSConfig.h中的配置选项启用运行时间统计功能。在主函数中调用vTaskGetRunTimeStats()函数获取并打印任务运行时间信息,从而达到监控MCU中任务执行效率的目的。
摘要由CSDN通过智能技术生成

四十四、 freertosCPU利用频率统计

1. Cpu利用率统计试验

在MCU中需要用到一个定时器来做定时

setupMRT(0, MRT_MODE_REPEAT, 20000);//20kHz,循环模式

运行效果:
在这里插入图片描述

  1. 如果 FreeRTOSConfig.h 中定义的时钟节拍是1000Hz(1ms),即有如下定义:
    #define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
    那么定时器的节拍就要是 10000-20000Hz 。

  2. 需要在定时器中定义一个全局变量,并在定时器中断中自加1.

(1). 定义一个全局变量

/* 用于统计运行时间 */
volatile uint32_t CPU_RunTime = 0UL;

(2). 把全局变量加到定时器中断函数中

	//判断中断通道0
	if (int_pend & (MRTn_INTFLAG(0) ))
	{
		CPU_RunTime++;
	}
  1. 需要在 FreeRTOSConfig.h 中做一下定义:
//启用运行时间统计功能
#define configGENERATE_RUN_TIME_STATS	1
//启用可视化跟踪调试
#define configUSE_TRACE_FACILITY		1
/* 与宏 configUSE_TRACE_FACILITY 同时为 1 时会编译下面 3 个函数
* prvWriteNameToBuffer()
* vTaskList(),
* vTaskGetRunTimeStats()
*/
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

extern volatile uint32_t CPU_RunTime;
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (CPU_RunTime = 0ul)
#define portGET_RUN_TIME_COUNTER_VALUE()			(CPU_RunTime)
  1. 主函数中直接调用vTaskGetRunTimeStats()即可。
/* K1键按下 */
//printf ( "KEY1 被按下\n" );
	Board_LED_Toggle(6);
					
	printf("---------------------------------------------\r\n");
	printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
	printf("%s", CpuRunInfo);
	printf("---------------------------------------------\r\n");
					 
	memset(CpuRunInfo,0,sizeof(CpuRunInfo));
					
	vTaskGetRunTimeStats((char*)CpuRunInfo);
	printf("任务名 运行计数 使用率\r\n");
	printf("%s", CpuRunInfo);
	printf("---------------------------------------------\r\n\n");

2. Cpu利用率统计试验源码:


main.c

/**
**************************************************************************************************/
#include <stdio.h>
#include <limits.h>//标准C库文件,定义了各种类型的范围
#include "board.h"
#include "led.h"
#include "key.h"
#include "uart.h"
#include "tim_mrt.h"

/**********************系统相关和硬件接口**************************************/
/*** System oscillator rate and clock rate on the CLKIN pin  ****/
/**/const uint32_t OscRateIn = MAIN_OSC_XTAL_FREQ_HZ;		 /**/
/**/const uint32_t ExtRateIn = EXT_CLOCK_IN_FREQ_HZ;		 /**/
 //系统复位
#define	System_restart	(LPC_SWM->PINENABLE0 = 0xffffffffUL) /**/
/**********************End**************************************/

//static void TIM_CallBack1(void);
//static void TIM_CallBack2(void);

/**********************FreeRTOS操作系统头文件**************************************/
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"//事件头文件
#include "queue.h"//队列头文件
#include "semphr.h"//信号量头文件
#include "timers.h"//软件定时器头文件
/**********************End**************************************/

/**************************** 任务句柄 ********************************/
static xTaskHandle	AppTaskCreate_Handle=NULL;

static xTaskHandle LED_TaskHandle=NULL;
static xTaskHandle KEY_TaskHandle=NULL;



/*************************** 宏定义 ************************************/
#define TASK_STACK_SIZE 32//每个任务的栈大小


/* Sets up system hardware 
**********************************************************************
  * @ 函数名  : BSP_Init
  * @ 功能说明: 板级外设初始化,所有板子上的初始化均可放在这个函数里面
  * @ 参数    :   
  * @ 返回值  : 无
*********************************************************************/
static void prvSetupHardware(void)
{

	SystemCoreClockUpdate();

	DEBUGINIT();
	led_Init() ;	
	Key_INIT();
	MRT_Init();
	DEBUGOUT("%u MHz\n",SystemCoreClock/1000000);
	Board_UARTPutSTR("build date: " __DATE__ " build time: " __TIME__ "\n");

}

/**********************************************************************
 * @ 函数名 :  
 * @ 功能说明:  接收发送通知
 * @ 参数 :
 * @ 返回值 : 无
 ********************************************************************/
static void LED_Task(void* parameter)
{
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 500;
	/* 获取当前的系统时间 */
    xLastWakeTime = xTaskGetTickCount();
	while(1)
	{

		Board_LED_Toggle(0);
		/* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
	}
}


/**********************************************************************
 * @ 函数名 :   
 * @ 功能说明: 发送任务
 * @ 参数 :
 * @ 返回值 : 无
 ********************************************************************/
static void KEY_Task(void* parameter)
{
	u8 CpuRunInfo[200];
	
	u8 ucKeyCode=0;
	while(1)
	{
		u8 key=0;
		if(Scan_Key())
			vTaskDelay(20);
		else continue;
		if(!Scan_Key())continue;
		else
		{
			key=Scan_Key();
			ucKeyCode=key;
		}
		while(Scan_Key()){};//等按键抬起
		
		memset(CpuRunInfo,0,sizeof(CpuRunInfo));
		vTaskList((char *)&CpuRunInfo); //获取任务运行时间信息
			
		if(ucKeyCode)
		{

			switch(ucKeyCode)
			{
				case 1:
				{
					/* K1键按下 */
//					printf ( "KEY1 被按下\n" );
					Board_LED_Toggle(6);
					
					printf("---------------------------------------------\r\n");
					printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
					printf("%s", CpuRunInfo);
					printf("---------------------------------------------\r\n");
					 
					memset(CpuRunInfo,0,sizeof(CpuRunInfo));
					
					vTaskGetRunTimeStats((char*)CpuRunInfo);
					printf("任务名 运行计数 使用率\r\n");
					printf("%s", CpuRunInfo);
					printf("---------------------------------------------\r\n\n");
					
					
				}break;
				case 2:
				{
					 /* K2键按下 */
//					printf ( "k2 被按下\n" );
					Board_LED_Toggle(5);
					 
				}break;
				case 3:
				{
					/* K3键按下*/
					 
				}break;
				default:break;
			}
			ucKeyCode=0;
		}
			
	}
}
 
/***********************************************************************
  * @ 函数名  : AppTaskCreate
  * @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
  * @ 参数    : 无  
  * @ 返回值  : 无
  **********************************************************************/
static void AppTaskCreate(void* par)
{
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
	taskENTER_CRITICAL();//进入临界区,禁止中断打断

	xReturn = xTaskCreate(	 LED_Task,
							"LED_Task",
							TASK_STACK_SIZE*1,
							NULL,
							2,
							&LED_TaskHandle);
	if (pdPASS == xReturn)
		printf("创建 Receive1_Task 任务成功!\r\n");
	

	xReturn = xTaskCreate(	 KEY_Task,
							"KEY_Task",
							TASK_STACK_SIZE*4,
							NULL,
							2,
							&KEY_TaskHandle);
	if (pdPASS == xReturn)
		printf("创建 KEY_Task 任务成功!\r\n");
	 
	
	
	vTaskDelete(AppTaskCreate_Handle);
	
	taskEXIT_CRITICAL(); //退出临界区	

}
/*
*********************************************************************************************************
*	函 数 名: AppObjCreate
*	功能说明: 创建任务通信机制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/

//static void AppObjCreate (void)
//{
//	 
//}
/**
 * @brief	main routine for blinky example
 * @return	Function should not exit.
 */
int main(void)
{
	
	prvSetupHardware();
	DEBUGSTR("CPU利用率统计\n");
	
	BaseType_t xReturn=xTaskCreate(AppTaskCreate,//任务入口函数
								"AppTaskCreate",//任务名
								TASK_STACK_SIZE*2,//任务栈大小
								NULL,//任务参数
								1,//任务优先级
								&AppTaskCreate_Handle);
	
	/* 创建任务通信机制 */
	// AppObjCreate();
	
	vTaskStartScheduler();//任务调度

	/* Loop forever */
	while (1) {
			printf("FreeRTOS 运行失败\n\r");
 	}
	
	
}

/******************
*函数名 : HardFault_Handler
*功能 	:硬件错误时会跳进这里
*说明 : 
******(1)可能是内存溢出,堆栈溢出。
******(2)可能是开启了中断,但没有中断函数。
******(3)可能指针赋值错误,最有可能是函数指针赋值错误。
******************/
void HardFault_Handler(void)
{
	printf("硬件错误中断\n");
	while(1)
	{

	}
}

tim_mrt.h

#ifndef _TIM_MRT_H_
#define _TIM_MRT_H_
 
void MRT_Init(void);
void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate);
void bsp_HardTimer(u8 ch,uint32_t frequency_Hz, void * _pCallBack);

#endif

tim_mrt.c

/*
 * 	注意,MRT定时器有4个独立通道,但共用中断号10。
 */
#include "board.h"
#include "tim_mrt.h"
/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

/* 保存 TIM定时中断到后执行的回调函数指针 */
static void (*s_TIM_CallBack0)(void);
static void (*s_TIM_CallBack1)(void);
static void (*s_TIM_CallBack2)(void);
static void (*s_TIM_CallBack3)(void);


/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

 
/* Interrupt fire reference counters for t0/1, t2, and t3 */
//bool Ms500;
//static uint32_t t01 , t3;
//static uint32_t t2;

/* 用于统计运行时间 */
volatile uint32_t CPU_RunTime = 0UL;


/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*  设置定时器

参数:
ch :定时器通道(0,1,2,3)
mode :模式(单次或者循环)
rate :速率,数字越小,间隔越长。
	--	1 表示 1Hz,即1s。
	--	2 表示 2Hz,即500ms。
	--	100表示100Hz,即10ms。
*/
void setupMRT(uint8_t ch, MRT_MODE_T mode, uint32_t rate)
{
	LPC_MRT_CH_T *pMRT;
	 
	pMRT = Chip_MRT_GetRegPtr(ch); //返回定时器的指针 

									//12MHz
	Chip_MRT_SetInterval(pMRT, (Chip_Clock_GetSystemClockRate() / rate) |\
						 MRT_INTVAL_LOAD);//立即加载
 
	Chip_MRT_SetMode(pMRT, mode);
	/* Clear pending interrupt and enable timer */
	Chip_MRT_IntClear(pMRT); 
	Chip_MRT_SetEnabled(pMRT); 
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief	MRT example main function
 * @return	Status (This function will not return)
 */
void MRT_Init(void)
{
	
	Chip_MRT_Init();//启用MRT时钟,复位MET
	Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(3));//禁用定时器通道3
	Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(2));//禁用定时器通道2 
	Chip_MRT_SetDisabled(Chip_MRT_GetRegPtr(0));//禁用定时器通道0
	
	NVIC_EnableIRQ(MRT_IRQn);	//启用定时器外设中断

	setupMRT(0, MRT_MODE_REPEAT, 20000);//20kHz,循环模式
	
	//通道初始化
//	setupMRT(2, MRT_MODE_REPEAT, 100); //100Hz,10ms循环
//	setupMRT(3, MRT_MODE_ONESHOT, 2); //2Hz单次,中断只发生一次,需要再次赋值。
//	setupMRT(3, MRT_MODE_REPEAT, 1); //1Hz,1s循环

}

/**
 * @brief	Handle interrupt from MRT
 * @return	Nothing
 */
void MRT_IRQHandler(void)
{
	uint32_t int_pend;

	int_pend = Chip_MRT_GetIntPending();
	Chip_MRT_ClearIntPending(int_pend);

	 //判断中断通道0
	if (int_pend & (MRTn_INTFLAG(0) ))
	{
		CPU_RunTime++;
		
	}
	if (int_pend &  (MRTn_INTFLAG(1)) ) {
		Board_LED_Set(4, true);

		s_TIM_CallBack0();
		s_TIM_CallBack1();
	}

	 //判断中断通道2
	if (int_pend & (MRTn_INTFLAG(2))) {	 

		s_TIM_CallBack2();
//		t2++;
		
	}

	 //判断中断通道3
	if (int_pend & (MRTn_INTFLAG(3))) {
		
		s_TIM_CallBack3();

	}
}

/*
*********************************************************************************************************
*	函 数 名: bsp_HardTimer
*	功能说明: 定时时间到后执行回调函数。
*	形    参: 
			ch: 多速率定时器通道(0,1,2,3)
*             _pCallBack : 定时时间到后,被执行的函数
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_HardTimer(u8 ch,uint32_t frequency_Hz, void * _pCallBack)
{
	
	switch(ch)
	{
		case 0:	{}break;
		case 1:{}break;
		case 2:
		{
			//因为函数指针赋值后才能正常运行,所以必须在调用时再初始化。
			s_TIM_CallBack2=(void (*)(void))_pCallBack;			
			setupMRT(2, MRT_MODE_ONESHOT, frequency_Hz); //单次
		}break;
		case 3:
		{
			s_TIM_CallBack3=(void (*)(void))_pCallBack;
//			setupMRT(3, MRT_MODE_REPEAT, frequency_Hz); //循环			
			setupMRT(3, MRT_MODE_ONESHOT, frequency_Hz); //单次
		}break;
		default:break;
	}
	 
	
}
/**
*END_TMI
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值