MCU性能測試最著名的部分是CoreMark和Dhrystone。
CoreMark以每秒迭代為性能評估,而Dhrystone的DMIPS與Dhrystone標準有關。
本文討論CoreMark,先來看看MCU廠家如何宣傳自家產(chǎn)品性能。
NXP i.MX RT1170,CoreMark:6468 ;ST STM32H747/757 CoreMark:3224
揭開神秘面紗:CoreMark是什么?為什么它可以作為MCU的性能指標?這個數(shù)是怎么計算出來的?
CoreMark是衡量嵌入式系統(tǒng)中微控制器性能的基準。通過包含列表處理(查找和排序)、矩陣處理(常見的矩陣操作)、狀態(tài)機(確定輸入流是否包含有效數(shù)字)和CRC(循環(huán)冗余校驗)等算法的測試給出性能評價。 需要下載的軟件包是免費開源的, 可以在官方網(wǎng)站找到:EEMBC’s CoreMark?,網(wǎng)頁截圖如下。部分朋友無法直接下載的,文末也提供下載好的軟件包。
作業(yè)不難:怎么將CoreMark移植到自己的MCU上?運行CoreMark需要哪些外設支持?
51單片機也可以跑CoreMark的,所以硬件上不用擔心。運行CoreMark,需要定時器提供計時功能,還需要一種向外部打印消息的手段。一個比較簡單的方法是,調(diào)用中定義的printf()函數(shù),將其重定向到串口?,F(xiàn)以使用STM32CubeIDE將CoreMark移植到STM32G071為例進行說明。
- Step1:復制必要文件到目標工程?,F(xiàn)已準備好目標MCU的軟件工程,其文件結(jié)構如下圖右側(cè)所示。從CoreMark官網(wǎng)獲得軟件包,軟件包解壓后文件結(jié)構如下圖左側(cè)所示。在右側(cè)軟件工程中新建文件夾CoreMark,將左側(cè)綠色框中,core_li、core_main.c、core_ma、core_、core_u、coremark.h等文件放到CoreMark文件夾里。打開左側(cè)simple文件夾,將core_復制到Src文件夾中,將core_復制到Inc文件夾中。
復制
- Step2:由于core_main.c文件已定義了main()函數(shù),該main()函數(shù)執(zhí)行時調(diào)用core_中的portable_init()函數(shù)作為MCU初始化接口,因此需要將MCU工程中原main.c文件MCU初始化代碼移動到到portable_init()函數(shù)里并刪除原有main.c文件。以STM32CubeIDE工程為例,需要移動SystemClock_Config和一堆MX_開頭的初始化函數(shù)(注意相關結(jié)構體、函數(shù)原型與函數(shù)實現(xiàn)要一起移動)。
- Step3:CoreMark的分數(shù)最終表示為Iterations/Sec,也就是每秒迭代數(shù),而Sec和系統(tǒng)Ticks相關。用過RTOS的朋友應該對這個概念很熟悉,考慮文字不太好解釋,直接看core_里這個宏定義。
復制
#define EE_TICKS_PER_SEC 1000
- 這里我定義每秒1000個Tick,每個Tick時長1ms,對應定時器每1ms觸發(fā)一次中斷。使用一個計數(shù)變量,定時器進入中斷一次,該變量值+1;對該變量值/1000即可求得定時器運行時長,也就是上文的Sec。所以EE_TICKS_PER_SEC并非一定要設置為1000,和定時器中斷頻率對應即可。與定時相關的函數(shù)有以下三個,
復制
void start_time(void); //啟動計時器;
void stop_time(void); //停止計時器;
CORE_TICKS get_time(void); //獲取計時器的計數(shù)值。
- 在start_time()里實現(xiàn)定時器啟動功能,在stop_time()里實現(xiàn)定時器停止功能,在get_time()中獲取中斷計數(shù)值。數(shù)據(jù)類型“CORE_TICKS ”實際上就是“unsigned long”。為方便操作,推薦將計數(shù)變量設置為全局變量,這樣可以通過extern關鍵字直接訪問。此處以TIM1為例,代碼如下:
復制
//計數(shù)變量
unsigned long time_ms_ticks=0;
//定時器啟動
void start_time(void)
{
(&htim1)->State = HAL_TIM_STATE_BUSY;
__HAL_TIM_ENABLE(&htim1);
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
}
//定時器停止
void stop_time(void)
{
__HAL_TIM_DISABLE_IT(&htim1, TIM_IT_UPDATE);
__HAL_TIM_DISABLE(&htim1);
(&htim1)->State = HAL_TIM_STATE_READY;
}
//獲取中斷計數(shù)值
CORE_TICKS get_time(void)
{
return time_ms_ticks;
}
//中斷處理函數(shù)
extern unsigned long time_ms_ticks;
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim1);
time_ms_ticks=time_ms_ticks+1;
}
- 注釋部分不使用的代碼。以下代碼位于core_中,需要注釋掉:
復制
//#define NSECS_PER_SEC CLOCKS_PER_SEC
//#define CORETIMETYPE clock_t
//#define GETMYTIME(_t) (*_t = clock())
//#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
//#define TIMER_RES_DIVIDER 1
//#define SAMPLE_TIME_IMPLEMENTATION 1
//static CORETIMETYPE start_time_val, stop_time_val;
- CoreMark要求的最短測試時間為10s,若測試時間低于10s則會報錯,見下圖:
- 為獲得有效的測試結(jié)果,需修改core_中關于ITERATIONS的設置,官方代碼中ITERATIONS沒有定義:
復制
volatile ee_s32 seed4_volatile = ITERATIONS;
- 此處使用STM32G071,主頻64MHz。經(jīng)測試ITERATIONS修改為1200左右即可,
復制
volatile ee_s32 seed4_volatile = 1200;
- Step4:打印測試結(jié)果時,編譯器優(yōu)化等級和調(diào)試等級也可以打印出來。這類信息可在core_中通過宏COMPILER_FLAGS修改。這里我使用-Ofast優(yōu)化,調(diào)試等級-g3,修改如下:
復制
#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS "-Ofast -g3"
#endif
- 重定向printf到串口,可參考以下代碼(以STM32 LPUART1為例),根據(jù)IDE不同可能需要添加float類型支持:
復制
__io_putchar (int ch)
{
HAL_UART_Transmit (&hlpuart1, (uint8_t*) &ch, 1, 0x0F);
return ch;
}
- Step5:移植完成!編譯程序下載運行,得到跑分結(jié)果:
STM32G071RB,64MHz,108.9分!
通常使用最高主頻和-Ofast優(yōu)化可以獲取最大分數(shù),歡迎大家把自己的跑分放到評論區(qū)。
歡迎大家把自己的跑分放到評論區(qū)。
附件詳見論壇原帖。
原標題:MCU性能測試,CoreMark極簡入門教程!
原作者:Litthins
本文為21ic有獎征文作品,詳情請見21ic論壇活動專區(qū):第二屆萬元紅包——藍V達人有獎征文活動,如果您也有興趣參與征文,歡迎進入論壇參與活動~
1.《關于如何初始化接口,你需要知道這些MCU性能測試,CoreMark極簡入門教程》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡信息知識,僅代表作者本人觀點,與本網(wǎng)站無關,侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《關于如何初始化接口,你需要知道這些MCU性能測試,CoreMark極簡入門教程》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。
3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/gl/2104358.html