【AT32F421测评】+ CoreMark跑分
[复制链接]
上篇测评,我们已经搭好了开发所需的环境,并且从0开始新建一个工程,并成功打印 Hello World
接下来,我将给单片机跑个分,现在很多电子产品消费者在选择时都会进行横向对比,比如各种参数性能呀,尤其像现在的手机,电脑,商家在宣传性能时都会展现自家的跑分,比如基于安兔兔的手机跑分,基于CPU-Z AID64的电脑跑分等,虽然跑分并不能完全代表硬件的真实性能,但是也可以做一定程度上的参考。同理选择MCU时,我们一方面当然是要满足自身项目的要求,另一方面更偏向于选择性价比更高的MCU。
那么,基于单片机的性能跑分就应运而生了,说到性能测试,最著名的就是CoreMark和Dhrystone。虽然Dhrystone的测试可以作为参考,但更容易受到其他因素的影响下。
而CoreMark能接近实际地反应出工作能力。它是由嵌入式微处理器基准测试联盟(EEMBC)开发,为了取代过时的Dhrystone标准。ARM官方也是建议使用CoreMark而不是Dhrystone来进行基准测试。
软件使用C语言编写,是一个免费使用,易于移植的基准测试程序。目前CoreMark已经成为测量与比较各类处理器性能的业界标准基准测试。CoreMark得分越高,意味着性能更高。下图为CoreMark与Dhrystone对比
来源于网络
CoreMark的模拟工作负载主要包含几种常用的算法:
矩阵操作:模拟常用的运算;
链表操作:模拟指针的各种用法;
状态机操作:模拟程序分支运行操作;
循环冗余校验(CRC):嵌入式系统常见的功能。
接下来,我们开始移植CoreMark。
第一步,先去官网在相应位置下载源代码,网站为www.eembc.org 下好的文件如下图所示,
第二步,打开我在上一篇测评新建的工程“AT32_Demo”(https://bbs.eeworld.com.cn/thread-1163406-1-1.html)新建一个子文件夹CoreMark,将core_list_join.c、core_main.c、core_matrix.c、core_state.c、core_util.c、coremark.h放入其中,再新建一个子文件夹CoreMark_Test,将simple文件夹中的core_portme.c和core_portme.h放入其中。同时打开工程,将上述的c文件添加到工程,记得不要忘了添加路径哦。最终效果如下,(在此工程中,我将串口相关配置和使用都单独放在了USART.c里,并将其放在HARDWARE文件夹里,这里说明一下)
第三步,因为在core_main.c文件里已经有main()函数,所以我们要将原来工程中的main函数屏蔽或删除,我这里选择屏蔽,选择main.c,右键选择第一个,将下图include in Target Build勾选去掉,如下图所示,
最重要的移植工作是适配core_portme.c,
首先,添加
#define SysTick_Counter_Disable ((uint32_t)0xFFFFFFFE)
#define SysTick_Counter_Enable ((uint32_t)0x00000001)
#define SysTick_Counter_Clear ((uint32_t)0x00000000)
__IO uint32_t Ticks;
#define ITERATIONS 2500;
ITERATIONS这个视情况而定,如果出现ERROR! Must execute for at least 10 secs for a valid result!,那么需要将此数值变大使程序运行时间至少在10秒以上。
同时,将以下代码屏蔽
#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
#define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER)
static CORETIMETYPE start_time_val, stop_time_val;
添加
#define EE_TICKS_PER_SEC 1000.0
将原有这三个函数修改为以下内容
void start_time(void)
{
Ticks++;
SysTick_Config(SystemCoreClock / 1000);//1ms中断
}
void stop_time(void)
{
/* Stop the Timer and get the encoding time */
SysTick->CTRL &=SysTick_Counter_Disable;
/* Clear the SysTick Counter */
SysTick->VAL = SysTick_Counter_Clear;
}
CORE_TICKS get_time(void)
{
CORE_TICKS elapsed=(CORE_TICKS) Ticks;//(MYTIMEDIFF(stop_time_val, start_time_val));
return elapsed;
}
同时由于core_main.c中的main函数执行时先调用core_portme.c中的portable_init函数,因此需要将原来main函数中的 RCC_Configuration、GPIO_Configuration、 NVIC_Configuration、assert_failed放到core_portme.c 同时在portable_init函数里调用,如下图所示(USART_Configuration在USART.c里,记得添加USART.h哦)
第四步,修改core_portme.h和coremark.h.首先要适配ee_printf打印函数,因为我们的板子已经实现了printf函数,所以保持coremark.h下面代码块不变
#if HAS_PRINTF
#define ee_printf printf
#endif
这样程序调用时会将ee_printf替换成printf实现打印功能
如果板子没有printf函数,得自己实现打印函数并进行相应替换.
同时,将core_portme.h中的下列函数改成你对应的编译器版本和优化等级
#ifndef COMPILER_VERSION
#ifdef __GNUC__
#define COMPILER_VERSION "GCC"__VERSION__
#else
#define COMPILER_VERSION "ARM Compiler 5.06 update 7 (build 960)"//changed
#endif
#endif
#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS "-g -O3 -Otime"//changed /* "Please put compiler flags here (e.g. -o3)" */
#endif
#ifndef MEM_LOCATION
#define MEM_LOCATION "STACK"
#endif
最后,因为我们是用系统滴答定时器来计时的,也就是start_time、stop_time、CORE_TICKS get_time所需要定时基准,所以要将at32f4xx_it.c 中的SysTick_Handler修改成以下代码;
extern __IO uint32_t Ticks;
void SysTick_Handler(void)
{
Ticks++;
}
最后一步,将Optimization,也就是优化等级改成Level 3,同时将芯片频率改成120MHZ,这样跑分更高。这里需要注意的是运行CoreMark需要很大的栈内存,所以我们要将startup_at32f421c8t7.s启动文件中的Stack_Size EQU 0x00000400改成了Stack_Size EQU 0x00001000
这里说明一点,有些移植细节我可能讲忘了,比如各种头文件,但重要的步骤我已经都讲了,具体可用的程序见我上传的文件。
编译,下载好后,如果都正常的话,用串口助手观察会出现以下信息
最后分数为201分,这里我要说明一点,可能由于IDE版本不同,编译链不同或者其他硬件原因,又或者个人能力有限,没考虑到一些细节,导致CoreMark分数不一样或者并不是AT32F421的真正性能,所以我只对我所运行的程序及配套软硬件负责。作为对比,我还测试了STM32F103RCT6,跑分只有86分,不及官方宣称的分数。
------------------------------------------------------------------
CoreMark Test Begin!
Transplant CoreMark programs By DMZ!
CoreMark Test is runing, Plase Wait!
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 17303
Total time (secs): 17.303000
Iterations/Sec : 86.690169
Iterations : 1500
Compiler version : ARM Compiler 5.06 update 7 (build 960)
Compiler flags : -g -O3 -Otime
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0x25b5
Correct operation validated. See readme.txt for run and reporting rules.
CoreMark 1.0 : 86.690169 / ARM Compiler 5.06 update 7 (build 960) -g -O3 -Otime / STACK
补充一下,在后来的查阅相关资料时,发现MDK 5的优化选项有一个Optimize for time, 当勾选时,CoreMark跑分会变高,原因大概是在keil中,在不选择"Optimize for time"编译选项时,局部float变量占用8个字节(编译器默认自动扩展成double类型),,一旦你使用"Optimize for time"编译选项,局部float变量只会占用4个字节.也就是优化了很多不必要的累赘变量定义,能大大优化编译速度,具体我也不太懂,这个应该是各个编译器的特点吧,我也不太懂其中的原理.但是我还是要尝试一下,当我将Optimize for time勾选,跑分竟然提高了50%多,如下图,当然此时要将ITERATIONS改大,我这里选择3500,不然不足10S
同时,我写修改了一下STM32F103的程序,也勾选了Optimize for time,跑分也提高了50%多,虽然还没到官方宣称的,但比原来更接近了,如下面展示的
------------------------------------------------------------------
CoreMark Test Begin!
Transplant CoreMark programs By DMZ!
CoreMark Test is runing, Plase Wait!
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 11323
Total time (secs): 11.323000
Iterations/Sec : 132.473726
Iterations : 1500
Compiler version : ARM Compiler 5.06 update 7 (build 960)
Compiler flags : -g -O3 -Otime
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0x25b5
Correct operation validated. See readme.txt for run and reporting rules.
CoreMark 1.0 : 132.473726 / ARM Compiler 5.06 update 7 (build 960) -g -O3 -Otime / STACK
------------------------------------------------------------------
CoreMark(同一测试程序和IDE及相关配置)
|
未勾选Optimize for time
|
勾选Optimize for time
|
AT32F421C8T7(120MHZ)
|
201.3
|
316.9
|
STM32F103RCT6(72MHZ)
|
86.7
|
132.7
|
根据上面的表格,最后得出结论,仅限我本人的软硬件和手头的测试板,120MHZ的AT32F421性能(基于CoreMark)可以说是72MHZ的STM32F103的两倍有余。
本次测评完毕,总的来说雅特力的超值型AT32F421性价比还是非常不错的
参考资料:
http://mcu.eetrend.com/content/2019/100046454.html
https://www.bilibili.com/read/cv7196931/
https://bbs.eeworld.com.cn/thread-610349-1-1.html
|