本文主要描述了如何在RT1170平台下,基于FreeRTOS实现CPU使用率的统计
参考:https://www.fatalerrors.org/a/statistical-analysis-of-cpu-utilization-in-freertos-system.html
第一、想要实现CPU使用率统计,需要一个比系统定时中断粒度更小的中断才能实现CPU使用率的统计,这是前提条件。
第二、需要在对应的操作系统中进行注册,实现对应的接口即可。
在本文中使用PIT2来充当这个角色。在PIT2_IRQHANDLER函数中对ulCpuTraceTick进行自加。这个变量后续会使用到。
#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_pit.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "FreeRTOS.h"
#include "task.h"
#include "string.h"
/*----------------------------------------------*
* external variables *
*----------------------------------------------*/
/*----------------------------------------------*
* external routine prototypes *
*----------------------------------------------*/
/*----------------------------------------------*
* internal routine prototypes *
*----------------------------------------------*/
/*----------------------------------------------*
* project-wide global variables *
*----------------------------------------------*/
/*----------------------------------------------*
* module-wide global variables *
*----------------------------------------------*/
const pit_config_t PIT2_config = {
.enableRunInDebug = false
};
volatile unsigned int ulCpuTraceTick = 0;
/*----------------------------------------------*
* constants *
*----------------------------------------------*/
/*----------------------------------------------*
* macros *
*----------------------------------------------*/
/* Get source clock for PIT driver */
#define PIT_SOURCE_CLOCK CLOCK_GetRootClockFreq(kCLOCK_Root_Bus)
/* Definitions for BOARD_InitPeripheral_PIT2_Ch_0 functional group */
/* BOARD_InitPeripheral_PIT2_Ch_0 defines for PIT2 */
/* Definition of peripheral ID. */
#define PIT2_PERIPHERAL PIT2
/* Definition of clock source frequency. */
#define PIT2_CLK_FREQ 240000000UL
/* Definition of channel number for channel 0. */
#define PIT2_CHANNEL_0 kPIT_Chnl_0
/* Definition of ticks count for channel 0. */
//#define PIT2_CHANNEL_0_TICKS 2399999U
#define PIT2_CHANNEL_0_TICKS 1199999U
/* PIT2 interrupt vector ID (number). */
#define PIT2_IRQN PIT2_IRQn
/* PIT2 interrupt handler identifier. */
#define PIT2_IRQHANDLER PIT2_IRQHandler
/*----------------------------------------------*
* routines' implementations *
*----------------------------------------------*/
/* PIT2_IRQn interrupt handler */
void PIT2_IRQHANDLER(void) {
/* Place your code here */
/* Clear interrupt flag.*/
PIT_ClearStatusFlags(PIT2_PERIPHERAL, PIT2_CHANNEL_0, kPIT_TimerFlag);
ulCpuTraceTick++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void PIT2_init(void) {
/* Initialize the PIT. */
PIT_Init(PIT2_PERIPHERAL, &PIT2_config);
/* Set channel 0 period to 1 s (240000000 ticks). */
PIT_SetTimerPeriod(PIT2_PERIPHERAL, PIT2_CHANNEL_0, PIT2_CHANNEL_0_TICKS);
/* Enable interrupts from channel 0. */
PIT_EnableInterrupts(PIT2_PERIPHERAL, PIT2_CHANNEL_0, kPIT_TimerInterruptEnable);
/* Enable interrupt PIT2_IRQN request in the NVIC */
EnableIRQ(PIT2_IRQN);
/* Start channel 0. */
PIT_StartTimer(PIT2_PERIPHERAL, PIT2_CHANNEL_0);
}
在FreeRTOSConfig.h做如下配置
/* Run time and task stats gathering related definitions. */
-#define configGENERATE_RUN_TIME_STATS 0
+#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
+
+extern volatile unsigned int ulCpuTraceTick;
+
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (ulCpuTraceTick = 0ul)
+#define portGET_RUN_TIME_COUNTER_VALUE() ulCpuTraceTick
编译函数接口打印CPU使用率:
uint8_t CPU_RunInfo[400]; //保存任务运行时间信息
//ref https://www.jianshu.com/p/cc4b948c7741
void CPU_Task(void* parameter)
{
PRINTF("CPU_Task \r\n");
while (1)
{
memset(CPU_RunInfo,0,400); //信息缓冲区清零
vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息
PRINTF("---------------------------------------------\r\n");
PRINTF("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
PRINTF("%s", CPU_RunInfo);
PRINTF("---------------------------------------------\r\n");
memset(CPU_RunInfo,0,400); //信息缓冲区清零
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
PRINTF("任务名 运行计数 利用率\r\n");
PRINTF("%s", CPU_RunInfo);
PRINTF("---------------------------------------------\r\n\n");
vTaskDelay(1000); /* 延时500个tick */
// PRINTF("CPU_Task \r\n");
}
}
通过创建任务实现CPU使用率的统计:
extern void CPU_Task(void* parameter);
stat = xTaskCreate(CPU_Task, "CpuTask", configMINIMAL_STACK_SIZE + 5000, NULL, tskIDLE_PRIORITY + 1, NULL);
if (pdPASS != stat)
{
PRINTF("Failed to create awtk task");
while (1)
;
}
实际效果如下所示:
---------------------------------------------
任务名 任务状态 优先级 剩余栈 任务序号
CpuTask X 1 5016 2
TestTask R 1 11952 1
IDLE R 0 79 4
bsp_can_t B 2 12069 3
Tmr Svc B 17 153 5
---------------------------------------------
任务名 运行计数 利用率
TestTask 1856 97%
CpuTask 40 2%
IDLE 0 <1%
bsp_can_t 0 <1%
Tmr Svc 0 <1%
---------------------------------------------
---------------------------------------------
任务名 任务状态 优先级 剩余栈 任务序号
CpuTask X 1 5008 2
TestTask R 1 11952 1
IDLE R 0 79 4
bsp_can_t B 2 12069 3
Tmr Svc B 17 153 5
---------------------------------------------
任务名 运行计数 利用率
TestTask 2088 99%
CpuTask 48 2%
IDLE 0 <1%
bsp_can_t 0 <1%
Tmr Svc 0 <1%
---------------------------------------------
---------------------------------------------
任务名 任务状态 优先级 剩余栈 任务序号
CpuTask X 1 5008 2
TestTask R 1 11952 1
IDLE R 0 79 4
bsp_can_t B 2 12069 3
Tmr Svc B 17 153 5
---------------------------------------------
任务名 运行计数 利用率
TestTask 2320 100%
CpuTask 53 2%
IDLE 0 <1%
bsp_can_t 0 <1%
Tmr Svc 0 <1%
---------------------------------------------
开启CPU使用率统计存在如下两个问题:
第一: 最大统计时间。
第二: 占用CPU资源。
欢迎订阅
“嵌入式实操”一个分享开发实践经验的地方。
文章会同时发布到我的 CSDN主页、今日头条号 平台上。