【技术分享】APM32F411 CoreMark 测试分享

1 前言

CoreMark,是业内认可度较高的衡量MCU性能的一个测试。它的测试分数在一定意义上衡量了该款MCU的性能优劣,也可以使得工程师在芯片选型时有一定的参考。

该测试代码使用C语言进行编写,涵盖列表、数学矩阵等运算操作,并没有与内核相关的操作,单纯是进行运算测试。

由于实现是C语言代码,不同的编译器及优化等级也会影响到该测试分数的最终呈现,刚刚好极海官方提供的APM32F411的demo包含了以下环境:

1. Keil MDK
2. IAR
3. Eclipse + gcc

我对CoreMark进行一个学习的同时,就上面的三个环境进行APM32F411的测试验证CoreMark。

2 CoreMark 的移植

我们先获取CoreMark的源码:

获取APM32F411的SDK:

2.1 移植思路

首先我们先总结一下CoreMark需要的一些底层驱动:

1. printf 重定向。
2. 系统时间的计时。

根据以上需求,结合手上的APM32F411 TINY 板我们需要初始化APM32F411的外设有:

1. USART1
2. 系统滴答时钟。

2.2 测试环境

我的测试目标是看不同编译器环境下的APM32F411的测试分数,那我们需要准备的测试环境有:

1. Keil MDK (AC5/AC6)
2. IAR
3. Eclipse +Gcc

环境的搭建步骤我这里就不赘述,相信我们的小伙伴都可以解决。这里也统一规定各个测试编译器的优化等级都为最高优化等级“-O3”

2.3 添加源码

我们把CoreMark源码中的以下文件复制至APM32F411的SDK中的Middlewares文件夹里:
 



2.4 工程包含源码

我这里选取官方提供的Examples中的“SysTick”例程进行CoreMark源码的添加(我复制了一份SysTick并改名为了CoreMark)。由于不同的开发环境对源码的添加方式有些许的差异,我这里就不一一说明(水文)了。

Keil MDK的话就是像图中的添加方式:
 



2.5 添加头文件包含

由于不同的开发环境对源码的添加方式有些许的差异,我这里就不一一说明(水文)了。

Keil MDK的话就是像图中的添加方式:
 



2.6 修改例程源码

回过头来看我们的移植思路,首先我们确认一下我们复制的“SysTick”有没有以下要点:

1. printf 重定向。
2. 系统时间的计时。

哦吼,printf 重定向有了,但是系统时间的计时,例程中是用来计时延时的,并不能用来指示当前时间。我们需要简单修改一下。

我们定义一个时间计数变量,让它每进入一次滴答中断(进入中断的时间是1ms 一次),自加一次:
 

复制
unsigned int system_tick = 0;



void SysTick_Init(void)

{

    SystemCoreClock = RCM_ReadSYSCLKFreq();

    /* SystemCoreClock / 1000 = 1ms */

    if (SysTick_Config(SystemCoreClock / 1000))

    {

        /* Capture error */

        while (1);

    }

}



void system_tick_fun(void)

{

    system_tick++;

}



与此同时我们也把当前的MCU及系统时钟信息也打印一下:
 

复制
    printf("\r\n");

    printf("\r\n");

    printf("******************************************\r\n");

    printf("APM32F411 CoreMark \r\n");

    printf("SystemCoreClock: %d Hz\r\n",SystemCoreClock);

    printf("******************************************\r\n");


更重要的是由于CoreMark测试需要更大的堆栈空间,建议把堆栈空间改大至0x1000;

2.7 修改CoreMark源码

2.7.1 core_portme.h

这里我们需要重点修改一下core_portme.h文件:

1. 编译器定义:

复制
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION

        Initialize these strings per platform

*/

#ifndef COMPILER_VERSION

#ifdef __GNUC__

#define COMPILER_VERSION "GCC"__VERSION__

#elif defined (__ICCARM__)

#define COMPILER_VERSION "ICCARM"__VERSION__

#elif defined (__CC_ARM)

//#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"

