发新帖本帖赏金 80.00元(功能说明)我要提问
返回列表
打印
[APM32F4]

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

[复制链接]
1884|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kai迪皮|  楼主 | 2023-10-17 14:19 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 kai迪皮 于 2023-10-18 17:20 编辑

#申请原创# @21小跑堂

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)


使用特权

评论回复

打赏榜单

21小跑堂 打赏了 80.00 元 2023-10-24
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
kai迪皮 2023-10-24 15:17 回复TA
@21小跑堂 :感谢支持,Thanks♪(・ω・)ノ 
21小跑堂 2023-10-24 14:31 回复TA
从MCU主频方向和AC6与AC5对比方向进行***测试,严谨细致,不再是单向测试,值得肯定。 
沙发
shanyuxiang| | 2023-10-18 13:24 | 只看该作者
F4的性能还是强啊!

使用特权

评论回复
板凳
kai迪皮|  楼主 | 2023-10-18 16:28 | 只看该作者
shanyuxiang 发表于 2023-10-18 13:24
F4的性能还是强啊!

是的呢

使用特权

评论回复
发新帖 本帖赏金 80.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

31

主题

212

帖子

11

粉丝