日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
MCU上的代碼執(zhí)行時(shí)間

在許多實(shí)時(shí)應(yīng)用程序中,二八原則并不生效,CPU 可以花費(fèi)95%(或更多)的時(shí)間在不到5% 的代碼上。電動(dòng)機(jī)控制、引擎控制、無(wú)線通信以及其他許多對(duì)時(shí)間敏感的應(yīng)用程序都是如此。這些嵌入式系統(tǒng)通常是用c編寫的,而且開發(fā)人員常常被迫對(duì)代碼進(jìn)行手工優(yōu)化,可能會(huì)回到匯編語(yǔ)言,以滿足性能的需求。測(cè)量代碼部分的實(shí)際執(zhí)行時(shí)間可以幫助找到代碼中的熱點(diǎn)。本文將說(shuō)明如何可以方便地測(cè)量和顯示在基于Cortex-M MCU的實(shí)時(shí)執(zhí)行時(shí)間。

成都創(chuàng)新互聯(lián)專注于奎文企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城開發(fā)??木W(wǎng)站建設(shè)公司,為奎文等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

測(cè)量代碼的執(zhí)行時(shí)間

測(cè)量代碼執(zhí)行時(shí)間的方法有很多。作為一個(gè)嵌入式工程師,經(jīng)常使用一個(gè)或多個(gè)數(shù)字輸出和一個(gè)示波器。需要在執(zhí)行要監(jiān)視的代碼之前設(shè)置一個(gè)高的輸出,然后將輸出降低。當(dāng)然,在做這些之前有相當(dāng)多的設(shè)置工作: 找到一個(gè)或多個(gè)自由輸出,確保它們可以輕松訪問(wèn),將端口配置為輸出,編寫代碼,編譯,設(shè)置范圍等等。一旦有了一個(gè)信號(hào),你可能需要對(duì)它進(jìn)行一段時(shí)間的監(jiān)視,以便看到最小值和***值。 數(shù)字存儲(chǔ)示波器使這個(gè)過(guò)程更容易,但是還有其他更簡(jiǎn)單的方法。

另一種測(cè)量執(zhí)行時(shí)間的方法是使用可跟蹤調(diào)試接口。只需要運(yùn)行代碼,查看跟蹤,計(jì)算 delta時(shí)間(通常是手動(dòng)的) ,并將CPU周期轉(zhuǎn)換為微秒。不幸的是,這個(gè)跟蹤給了一個(gè)執(zhí)行的實(shí)例,可能不得不在追蹤捕獲中進(jìn)一步查找最壞情況下的執(zhí)行時(shí)間。這是一個(gè)乏味的過(guò)程。

Cortex-M 周期計(jì)數(shù)器

在大多數(shù)Cortex-M的處理器中調(diào)試端口包含一個(gè)32位的自由運(yùn)行計(jì)數(shù)器,它可以計(jì)算 CPU 的時(shí)鐘周期。計(jì)數(shù)器是 Debug 觀察和跟蹤(DWT)模塊的一部分,可以很容易地用于測(cè)量代碼的執(zhí)行時(shí)間。下面的代碼是啟用和初始化這個(gè)特性非常有用。

 
 
 
 
  1. #define  ARM_CM_DEMCR      (*(uint32_t *)0xE000EDFC)
  2. #define  ARM_CM_DWT_CTRL   (*(uint32_t *)0xE0001000)
  3. #define  ARM_CM_DWT_CYCCNT (*(uint32_t *)0xE0001004)
  4. if (ARM_CM_DWT_CTRL != 0) {        // See if DWT is available
  5.     ARM_CM_DEMCR      |= 1 << 24;  // Set bit 24
  6.     ARM_CM_DWT_CYCCNT  = 0;
  7.     ARM_CM_DWT_CTRL   |= 1 << 0;   // Set bit 0
  8. }

使用DWT周期計(jì)數(shù)器來(lái)測(cè)量代碼執(zhí)行時(shí)間

可以通過(guò)在目標(biāo)代碼之前和之后讀取周期計(jì)數(shù)器的值來(lái)測(cè)量和計(jì)算代碼段的執(zhí)行時(shí)間,如下所示。 當(dāng)然,這意味著必須設(shè)置代碼,但能夠得到一個(gè)非常準(zhǔn)確的值。

 
 
 
 
  1. uint32_t  start;
  2. uint32_t  stop;
  3. uint32_t  delta;
  4. start = ARM_CM_DWT_CYCCNT;
  5. // Code to measure
  6. stop  = ARM_CM_DWT_CYCCNT;
  7. delta = stop – start;

