嵌入式实操----基于RT1170 FreeRTOS实现CPU使用率统计(二十四)

本文主要是通过迁移的思维,记录本人初次使用NXP MCUXpresso SDK API进行BSP开发

本文主要描述了如何在RT1170平台下,基于FreeRTOS实现CPU使用率的统计
参考:https://www.fatalerrors.org/a/statistical-analysis-of-cpu-utilization-in-freertos-system.html

1. CPU使用率统计的原理

第一、想要实现CPU使用率统计,需要一个比系统定时中断粒度更小的中断才能实现CPU使用率的统计,这是前提条件。
第二、需要在对应的操作系统中进行注册,实现对应的接口即可。

2. 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);
}

3. 操作系统接口注册

在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");			
    }
}

4. 验证

通过创建任务实现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%
---------------------------------------------

4. 总结

开启CPU使用率统计存在如下两个问题:
第一: 最大统计时间。
第二: 占用CPU资源。

欢迎订阅
嵌入式实操”一个分享开发实践经验的地方。
文章会同时发布到我的 CSDN主页今日头条号 平台上。

猜你喜欢

转载自blog.csdn.net/weixin_30965175/article/details/125821519