MM32L373 CoreMark跑分测试

Introduction of CoreMark

CoreMark 是一项衡量嵌入式系统中微控制器(MCU)和中央处理器(CPU)性能的基准测试。运用CoreMark测试MCU核心性能时,通过计算MCU运行一定次数的标准程序算法所需要的运算时间,得到最终分数,时间越短,分数越高,MCU性能越好。Coremakr包含以下算法:

  • 列表处理(查找和排序)
  • 矩阵操作(常见的矩阵操作)
  • 状态机(判断输入流是否包含有效数字)
  • CRC(循环冗余检查)

关于CoreMark具体的介绍可以参考CoreMark官网,或是参考CoreMark github

接下来介绍如何将Coremark移植到MM32L373上,并对它进行性能测试。

Create Project of MM32

  1. 打开IAR,新建一个工程

    • 新建工作空间

      File→New→Workspace

    • 新建工程

      • Project→Create New Project

      • Tool chain默认ARM

      • Project templates默认Empty project

  2. 配置工程

    • 芯片选择

      这里选择的芯片是MM32L373PS。

      tz_device

    • 添加bsp、lib、User文件夹,将startup和HAL_lib文件放入lib

      tz_lib_bsp

    • 配置头文件路径

      在Additional include directories中添加bsp、HAL、startup以及User的头文件路径。

      tz_preprocessor

    • 配置宏定义

      在Defined Symbols中添加宏定义。
      tz_macro_definition

    • 配置仿真器

      • 选择Debugger→Setup→Driver→Third-Party Driver

      • 配置第三方仿真器

        在这里插入图片描述

  3. 添加工程文件

    • 右键Add→AddGroup,添加bsp、lib、system、user四组
    • 在每组上右键Add→AddFiles,bsp中添加bsp文件,lib中添加HAL文件,system中添加startup_mm32.c和system_mm32.c。

这样MM32的工程就新建好了,可以在user里添加main.c测试一下工程是否新建成功。

Transplant CoreMark

  1. 克隆CoreMark测试代码

    CoreMark在github上开源了它的测试代码:eembc/coremark,首先将测试代码克隆下来。

    需要用到的代码文件如下:

    tz_coremark_project

  2. 将克隆的CoreMark代码添加到MM32工程中

    • 在User文件夹中新建Coremark文件夹,拷贝以下代码文件至coremark文件夹中。

      tz_user_coremark

    • 将core_portme.c拷贝至User文件夹中,将core_portme.h拷贝至inc文件夹中。

      tz_user

  3. 在IAR工程中配置新添加的coremark代码文件

    • 添加coremark.h的头文件路径

      tz_coremark_processor

    • 在users中添加工程文件

      tz_user_core

Modify Coremark Code

  1. 修改core_portme文件中的初始化代码

    • 添加Coremark_UART1_Init()函数,用于UART1的配置及初始化

      void Coremark_UART1_Init(){
          COMMON_EnableIpClock(emCLOCK_UART1);
      
          UART_InitTypeDef pUARTInit;
          UART_StructInit(&pUARTInit);
      
          pUARTInit.BaudRate      = 115200;
          pUARTInit.WordLength    = UART_WordLength_8b;
          pUARTInit.StopBits      = UART_StopBits_1;
          pUARTInit.Parity        = UART_Parity_No;
          pUARTInit.Mode          = UART_Mode_Rx | UART_Mode_Tx;
          pUARTInit.HWFlowControl = UART_HWFlowControl_None;
      
          UART_Init(UART1, &pUARTInit);
          UART_Cmd(UART1, ENABLE);
      
          BSP_UART_GPIO_CONFIGURE(UART1);
      }
      
    • 添加AppTaskTick()函数,用于系统时钟配置

      void AppTaskTick()
      {
          if (tickCnt++ >= 500) {
              tickCnt  = 0;
              tickFlag = true;
      	}
      }
      
    • 在portable_init函数中添加时钟配置函数及UART初始化函数

      /* Function : portable_init
              Target specific initialization code
              Test for some common mistakes.
      */
      void
      portable_init(core_portable *p, int *argc, char *argv[])
      {
          /* Set System Clock */
          MCUID = SetSystemClock(emSYSTICK_On, AppTaskTick);
          /* UART Configuration & Initialization */
          Coremark_UART1_Init();
      
          if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
          {
              ee_printf(
                  "ERROR! Please define ee_ptr_int to a type that holds a "
                  "pointer!\n");
          }
          if (sizeof(ee_u32) != 4)
          {
              ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
          }
          p->portable_id = 1;
      }
      
    • 添加printf重定向,以此可以通过C语言标准库函数printf()将信息打印到串口

      #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */
      #define PUTCHAR_PROTOTYPE
       int __io_putchar(int ch)
      #else
      #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
      #endif /* __GNUC__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */
      PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
      
       while (UART_GetFlagStatus(UART1, UART_IT_TXIEN) == RESET);
       UART_ClearITPendingBit(UART1, UART_IT_TXIEN);
       UART_SendData(UART1, (uint8_t)ch);
           
       return ch;
      }
      

      这里需要将IAR中的库选成Full,使其支持所有C/C++标准库函数。

      tz_library_full

    • 在core_portme.h文件中添加头文件和函数申明

      #include <inttypes.h>
      #include "system_mm32.h"
      #include "common.h"
      #include "HAL_uart.h"
      #include "bsp_uart.h"
      
      void AppTaskTick();
      static void Coremark_UART1_Init(void);
      
  2. 修改core_portme文件中的计时代码

    core_portme.c中有start_time、stop_time、get_time三个计时相关的函数,依次对他们进行修改。使用SysTick定时器进行计时,每进依次中断Tick值加1。

    • 修改start_time()

      void start_time(void)
      {
          Tick = 0;
      }
      
    • 修改stop_time()

      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;
      }
      
    • 修改get_time()

      CORE_TICKS get_time(void)
      {
          CORE_TICKS elapsed = (CORE_TICKS)Tick;
          return elapsed;
      }
      
    • 修改宏定义

      /* Comment out the Original Code */
      
      //#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)
      //
      ///** Define Host specific (POSIX), or target specific global time variables. */
      //static CORETIMETYPE start_time_val, stop_time_val;
      
      /* Add the following code */
      #define SysTick_Counter_Disable ((uint32_t)0xFFFFFFFE)
      #define SysTick_Counter_Enable ((uint32_t)0x00000001)
      #define SysTick_Counter_Clear ((uint32_t)0x00000000)
      #define EE_TICKS_PER_SEC 1000
      __IO uint32_t Tick;
      
    • 在system_mm32.c文件中修改SysTick的中断处理函数

      每次进中断,Tick+1

      void SysTick_Handler(void)
      {
          extern __IO uint32_t Tick;
          Tick++;
      }
      
  3. 在core_portme.h中配置CoreMark运行参数

    • 添加Coremark计算迭代次数

      #define ITERATIONS 10000
      
    • 修改打印信息

      // #ifndef COMPILER_FLAGS
      // #define COMPILER_FLAGS \
      //     FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
      // #endif
      #ifndef COMPILER_FLAGS
      #define COMPILER_FLAGS "-Ohs -no_size_constraints"
      #endif
      
  4. 将stack空间扩大到0x2000

    tz_stack

  5. 修改程序运行优先级

    选择High Speed,提升运行速度

    tz_optimization

Result

tz_result_L373
代码可以在Miao-T github上拉取。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值