因?yàn)槭褂玫氖菬o(wú)符號(hào)運(yùn)算,delta表示所測(cè)量代碼的實(shí)際執(zhí)行時(shí)間(CPU 時(shí)鐘周期)。

在測(cè)量開始和停止讀數(shù)之間的代碼執(zhí)行時(shí)間時(shí),可能會(huì)發(fā)生中斷,所以每次執(zhí)行這個(gè)序列很可能會(huì)有不同的值。在這種情況下,可能希望在測(cè)量過(guò)程中禁用中斷,但是要清楚禁用中斷是暫時(shí)的,只用于測(cè)量。盡管如此,也許應(yīng)該把中斷的任務(wù)包括進(jìn)來(lái),因?yàn)樗鼈儠?huì)影響到代碼的***執(zhí)行時(shí)間。

 
 
 
 
  1. Disable Interrupts;
  2. start = ARM_CM_DWT_CYCCNT;
  3. // Code to measure
  4. stop  = ARM_CM_DWT_CYCCNT;
  5. Enable Interrupts;
  6. delta = stop – start;

如果所測(cè)代碼包含條件語(yǔ)句、循環(huán)或任何可能導(dǎo)致變化的東西,那么獲得的值可能不代表最壞情況下的執(zhí)行時(shí)間。為了糾正這個(gè)問(wèn)題,需要添加一個(gè)峰值檢測(cè)器,如下圖所示。當(dāng)然,在進(jìn)行任何測(cè)量之前,需要將 max 聲明并初始化為最小值(即0)。

 
 
 
 
  1. start = ARM_CM_DWT_CYCCNT;
  2. // Code to measure
  3. stop  = ARM_CM_DWT_CYCCNT;
  4. delta = stop – start;
  5. if (max < delta) {
  6.     max = delta;
  7. }

同樣,知道最短執(zhí)行時(shí)間也是有趣且有用的 在進(jìn)行任何測(cè)量之前,只需要聲明和初始化***可能值(即0xFFFFFFFF)。下面是新的代碼: ``` tart = ARMCMDWT_CYCCNT;

 
 
 
 
  1. // Code to measure
  2. stop = ARMCMDWT_CYCCNT;
  3. delta = stop – start;
  4. if (max < delta) {
  5. max = delta;
  6. }
  7. if (min > delta) {
  8. min = delta;

} ``` 就像 Cortex-M4處理器和 Cortex-M7那樣,執(zhí)行時(shí)間還取決于CPU是否配備了緩存。如果系統(tǒng)中使用了指令或數(shù)據(jù)緩存,對(duì)同一段代碼的多重測(cè)量可能不一致。這時(shí),可以考慮禁用緩存以測(cè)量最壞的情況。

大多數(shù)調(diào)試器允許顯示這些變量值。如果是這樣,則需要在全局范圍內(nèi)聲明顯示變量,以保留它們的值并允許實(shí)時(shí)監(jiān)控。不幸的是,這些值代表的是CPU時(shí)鐘周期,而且大多數(shù)調(diào)試器還不夠成熟,無(wú)法為了顯示目的而對(duì)變量進(jìn)行縮放。假設(shè)一個(gè)16兆赫的CPU時(shí)鐘速度,顯示70.19微秒比顯示1123個(gè)周期要方便得多。實(shí)際上還有一種更好的方法來(lái)顯示這些變量,這也提供了規(guī)?;芰?,可以以一種更加可讀的形式看待它們。

經(jīng)過(guò)的時(shí)間模塊

當(dāng)然,可以將代碼片段嵌入到應(yīng)用程序中,但還可以可以使用一個(gè)簡(jiǎn)單的模塊。 elapsedtime.c與elapsedtime.h,它僅由4個(gè)函數(shù)組成。

方法如下:

  1. 按照慣例,#include
  2. 在使用elapsedtime.c 中的其他函數(shù)之前,調(diào)用 elapsedtime_init()
  3. 通過(guò)設(shè)置"ELAPSEDTIMEMAX_SECTIONS"來(lái)定義時(shí)間測(cè)量結(jié)構(gòu)的***數(shù)目。這與用 stop/start代碼包裝的不同代碼段相對(duì)應(yīng)
  4. 調(diào)用elapsedtimestart()并傳遞要監(jiān)視的代碼片段的索引(即0 到ELAPSEDTIMEMAX_SECTIONS-1)
  5. 調(diào)用elapsedtimestop()并傳遞在運(yùn)行時(shí)啟動(dòng)時(shí)所使用的相同索引
  6. 如果調(diào)試器允許監(jiān)視變量(即當(dāng)目標(biāo)正在運(yùn)行時(shí)) ,則可以顯示elapsedtimetbl[],并查看對(duì)應(yīng)索引的運(yùn)行時(shí)間結(jié)構(gòu)
  7. 重復(fù)執(zhí)行步驟4到6,并將代碼置于最壞和***的情況下,以便ELAPSED_TIME數(shù)據(jù)結(jié)構(gòu)中的Min 和max 字段可以很好地表示所測(cè)量代碼片段的執(zhí)行時(shí)間

