痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(2)- RT1052DVL6性能实测(CoreMark)
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MX RT1xxx系列MCU的性能。
在前面的文章 i.MXRT1xxx微控制器概览 里,痞子衡给大家简介过恩智浦半导体在2017年推出的新一代跨界微控制器i.MX RT1xxx系列,该系列第一款芯片i.MXRT105x性能完爆同时期市面上所有的微控制器,官方公布的CoreMark跑分高达3020,有人可能不明白这个数字意味着什么,作为对比,我们再来看看意法半导体最流行的芯片STM32F103RB,它的CoreMark是108(此处应该有类似My God的尖叫),真是没有对比就没有伤害,那么i.MXRT105x性能到底有没有这么强?今天痞子衡为大家实测一下。
关于CoreMark标准的基本知识,痞子衡之前专门写过一篇文章 微控制器CPU性能测试基准(EEMBC-CoreMark) ,本篇就是基于了解CoreMark基本知识之后的一次实践。来,让我们开始吧。
一、准备工作
1.1 硬件平台NXP i.MX RT1050 EVK
要开始实测i.MXRT105x的CoreMark,首先你得有一块开发板,恩智浦官网上有i.MXRT105x配套的评估板,如下图所示,痞子衡今天用的就是这块板子,板载主芯片型号为iMXRT1052DVL6。
1.2 集成开发环境IAR EWARM
ARM Cortex-M微控制器的集成开发环境有很多,其中IAR EWARM凭借优良的特性备受广大工程师青睐,且痞子衡在CoreMark标准基本知识介绍文章的最后贴出了一张iMXRT1050与STM32H743性能对比图,其中CoreMark跑分就是在IAR下得到的,所以今天痞子衡也选用IAR作为软件环境,具体版本为IAR EWARM v8.20.2。
1.3 官方软件开发包NXP MCUXpresso SDK
在开始移植CoreMark程序到i.MXRT1052上之前,我们需要先有一个i.MXRT1052的基本hello world的例程,当然我们可以对着数据手册自己从头写一个,但是这里痞子衡推荐使用官方软件开发包。
注册并登录恩智浦官网,来到 MCUXpresso SDK Builder 页面,在"Select Development Board"里选择EVKB-IMXRT1050后点击Build MCUXpresso SDK后跳转到下一个页面,在"Developer Environment Settings"里选择IAR并点击Download SDK后便可得到SDK_2.3.1_EVKB-IMXRT1050.zip,下面是痞子衡下载的开发包具体版本信息:
二、开始实测
2.1 跑通hello world
给i.MXRT1050 EVK板子供电(J2口接5V输出的电源),并且使用USB线连接电脑与板子的J28 USB口,此时在设备管理器应该可以看到USB虚拟的串口(EVK板载OpenSDA调试器内含USB转串口功能,如果看不到串口,请自行安装PE Micro驱动)。
打开前一步下载的开发包里的\SDK_2.3.1_EVKB-IMXRT1050\boards\evkbimxrt1050\demo_apps\hello_world\iar\hello_world.eww工程,确认工程option里linker文件选择的是MIMXRT1052xxxxx_ram.icf,然后J21 JTAG口连接上Jlink Plus直接将工程下载进主芯片的RAM运行。
如果工程运行正常,你在串口调试助手(115200,8N1)里应该能看到"hello world."打印输出。
2.2 移植CoreMark程序
以hello_world工程为基础,将从EEMBC官网下载到的coremark_v1.0.tgz包解压,将\coremark_v1.0\以及\coremark_v1.0\barebones\路径下的如下所有源文件(.c或.h)全部拷贝到hello world工程目录下
\coremark_v1.0
\barebones --移植到裸机下需要修改的文件
\core_portme.h -- 移植平台工程具体配置信息
\core_portme.c -- 计时以及板级初始化实现
\cvt.c
\ee_printf.c -- 打印函数串口发送实现
core_main.c --主程序入口
core_state.c --状态机控制子程序
core_list_join.c --列表操作子程序
core_matrix.c --矩阵运算子程序
core_util.c --CRC计算子程序
coremark.h --工程配置与数据结构定义
将上面的所有coremark源文件全部添加进hello_world工程,并从工程中移除原主函数入口文件hello_world.c,此时基本coremark工程就完成了。但注意此时工程无法编译,因为从\coremark_v1.0\barebones\下拷贝的源文件还需要进一步修改。
2.2.1 板级初始化
程序移植的第一步是实现板载初始化,编译上一步建好的coremark工程会报这样的错误error "Call board initialization routines in portable init (if needed), in particular initialize UART!\n"。其实这是coremark作者故意在core_portme.c里的portable_init()函数里留下的提示,我们需要用i.MXRT1052的板级初始化函数替代这个#error,打开之前移除的hello_world.c文件,将其中板级初始化函数调用拷贝到portable_init函数中:
void portable_init(core_portable *p, int *argc, char *argv[])
{
// 删除#error提示
//#error "Call board initialization routines in portable init (if needed), in particular initialize UART!\n"
// 添加板级初始化调用
/* Init board hardware. */
BOARD_InitHardware();
//...
}
原hello_world里的BOARD_InitHardware已经包含了系统时钟以及UART初始化,所以这里的移植工作就算结束了。
2.2.2 计时功能
程序移植的第二步是实现计时功能,由于CoreMark得分其实是单位时间内跑了多少次CoreMark程序,所以CoreMark工程必须要有计时功能。编译coremark工程会报这样的错误error "You must implement a method to measure time in barebones_clock()! This function should return current time.\n",这也是coremark作者故意在core_portme.barebones_clock()函数里留下的提示。
关于计时器,第一个想到的自然是Cortex-M内核里的SysTick,不过考虑到coremark程序是要跑在600MHz的主频下,而SysTick计时器只有24bit,也就是说即使SysTick->LOAD设最大的reload值0xFFFFFF,也将每隔0.02796s(0x1000000/600MHz)产生一次SysTick中断,而CoreMark程序至少要跑10s以上,在coremark运行的10s内会产生357次(10/0.02796)SysTick中断,这无疑会降低coremark得分,所以SysTick直接被pass。(备注:SysTick->CTRL[2]用于选择SysTick的时钟源,默认1'b0为Core Clock,1'b1为外部clock,暂未研究这里的外部clock在i.MXRT105x上是否能用)。
翻看i.MXRT1052的参考手册,其支持的计时器种类很多,有GPT、PIT、TMR、WDOG,就选择比较常用的32bit计时器PIT吧。
之前下载的软件包里也有PIT的例程\SDK_2.3.1_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\pit,打开pit.c文件将其中PIT初始化相关代码放入新定义的timer_pit_init()函数中并在portable_init()中调用timer_pit_init()一次以完成PIT初始化。
barebones_clock()函数中的#error也需要被PIT_GetCurrentTimerCount()函数替换,此外还需要添加定义#define CLOCKS_PER_SEC (24000000),因为我们会在clock_config.c文件里的BOARD_BootClockRUN()函数最后添加如下语句以选择OSC作为PIT计时时钟,而EVK板载外部XTALOSC晶振是24MHz。
/* Configure PIT divider */
CLOCK_SetMux(kCLOCK_PerclkMux, 1U); /* Set PERCLK_CLK source to OSC_CLK*/
CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U); /* Set PERCLK_CLK divider to 1 */
有朋友可能会好奇,我们似乎没有使能和实现PIT中断,其实在当前coremark工程下没有必要,因为PIT中断每隔178s(0x100000000/24MHz)才会触发一次,而我们只需要执行几十秒就够了,所以即使使能和实现PIT中断也用不到,当然如果能实现PIT中断更好,万一我们让coremark程序执行超过178s,不实现PIT中断就会导致计时出错。
#define CLOCKS_PER_SEC (24000000)
void timer_pit_init(void)
{
/* Structure of initialize PIT */
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
/* Init pit module */
PIT_Init(PIT, &pitConfig);
/* Set max timer period for channel 0 */
PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, (uint32_t)~0);
/* Start channel 0 */
PIT_StartTimer(PIT, kPIT_Chnl_0);
}
CORETIMETYPE barebones_clock() {
// 删除#error提示
#error "You must implement a method to measure time in barebones_clock()! This function should return current time.\n"
// 添加PIT计数值返回语句
return (~PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_0));
}
void portable_init(core_portable *p, int *argc, char *argv[])
{
// 删除#error提示
//#error "Call board initialization routines in portable init (if needed), in particular initialize UART!\n"
// 添加板级初始化调用
/* Init board hardware. */
BOARD_InitHardware();
// 添加PIT计时器初始化调用
/* Init timer for microsecond function. */
timer_pit_init();
//...
}
2.2.3 串口打印功能
程序移植的第三步是实现串口打印功能,由于hello_world工程已经包含串口打印功能,所以这里的修改比较简单。
void uart_send_char(char c) {
// 删除#error提示
//#error "You must implement the method uart_send_char to use this file!\n";
// 添加UART发送函数调用
if (c == '\n')
{
char tmp = '\r';
LPUART_WriteBlocking((LPUART_Type *)BOARD_DEBUG_UART_BASEADDR, (const uint8_t *)&tmp, 1);
}
LPUART_WriteBlocking((LPUART_Type *)BOARD_DEBUG_UART_BASEADDR, (const uint8_t *)&c, 1);
//...
}
2.3 CoreMark参数配置
2.2里只是将基本CoreMark功能移植完成,但此时coremark工程还是无法编译,因为还有一些CoreMark配置没有确定,都在coremark_portme.h里,需要重定义下面三个宏,并且IAR的优化选项也要设置如下图所示:
#define ITERATIONS (40000)
#define COMPILER_VERSION "IAR EWARM v8.20.2"
#define COMPILER_FLAGS "High - Speed - No size constraints"
2.4 输出CoreMark结果
到这里CoreMark的移植工作就完全结束了,此时coremark工程也应该能正常编译了。为得到最高的CoreMark得分,最后需要再确定两件事:一、Core Clock是否确定配置为600MHz;二、工程代码段/数据段是否放在了ITCM/DTCM RAM。
打开clock_config.c文件,查看BOARD_BootClockRUN()函数,ARM Core/AHB时钟确实都为600MHz。
void BOARD_BootClockRUN(void)
{
/* Boot ROM did initialize the XTAL, here we only sets external XTAL OSC freq */
CLOCK_SetXtalFreq(24000000U);
CLOCK_SetRtcXtalFreq(32768U);
CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0x1); /* Set PERIPH_CLK2 MUX to OSC */
CLOCK_SetMux(kCLOCK_PeriphMux, 0x1); /* Set PERIPH_CLK MUX to PERIPH_CLK2 */
/* Setting the VDD_SOC to 1.5V. It is necessary to config AHB to 600Mhz */
DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x12);
CLOCK_InitArmPll(&armPllConfig); /* Configure ARM PLL to 1200M */
CLOCK_SetDiv(kCLOCK_ArmDiv, 0x1); /* Set ARM PODF to 1, divide by 2 */
CLOCK_SetDiv(kCLOCK_AhbDiv, 0x0); /* Set AHB PODF to 0, divide by 1 */
CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); /* Set IPG PODF to 3, divede by 4 */
// ...
}
再打开MIMXRT1052xxxxx_ram.icf文件,查看text段确实放在了ITCM里(0x0 - 0x7FFFF),data段确实放在了DTCM里(0x20000000 - 0x2007FFFF)。
define symbol m_interrupts_start = 0x00000000;
define symbol m_interrupts_end = 0x000003FF;
define symbol m_text_start = 0x00000400;
define symbol m_text_end = 0x0001FFFF;
define symbol m_data_start = 0x20000000;
define symbol m_data_end = 0x2001FFFF;
还等什么?将coremark工程赶紧下载进芯片并打开串口调试助手看CoreMark得分啊。痞子衡实测的CoreMark得分为2952,这与官方标称的3020有一点差距。
对于coremark得分没上3000,痞子衡感到不服啊,那怎么提高coremark得分?痞子衡试尽方法(改编译器选项、调coremark配置)均无功而返,后来无意中看到EEMBC上跑出3036得分的IDE(编译器)是IAR 7.80,于是死马当活马医吧,痞子衡也在IAR 7.80.4上运行了一次,得到了3017分,原来这微小差异取决于编译器版本,真相大白。
想偷懒的朋友直接移步痞子衡的github https://github.com/JayHeng/Cortex-M-Apps 去下载移植好的工程,工程在\Cortex-M-Apps\apps\coremark_imxrt1052\bsp\下面,build8202和build7804分别对应不同的IAR版本。
至此,恩智浦i.MX RT1xxx系列MCU的CoreMark性能与实测痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(2)- RT1052DVL6性能实测(CoreMark)的更多相关文章
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(5)- 划时代新品RT1170
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的划时代新品i.MXRT1170. 自2017年开始,每年的6月25日恩智浦都会在北京举行微控制 ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(1)- 概览
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的基本特性. ARM Cortex-M微控制器芯片厂商向来竞争激烈,具体可参看我的另一篇文章&l ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU特性那些事(1)- 概览
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的基本特性. 恩智浦半导体于2017年开始推出的i.MX RT系列重新定义了MCU,其第一款芯片i. ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的OTP. 在i.MXRTxxx启动系列第二篇文章 Boot配置(ISP Pin, OTP) 里痞子 ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(1)- Boot简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的BootROM功能简介. 截止目前为止i.MX RTxxx系列已公布的芯片仅有一款i.MXRT60 ...
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(2)- Boot配置(ISP_Pin, OTP)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的Boot配置. 在上一篇文章 Boot简介 里痞子衡为大家介绍了Boot基本原理以及i.MXRTx ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU硬件那些事(1)- 官方EVK简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的配套EVK板. 半导体设计厂商发布任何一块MCU芯片新品,一般都会同步推出基于这款MCU的配套 ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU启动那些事(1)- Boot简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的BootROM功能简介. 截止目前为止i.MX RTyyyy系列已公布的芯片有三款i.MXRT ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU启动那些事(2)- Boot配置(BOOT Pin/eFUSE)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的Boot配置. 在上一篇文章 Boot简介 里痞子衡为大家介绍了Boot基本原理以及i.MXR ...
随机推荐
- return之为什么能够终止函数,代码演练
''' return 有终止函数的作用,下面通过执行到return x 以后, 就结束了程序的下一步执行,所以就没有往下面走,所以终端上也就只能 看到打印结果100,看不到打印呢 ''' def se ...
- 中文分词接口api,采用结巴分词PHP版中文分词接口
中文分词,分词就是将连续的字序列按照一定的规范重新组合成词序列的过程.我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字.句和段能通过明显的分界符来简单划界,唯独词没有一个形式上 ...
- Android Studio 安装教程
前言 前段时间周围有很多认识的人学习Android,看蛮多人在装Android Studio,然而看他们装的过程不是那么顺利?然后也有高中同学来问我,于是乎就自己也试着去装了下,也方便日后学习Andr ...
- C#中使用Path、Directory、Split、Substring实现对文件路径和文件名的常用操作实例
场景 现在有一个文件路径 E:\\BTSData\\2019-11\\admin_20180918_1_1_2 需要获取最后的文件名admin_20180918_1_1_2 需要获取文件的上层目录20 ...
- View 的绘制过程
配合Activity 从启动到布局绘制的简单分析 阅读 基本概念介绍 Activity:一个 Activity 是一个应用程序组件,提供一个屏幕,用户可以用来交互. View:所有视图控件的基类 Vi ...
- Pikachu-Sql Inject
Pikachu-Sql Inject 在owasp发布的top10排行榜里,注入漏洞一直是危害排名第一的漏洞,其中注入漏洞里面首当其冲的就是数据库注入漏洞. 一个严重的SQL注入漏洞,可能会直接导致一 ...
- PCA主成分分析(最大投影方差)
PCA简介: 从n维数据中提取最能代表这组数据的m个向量,也就是对数据进行降维(n->m),提取特征. 目标: 找到一个向量\(\mu\),使n个点在其上的投影的方差最大(投影后的数据越不集中, ...
- AWVS12破解版使用
本篇简单介绍AWVS12破解版的安装使用,如果您已经安装了AWVS 10.5的版本,不用卸载,可以共存. AWVS12破解版下载链接:https://github.com/starnightcyber ...
- Spring Boot 处理异常返回json
spring boot 老版本处理异常 对于浏览器客户端,返回error数据 对于非浏览器返回json数据, 主要取决于你的请求head 是什么 但是当我们自定义了: 老版本无论请求什么都会返回j ...
- 一步一步搭建 Oracle Data Guard
前言 为什么要写前言,因为我要吐槽一下.作为一个Java后端,搭建Oracle Data Guard真的是一件,嗯,既不专业也不擅长的事情,然而,为什么还是要我来弄? 因为DBA出差了,我们这边急着要 ...