#define COMPILER_VERSION "Armcc V5.06 update 6 (build 750)"

#endif

#endif


2. 代码优化等级

复制
#ifndef COMPILER_FLAGS

#define COMPILER_FLAGS \

    "-O3"

//    FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */

#endif


3. 主测试函数的变量支持

复制
#define MAIN_HAS_NOARGC 1


2.7.2 core_portme.c

接下来我们修改core_portme.c中对于时基相关的定义:

复制
#define ITERATIONS 4000



extern unsigned int system_tick;



ITERATIONS是循环测试多少次CoreMark的相关测试,我这里设置是4000,需要注意的是不同的芯片该值是有差异的,如果你是移植至其他芯片,需要注意这里的取值。

复制
#define NSECS_PER_SEC              1000//CLOCKS_PER_SEC

#define CORETIMETYPE               clock_t

//#define GETMYTIME(_t)              (*_t = clock())



#define GETMYTIME(_t)              (*_t = system_tick)


然后是NSECS_PER_SEC,告诉系统我们的时基(1S)中有多少计数值,由于我的时基是1ms,所以这里设置是“1000”。
GETMYTIME(_t)是获取当前的计数值,这里直接返回我们在滴答定时器中的system_tick变量。

2.7.3 core_main.c

由于我们是已经有一个主函数了,需要在已有的主函数调用CoreMark测试主函数,我们这里修改一下CoreMark的主函数名字(core_main.c中):

复制
#if MAIN_HAS_NOARGC

MAIN_RETURN_TYPE

CoreMark_main(void)

{

    int   argc = 0;

    char *argv[1];

#else

MAIN_RETURN_TYPE

CoreMark_main(int argc, char *argv[])

{


由于测试的分数还有一个衡量,就是“CoreMark/MHz”分数。我们在测试分数输出的地方加入该测试分数的输出:

复制
ee_printf("CoreMark 1.0 : %f / %s %s",

                      default_num_contexts * results[0].iterations

                          / time_in_secs(total_time),

                      COMPILER_VERSION,

                      COMPILER_FLAGS);

            ee_printf("\r\n");



            extern unsigned int SystemCoreClock;

            ee_printf("CoreMark/MHz 1.0 : %f / %s %s",

                      default_num_contexts * results[0].iterations / (SystemCoreClock/1000000)

                          / time_in_secs(total_time),

                      COMPILER_VERSION,

                      COMPILER_FLAGS);


2.7.4 其他

由于我的串口助手是使用“\r\n”换行,我这里就把CoreMark测试代码里面的“\r”换行全部修改了。这里就不一一赘述。

2.8 设置优化等级

由于我们主要测试最高优化等级的CoreMark分数,我们需要吧各个编译器的优化等级进行调整:

1. Keil MDK
    



2. IAR
    



3. Eclipse + gcc
    



3 进行CoreMark测试

完成代码移植,编译无误后进行测试。

3.1 主频100Mhz

首先是主频100Mhz的测试:

1. Keil MDK AC5
    



2. Keil MDK AC6
    



3. IAR 8.5
    



4. Eclipse +gcc
    



3.2 主频120Mhz

然后是主频120MHz的测试:

1. Keil MDK AC5
    



2. Keil MDK AC6
    



3. IAR 8.5
    



4. Eclipse +gcc
   



4 数据总结

经测试汇总,不同主频及编译器情况下CoreMark测试汇总画出折线图。

 


通过以上数据我们发现:

1. 在相同情况下.AC6编译器的效率是最好的(PS,难怪Keil 不维护 AC5了,(*/ω\*))。
2. 芯片主频提升后,CoreMark分数整体上升但是CoreMark/MHz的分数不一定上升。这个时候如果考虑功耗(主频越高功耗肯定随之上升)等多方面,芯片是否使用高主频去工作得再三思虑。


这里是参考代码 

 APM32F4xx_SDK_V1.4_CoreMark.zip (1.23 MB) 
---------------------
作者:kai迪皮
链接:https://bbs.21ic.com/icview-3333812-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值