需要注意的是, 沒有在測(cè)量過(guò)程中禁用中斷,因?yàn)镮SR可能會(huì)涉及到,也需要了解這會(huì)如何影響感知的執(zhí)行時(shí)間。

 
 
 
 
  1. void  main (void)
  2. {
  3.     // Some code
  4.     elapsed_time_init();         // Iitialize the module
  5.     // Some code
  6. }
  7. void  MyCode (void)
  8. {
  9.     // Some code here
  10.     elapsed_time_start(0);    // Start measurement of code snippet #0
  11.     // Code being measured
  12.     elapsed_time_stop(0);     // Stop and
  13.     // Some other code
  14. }

當(dāng)然,最小和***的執(zhí)行時(shí)間取決于測(cè)量的頻率,以及代碼是否分別受到***和最差條件的限制。

另外,沒有必要顯示起始字段,因?yàn)樗挥糜谠跍y(cè)量開始時(shí)記錄DWT周期計(jì)數(shù)器的值,然而,啟動(dòng)字段可以用來(lái)顯示出來(lái)。換句話說(shuō),當(dāng)看到這個(gè)值變化時(shí),就會(huì)知道測(cè)量正在發(fā)生。

使用 uc / probe 的示例顯示

使用了elapsed_time.c 和 uc/probe,來(lái)測(cè)量一下代碼片段的執(zhí)行時(shí)間。

圖1| IAR 和 uc/probe 的樹視圖

圖1顯示了使用IAR的LiveWatch (左)和 uc / probe 的樹視圖(右)。截圖是在不同的時(shí)間拍攝的,是一個(gè)存儲(chǔ)不同代碼片段的測(cè)量值的數(shù)組。

可以將min/max/current分配給計(jì)量表和數(shù)字指示器,如圖2所示。CPU 運(yùn)行在80mhz,這些值以微秒顯示,應(yīng)用了0.0125的縮放因子。左側(cè)的按鈕用于重置統(tǒng)計(jì)數(shù)據(jù),從而迫使重新計(jì)算最小值和***值。

圖2 | 使用uc/probe 的儀表顯示***執(zhí)行時(shí)間

Uc/probe 的一個(gè)強(qiáng)大特性是能夠與微軟的 Excel 對(duì)接,從而在電子表格中顯示這些值(實(shí)時(shí)) ,如圖3所示。

圖3 | 使用 Excel 顯示實(shí)時(shí)數(shù)據(jù)

小結(jié)

作為嵌入式開發(fā)人員,有許多工具可以用來(lái)測(cè)試和驗(yàn)證設(shè)計(jì)。對(duì)于代碼執(zhí)行時(shí)間,可以很容易地使用 Cortex-M 處理器眾多特性中的一個(gè),即DWT周期計(jì)數(shù)器。

uc/probe 提供了很多功能,允許使用計(jì)量表、儀表盤、數(shù)字指示器、 Excel界面或圖表來(lái)監(jiān)控應(yīng)用程序中的許多變量。通過(guò)內(nèi)置的示波器功能,一旦觸發(fā)條件滿足,還可以捕獲多達(dá)7個(gè)額外變量值。

附錄代碼

elapsed_time.c

 
 
 
 
  1. #include  
  2. #include  
  3. /*
  4. ********************************************************************************
  5. *                           CORTEX-M - DWT TIMER
  6. ********************************************************************************
  7. */
  8. #define  ARM_CM_DEMCR      (*(uint32_t *)0xE000EDFC)
  9. #define  ARM_CM_DWT_CTRL   (*(uint32_t *)0xE0001000)
  10. #define  ARM_CM_DWT_CYCCNT (*(uint32_t *)0xE0001004)
  11. /*
  12. ********************************************************************************
  13. *                             Data Structure
  14. ********************************************************************************
  15. */
  16. typedef  struct  elapsed_time {
  17.     uint32_t  start;
  18.     uint32_t  current;
  19.     uint32_t  max;
  20.     uint32_t  min;
  21. } ELAPSED_TIME;
  22. /*
  23. ********************************************************************************
  24. *                      STORAGE FOR ELAPSED TIME MEASUREMENTS
  25. ********************************************************************************
  26. */
  27. static  ELAPSED_TIME  elapsed_time_tbl[ELAPSED_TIME_MAX_SECTIONS];
  28. /*
  29. ********************************************************************************
  30. *                              MODULE INITIALIZATION
  31. *
  32. * Note(s): Must be called before any of the other functions in this module
  33. ********************************************************************************
  34. */
  35. void  elapsed_time_init (void)         
  36. {
  37.     uint32_t  i;
  38.     
  39.     
  40.     if (ARM_CM_DWT_CTRL != 0) {                  // See if DWT is available
  41.         ARM_CM_DEMCR      |= 1 << 24;            // Set bit 24
  42.         ARM_CM_DWT_CYCCNT  = 0;                
  43.         ARM_CM_DWT_CTRL   |= 1 << 0;             // Set bit 0
  44.     }
  45.     for (i = 0; i < ELAPSED_TIME_MAX_SECTIONS; i++) {
  46.         elapsed_time_clr(i);
  47.     }
  48. }
  49. /*
  50. ********************************************************************************
  51. *                  START THE MEASUREMENT OF A CODE SECTION
  52. ********************************************************************************
  53. */
  54. void  elapsed_time_start (uint32_t  i)  
  55. {
  56.     elapsed_time_tbl[i].start = ARM_CM_DWT_CYCCNT;
  57. }
  58. /*
  59. ********************************************************************************
  60. *           STOP THE MEASUREMENT OF A CODE SECTION AND COMPUTE STATS
  61. ********************************************************************************
  62. */
  63. void  elapsed_time_stop (uint32_t  i)  
  64. {
  65.     uint32_t       stop; 
  66.     ELAPSED_TIME  *p_tbl;
  67.     
  68.     stop           = ARM_CM_DWT_CYCCNT;   
  69.     p_tbl          = &elapsed_time_tbl[i];
  70.     p_tbl->current = stop - p_tbl->start;
  71.     if (p_tbl->max < p_tbl->current) {
  72.         p_tbl->max = p_tbl->current;
  73.     }
  74.     if (p_tbl->min > p_tbl->current) {
  75.         p_tbl->min = p_tbl->current;
  76.     }
  77. }
  78. /*
  79. ********************************************************************************
  80. *                      CLEAR THE MEASUREMENTS STATS
  81. ********************************************************************************
  82. */
  83. void  elapsed_time_clr (uint32_t  i)         
  84. {
  85.     ELAPSED_TIME  *p_tbl;
  86.     
  87.     
  88.     p_tbl          = &elapsed_time_tbl[i];
  89.     p_tbl->start   = 0;
  90.     p_tbl->current = 0;
  91.     p_tbl->min     = 0xFFFFFFFF;
  92.     p_tbl->max     = 0;
  93. }
  94. elapsed_time.h
  95. /*
  96. ********************************************************************************
  97. *                       MODULE TO MEASURE EXECUTION TIME
  98. ********************************************************************************
  99. */
  100. /*
  101. ********************************************************************************
  102. *                MAXIMUM NUMBER OF ELAPSED TIME MEASUREMENT SECTIONS
  103. ********************************************************************************
  104. */
  105. #define  ELAPSED_TIME_MAX_SECTIONS  10
  106. /*
  107. ********************************************************************************
  108. *                             FUNCTION PROTOTYPES
  109. ********************************************************************************
  110. */
  111. void  elapsed_time_clr   (uint32_t  i);      // Clear measured values
  112. void  elapsed_time_init  (void);             // Module initialization
  113. void  elapsed_time_start (uint32_t  i);      // Start measurement 
  114. void  elapsed_time_stop  (uint32_t  i);      // Stop  measurement 

參考文獻(xiàn)

https://www.micrium.com/ucprobe/about/

https://www.iar.com/iar-embedded-workbench/

https://www.arm.com/products/processors/cortex-m

【本文來(lái)自專欄作者“老曹”的原創(chuàng)文章,作者微信公眾號(hào):喔家ArchiSelf,id:wrieless-com】


當(dāng)前標(biāo)題:MCU上的代碼執(zhí)行時(shí)間
URL分享:http://www.dlmjj.cn/article/djjjcde.html