如何測試嵌入式處理器的CPU使用率


某個網站的方法

需要使用邏輯分析儀

https://www.embedded.com/how-to-calculate-cpu-utilization/

CPU Utilization使用率定義:

 

 由1,需要計算空閑任務執行時間。空閑任務一般如下:

 1 Listing 1: Simple example of a background loop
 2 
 3 int main( void )
 4 {
 5    SetupInterrupts();
 6    InitializeModules();
 7    EnableInterrupts();
 8 
 9    while(1)      /* endless loop – spin in the background */
10    {
11       CheckCRC();
12       MonitorStack();
13do other non-time critical logic here.
14    }
15 }

不改變代碼的方式來計算空閑任務執行時間有3種。

第1種

使用邏輯分析儀LSA(Logic State Analyzer)檢測地址線,若訪問了while(1)里代碼所在的地址(具體地址可以通過map文件獲得),則認為在執行空閑任務(如何獲得數據呢,訪問一次地址記錄一次時刻?文中180us是空閑任務執行時間?那剩余的時間被誰在執行呢?)。獲取的數據需要做野值剔除,因為空閑任務會被中斷打斷,會被高優先級任務打斷,若打斷了則空閑任務時間會被延長。

第2種

用公式3,看不懂。

第3種

一種自動化的方式,需要高精度時鍾,比如空閑任務需要180us,則需要20分之一精度的時鍾,180/20=9us。

 

CPU使用率最好在50%以內。

 

一種針對Arduino的方法,AVR

https://spin.atomicobject.com/2012/05/02/measuring-cpu-utilization/

https://github.com/chrishonson/Arduino_CPU_Usage

基本原理就是需要一個高精度時鍾,來計數。

Measuring CPU Utilization

Understanding processor load in an embedded system is important, yet often overlooked. It’s a step toward analyzing your processor’s ability to meet system deadlines. I have provided a sample arduino sketch to show how you can add real-time CPU utilization measurements to your embedded project.

CPU utilization is simply the ratio of time a processor spends doing real work over a given period of time. The time of measurement can be arbitrary. Ideally, it’s better to align your measurement time with the shortest deadline time in your project; it depends on the goals of the CPU utilization measurement. If you have to service a communication bus 10ms after receiving an input, and it takes 9ms to perform the necessary processing, then you may want to measure utilization over 10ms so that you can capture this 90% worst case, critical path. For the purpose of simplicity and illustration I will measure over 1s.

The first thing we are going to need is a reliable timing source. I recommend setting up a timer interrupt. I could explain how to, but luckily someone else already has here. In my example I chose to use timer 2 since timer 1 is used by the servo library and I might actually use that in the future.

The next step in setting up your project is defining what 0% utilization is. The most basic way of doing this is by incrementing a counter in your idle task (in this case loop()) and seeing how many idle counts occur during a measurement period. If no work is being done (besides the timer interrupt) then this represents the maximum number of idle counts and 0% utilization. One might argue that the act of calculating idle counts is work and that 0% utilization is not achievable with the instrumentation code in place. That’s true, but I think such concerns are negligible when the CPU utilization measurement period is sufficiently large.

Anyway, it’s important to note, here, that once you determine the maximum idle counts, no code can be added to the idle task. This would change the maximum idle counts. In general, I think the idle task should do essentially nothing. Where then can you get useful work done?

My example provides a very simple, round robin, periodic task scheduler. Here you can perform calculations as fast or as slow as required. It’s also noteworthy that I used the ISR only to notify tasks that they are ready to run. It’s good practice to keep ISR’s as fast as possible and to keep application code out in order to prevent problems with shared data.

To test my example I simply add a delay(50) to my 100ms task. This will run 10 times in one second. 10*50ms=500ms I should calculate 50% utilization and if I run the example I see that it does.

Feel free to use my template as you wish. I recommend moving any activity out of loop() and putting it into one of the task functions.
View Code

 

一個介紹任務和中斷貢獻資源保護的課件,

鏈接:https://pan.baidu.com/s/1UHnLI6SsJQnns7ys8kQd8g
提取碼:zf5c

FreeRTOS的方法

FreeRTOSConfig.h使能configGENERATE_RUN_TIME_STATS

1 #define configGENERATE_RUN_TIME_STATS            1
2 #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ConfigureTimeForRunTimeStats()
3 #define portGET_RUN_TIME_COUNTER_VALUE() FreeRTOSRunTimeTicks

timer.c中配置定時器

 1 #include "timer.h"
 2 
 3 void TIM2_Init(u16 auto_data,u16 fractional)
 4 {
 5     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
 6     NVIC_InitTypeDef NVIC_InitStructure;
 7     
 8     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);      //ʹ��TIM2ʱ��
 9     
10   TIM_TimeBaseInitStructure.TIM_Period = auto_data;          //�Զ���װ��ֵ
11     TIM_TimeBaseInitStructure.TIM_Prescaler=fractional;      //��ʱ����Ƶ
12     TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //���ϼ���ģʽ
13     TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
14     
15     TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//��ʼ��TIM2
16     
17     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //�����ʱ��2�����ж�
18     TIM_Cmd(TIM2,ENABLE);                    //ʹ�ܶ�ʱ��2
19     
20     NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; //��ʱ��2�ж�
21     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //��ռ���ȼ�1
22     NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;  //�����ȼ�3
23     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
24     NVIC_Init(&NVIC_InitStructure);
25 }
26 
27 volatile unsigned long long FreeRTOSRunTimeTicks;
28 
29 void ConfigureTimeForRunTimeStats()
30 {
31     FreeRTOSRunTimeTicks = 0;
32     TIM2_Init(50-1, 90-1);
33 }
34 
35 
36 //��ʱ��3�жϷ�����
37 void TIM2_IRQHandler(void)
38 {
39     if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) //����ж�
40     {
41         ++FreeRTOSRunTimeTicks;
42     }
43     TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  //����жϱ�־λ
44 }

main.c,在某個任務中獲取信息並通過串口打印

 1 char RunTimeInfo[400];
 2 
 3 void ToggleLed4(void * pvParameters)
 4 {
 5   while(1)
 6   {
 7     /* toggle LED4 each 250ms */
 8     GPIOE->ODR ^= GPIO_Pin_3;
 9     vTaskDelay(1000);
10 
11     memset(RunTimeInfo, 0, 400);
12     vTaskGetRunTimeStats((signed char *)RunTimeInfo);
13     printf("%s\r\n", RunTimeInfo);
14   }
15 }

串口打印結果:只能打印一次,后面就進Hard Fault了。。。原因未知。。。

LED4        0        0%
IDLE        24834        9%
slipif_loop        3        <1%
slipif_loop        0        0%
E_link        4        <1%
Eth_if        4        <1%
TCP/IP        811        <1%
ospf_task        3293        1%
udpsocktx_threa        14        <1%
Main        244709        89%
snmp_netconn        1        <1%

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM