通过对工程中各个线程任务的分析,以便进行任务代码的优化或者更换主处理芯片。仅为记录,欢迎大佬指出错误。如有帮助,十分荣幸。
我的mcu是stm32f405,frertos,标准库函数。
cpu占用率的思想就是有一个基准时间,通过一个通用计时器,记录各个线程的运行时间与任务执行总时间,就得到了各个线程的cpu占用率。功能实现是通过调用vTaskGetRunTimeStats()函数,下面开始介绍如何使用这个函数。
一、相关宏设置
#define configGENERATE_RUN_TIME_STATS 1 //为1时启用运行时间统计功能
extern volatile long long FreeRTOSRunTimeTicks;
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ConfigureTimeForRunTimeStats()//定时器4提供时间统计的时基,频率为10K,即周期为100us
#define portGET_RUN_TIME_COUNTER_VALUE() FreeRTOSRunTimeTicks //获取时间统计时间值
#define configUSE_TRACE_FACILITY 1 //为1启用可视化跟踪调试
#define configUSE_STATS_FORMATTING_FUNCTIONS 1 //与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
//prvWriteNameToBuffer(),vTaskList(),
//vTaskGetRunTimeStats()
`
二、定时器配置
配置定时器是为了提供精准时钟,要求为系统时钟的10~20倍,我的系统时钟为1hz,所以将定时器配置为20hz,使用的TIM4通用定时器,时钟频率为87M。另外ConfigureTimeForRunTimeStats()函数以及全局变量FreeRTOSRunTimeTicks也在time.c中进行定义。
//freertos 时钟需要的时钟定时器
volatile long long FreeRTOSRunTimeTicks;
void ConfigureTimeForRunTimeStats(void)
{
FreeRTOSRunTimeTicks=0;
TIM4_Init(50-1,84-1); //周期50us 频率20k
}
void TIM4_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); ///使能TIM4时钟
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM4
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器4更新中断
TIM_Cmd(TIM4,ENABLE); //使能定时器3
NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器4中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//定时器4中断服务函数
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
{
FreeRTOSRunTimeTicks++;
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除中断标志位
}
三、使用时间函数
char InfoBuffer[400];
char RunTimeInfo[400]; //保存任务运行时间信息
void RunTimeStatsTask(void* param)
{
while(1)
{
#if 0
/*打印任务信息*/
vTaskList(InfoBuffer);
printf("%s",InfoBuffer);
vTaskDelay(1000);
#endif
#if 1
/*任务占用cpu使用率百分比*/
memset(RunTimeInfo,0,400); //信息缓冲区清零
vTaskGetRunTimeStats(RunTimeInfo); //获取任务运行时间信息
printf("任务名\t\t\t运行时间\t运行所占百分比\r\n");
printf("%s\r\n",RunTimeInfo);
vTaskDelay(1000);
#endif
}
}
四、输出结果分析
通过串口助手,得到信息