找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2791

积分

0

好友

387

主题
发表于 昨天 23:21 | 查看: 0| 回复: 0

在嵌入式处理器领域,衡量CPU性能最知名和常见的基准测试莫过于 CoreMarkDhrystone

  • CoreMark: 专门用于衡量嵌入式系统中CPU(或微控制器MCU)性能的标准,于2009年由EEMBC开发。
  • DMIPS: Dhrystone Million Instructions executed Per Second,主要用于测试系统的整数运算性能。

本文将结合瑞萨RA6M4开发板,提供一个详细的、基于e² studio开发环境的CoreMark移植教程,并分享关键的代码修改步骤。

CoreMark简介

CoreMark旨在取代过时的Dhrystone基准,成为行业标准。其测试代码完全用C语言编写,核心包含四种算法:列表处理(增删改查排序)、矩阵操作、状态机(校验数字)和CRC。开发者可以自由下载并移植到自己的平台运行,最终获得一个量化的性能分数。

下载CoreMark源码

首先,前往CoreMark官网下载官方源码:
https://www.eembc.org/coremark/index.php

解压后,我们主要关注以下核心文件:
CoreMark源码解压后的simple文件夹内容

移植所需的核心文件包括:

  • core_list_join.c
  • core_main.c
  • core_matrix.c
  • core_state.c
  • core_util.c
  • coremark.h
  • simple/core_portme.c
  • simple/core_portme.h

在e² studio中新建CoreMark测试工程

本文以RA6M4开发板为例,创建工程并选择正确的MCU型号。随后,将上述CoreMark源文件拷贝到工程的 src 文件夹下。
将CoreMark源码文件拷贝到e² studio工程的src目录下

关键提示:e² studio的FSP框架会自动生成一个main.c,其中直接调用hal_entry()函数。由于hal_entry.c是自动生成且无法删除,我们需要将core_main.c中的全部内容复制到hal_entry.c里,并把main(void)函数重命名为void hal_entry(void)
将core_main.c内容整合到hal_entry函数中

前期硬件功能准备

  1. 配置UART串口:用于打印CoreMark结果。本文假设串口打印功能(例如Uart0_printf)已调试完成。
  2. 配置定时器:设定一个1ms周期的定时器中断,用于精确计算CoreMark算法运行所耗费的时间。

移植后的关键代码修改步骤

1. 添加头文件

hal_entry.c 文件开头,加入串口打印功能所需的头文件。

#include “hal_data.h”
#include “stdio.h”
#include “uart_printf.h” // 你的串口打印头文件
#include “core_mark.h”

在hal_entry.c中添加串口打印头文件

2. 初始化外设

hal_entry函数的起始位置,添加打开GPIO和UART外设的代码。

void hal_entry(void)
{
    /* TODO: add your own code here */
    // ... 变量声明

    /**********Added function start**********/
    R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg); /* GPIO open */
    R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg); /* UART open */
    /**********Added function end**********/

    // ... 后续代码
}

在hal_entry函数中初始化UART和GPIO

3. 修改 portable_init 函数

系统的时钟等初始化已在启动文件startup.c中完成,且此函数无参数传入,因此需要修改core_portme.c中的portable_init函数。主要改动是移除参数,并将内部的ee_printf替换为自己的串口打印函数(如Uart0_printf)。

修改前:
portable_init函数修改前代码

修改后:

portable_init(core_portable *p)
{
    if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
        Uart0_printf(“ERROR! Please define ee_ptr_int to a type that holds a \“pointer!\n”);
    }
    if (sizeof(ee_u32) != 4) {
        Uart0_printf(“ERROR! Please define ee_u32 to a 32b unsigned type!\n”);
    }
    p->portable_id=1;
}

portable_init函数修改后代码

4. 修改计时相关代码

这是移植的核心,需要根据你使用的定时器修改时间获取函数。本例使用1ms定时器中断。

  • 修改计时函数 (core_portme.c)
    计时函数start_time/stop_time/get_time修改前后对比
    主要改动为:在start_time中启动定时器并清零计数器,在stop_time中停止定时器,get_time直接返回累加的Tick值。

  • 简化时间相关宏定义
    时间相关宏定义的简化修改
    仅需保留 #define EE_TICKS_PER_SEC (1000) (因为定时器1ms中断一次),其他与平台相关的宏可以注释或删除。

  • 添加定时器中断回调函数
    在合适的位置(如hal_entry.c)定义定时器中断服务函数,用于累加全局变量Tick

    /***********Added time counter***********/
    void Timer0_1ms_Callback(timer_callback_args_t *p_args)
    {
        if((p_args != NULL) && (p_args->event == TIMER_EVENT_CYCLE_END)) {
            Tick++;
        }
    }
    /***********************************************/

    1ms定时器中断回调函数实现

5. 调整迭代次数并声明Tick变量

为了保证测试的有效性,CoreMark要求程序运行时间至少大于10秒。你需要根据主频调整ITERATIONS的值。

core_portme.ccore_portme.h中修改:

#define ITERATIONS (12000) // 根据实际情况调整此值
static uint32_t Tick; // 声明在计时函数中使用的全局变量

修改迭代次数ITERATIONS并声明Tick变量

6. 设置编译器信息

core_portme.h中,定义COMPILER_FLAGS宏,用于在结果中标识你的编译环境。

#ifndef COMPILER_FLAGS
    #define COMPILER_FLAGS “FSP V2.3.0” // 替换为你的实际环境
#endif

定义编译器版本信息宏

7. 替换打印函数

在整个工程中,将CoreMark源码中默认的ee_printf()函数调用,全部替换为你自己的串口打印函数(例如Uart0_printf)。可以使用编辑器的“查找与替换”功能高效完成。

8. 使能e² studio的浮点数打印支持

e² studio的默认newlib-nano库配置不支持printf浮点数。需要手动开启此功能:

  1. 右键工程,选择 Properties
  2. 进入 C/C++ Build -> Settings -> Tool Settings -> GNU ARM Cross C Linker -> Miscellaneous
  3. 勾选 Use float with nano printf (-u_printf_float)
    在e² studio链接器设置中启用浮点数打印支持

运行测试与结果

完成以上所有修改并编译下载程序后,打开串口调试助手(波特率115200),复位开发板。你将看到CoreMark的测试结果输出。

RA6M4运行CoreMark的串口输出结果

结果中包含了关键的CoreMark/MHz分数(本例中约为355.84),以及算法正确性校验值。这为你评估MCU的计算机基础运算性能提供了一个权威的量化参考。

至此,基于瑞萨RA MCU的CoreMark移植就完成了。你可以将此框架应用到其他RA系列MCU上,只需根据具体型号调整时钟和引脚配置即可。如果在移植过程中遇到问题,欢迎在云栈社区的技术板块进行交流探讨。




上一篇:Qt QSettings 写入 Windows 注册表权限问题详解:拒绝访问(Access Denied)的成因与解决方案
下一篇:多智能体架构如何应对B端复杂业务:解耦与协同,取代单体智能体巨无霸
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-2 22:03 , Processed in 0.453253 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表