FreeRTOS--获取CPU的利用率两种方法

计算RTOS的CPU的使用率及任务栈的使用情况,有助于RTOS的调试开发。可以分析多任务的设计的合理性,如果CPU的利用率为1%,说明CPU 99%的时间运行在空闲任务上,则极大的浪费CPU的性能。计算FreeRTOS的CPU使用率就要用到两个函数vTaskList和vTaskGetRunTimeStats。通过这两个函数获取任务的执行状态。

执行的结果用串口打印出来,这种调试仅用于测试而非正常项目。

1.定义一个Timer 50us进入中断一次,最大支持计数时间:2^32 * 50us / 3600s = 59.6分钟。运行时间超过了59.6分钟将不准确。FreeRTOS的系统内核没有对总的计数时间做溢出保护。

 1 /**
 2   * @brief  Period elapsed callback in non blocking mode
 3   * @note   This function is called  when TIM1 interrupt took place, inside
 4   * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
 5   * a global variable "uwTick" used as application time base.
 6   * @param  htim : TIM handle
 7   * @retval None
 8   */
 9 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
10 {
11   /* USER CODE BEGIN Callback 0 */
12 
13   /* USER CODE END Callback 0 */
14   if (htim->Instance == TIM1) {
15     HAL_IncTick();
16   }
17   /* USER CODE BEGIN Callback 1 */
18     if(htim->Instance == TIM2)
19     {
20         CPU_RunTime++;
21     }
22   /* USER CODE END Callback 1 */
23 }

2.使能相关的宏定义FreeRTOSConfig.h

extern volatile uint32_t CPU_RunTime;

#define configUSE_TRACE_FACILITY 1    //设置为1,使用可视化追踪功能。设置为0,就不使用。如果使用可视化追踪,必须提供追踪缓冲区。
#define configGENERATE_RUN_TIME_STATS 1  //为1,则该函数将总运行时间写入*pulTotalRunTime中。pulTotalRunTime可以设置为NULL,表示忽略总运行时间

#define configUSE_STATS_FORMATTING_FUNCTIONS 1  //用户配置宏定义configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS都为1的时候,将使能函数vTaskList() 和 vTaskGetRunTimeStats(),如/果两者中任何一个为0,那么这两个函数都将被禁能

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (CPU_RunTime = 0UL)
#define portGET_RUN_TIME_COUNTER_VALUE() CPU_RunTime

3. 单独创建一个任务统计CPU利用率

 1 /* Cpu_task function */
 2 void Cpu_task(void const * argument)
 3 {
 4   /* USER CODE BEGIN Cpu_task */
 5     uint8_t CPU_RunInfo[512];
 6   /* Infinite loop */
 7   for(;;)
 8   {
 9       memset(CPU_RunInfo,0,512);
10       vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息
11       printf("---------------------------------------------\r\n");
12       printf("任务名       任务状态     优先级     剩余栈     任务序号\r\n");
13       printf("%s", CPU_RunInfo);
14       printf("---------------------------------------------\r\n");
15       memset(CPU_RunInfo,0,512);
16       vTaskGetRunTimeStats((char *)&CPU_RunInfo);
17       printf("任务名         运行计数     使用率\r\n");
18       printf("%s", CPU_RunInfo);
19       printf("---------------------------------------------\r\n\n");
20       osDelay(200); /* 延时500个tick */
21 
22   }
23   /* USER CODE END Cpu_task */
24 }

 

 

 

第二种方法查看CPU利用率的方利用TrueStudio IDE或STM32CUBEMXIDE查看

 

 

 设置方法参考:STM32CubeIDE user guide - User manual   

1) #define configUSE_TRACE_FACILITY 1

2)应用程序软件必须调用vQueueAddToRegistry()函数,使FreeRTOS队列和FreeRTOS信号量视图能够显示对象

3)freeRTOSConfig.h

#define configGENERATE_RUN_TIME_STATS 1

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (RunTime=0UL)

#define portGET_RUN_TIME_COUNTER_VALUE() RunTime

 4)tasks.c 中 ulTutoralRunTime

#if ( configGENERATE_RUN_TIME_STATS == 1 )

PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */

PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */

#endif

修改为

#if ( configGENERATE_RUN_TIME_STATS == 1 )

PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */

PRIVILEGED_DATA volatile static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */

#endif

 详细操作如下:

1.在STM32CUBEMX中找到FreeRTOS的配置参数如下:

1) #define configUSE_TRACE_FACILITY   1

2)#define configGENERATE_RUN_TIME_STATS   1

3)#define configUSE_STATS_FORMATTING_FUNCTIONS     1

 2. 为了使可视化任务列表显示任务栈的使用率需要使能RECORD_STACK_HIGH_ADDRESS 

#define configRECORD_STACK_HIGH_ADDRESS          1

 3. 使用vQueueAddToRegistry()注册函数在应用程序中把你创建的信号量,消息队列等进行注册,生成FreeRTOS队列和可以显示对象的FreeRTOS信号量视图

Example:

vQueueAddToRegistry(mailId, "osMailQueue");  //注册邮箱

vQueueAddToRegistry(osQueueHandle, "osQueue"); //注册队列

vQueueAddToRegistry(osSemaphoreHandle, "osSemaphore");//注册信号量

你可以在MX_FREERTOS_Init中添加如下代码

 vQueueAddToRegistry(Mutex_printfHandle, "Mutex_printf");
 vQueueAddToRegistry(msgQueueHandle, "msgQueue");
 
4.要获得有效的RTOS运行时统计信息,应用程序必须设置一个运行时统计时基。的时基建议时钟的运行频率至少比用于处理RTOS tick的时钟的频率快10倍

中断。要启用FreeRTOS™收集运行时统计信息,这里RTOS tick是1ms,那么至少定义一个100us的TIMER,如下200MHZ的APB1/APB2 Timer clcok,

预分频200,得到1MHZ 的频率,周期计数100即100us中断一次。

 5. 用STM32CUBEMX生成的代码中,以下两个函数是自动生成的,需要自己实现。定义全局变量RunTime,在Timer中断中自增

void configureTimerForRunTimeStats(void);
unsigned long getRunTimeCounterValue(void);

 

 

 6. tasks.c 中 ulTutoralRunTime修改为volatile或修改编译优化等级

#if ( configGENERATE_RUN_TIME_STATS == 1 )

PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */

PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */

#endif

修改为

#if ( configGENERATE_RUN_TIME_STATS == 1 )

PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */

PRIVILEGED_DATA volatile static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */

#endif

或者仅仅为tasks.c更改优化级别

1. 在项目资源管理器视图中右键单击它并打开属性

2. 选择[属性]&gt;[C/ c++构建]&gt;[设置]&gt;[工具设置]&gt;[优化]

3. 设置[优化级别]为None (- 0)

 Stack Usage默认无数据显示,点击如下图按钮

 

 

 

 

posted @ 2021-08-26 14:15  M&D  阅读(5186)  评论(1编辑  收藏  举报