本文首介绍CoreMark是什么,然后使用CubeMX创建空的STM32H7S7L8HxH项目,并生成基于CMake的项目代码;接着一步步将CoreMark源码移植到项目中;最后一步步优化CoreMark跑分,将跑分从106.4最终优化到2410.2分,实现了近23倍的提升。本文实验过程中介绍了如何使用STM32 HAL库接口进行计时,以及如何将printf输出重定向到UART,并通过ST-Link调试器接收UART输出。另外,本文还介绍了如何解决使用gcc工具链时STM32上的printf无法输出浮点数问题,以及如何解决STM32上printf输出换行不对齐问题。因此,无论你对STM32H7S上的CoreMark跑分感兴趣,还是对STM32上的printf重定向方法及常见问题感兴趣,本文都值得一看。 一、CoreMark简介什么是CoreMark? 来自CoreMark首页的解释是:
翻译一下就是:
简单来说,就是一个测试CPU性能的程序,类似PC上的Cinebench、CPU-Z之类的CPU性能测试工具。 了解了CoreMark是什么之后,接下来我们尝试在STM32H7S78-DK开发板上跑一下CoreMark,看看分数是多少。 接下来就可以开始进行CoreMark移植了,为了让移植步骤清晰明确,这里我把移植分为两大部分:
二、创建CubeMX项目2.1 选择MCU首先,启动CubeMX,Commercial Part Number 收入H7S7,回车搜索: 选中Board一行有STM32H7S78-DK的,然后点击右上角的Sart Project,开始创建项目。 2.2 配置CPU时钟然后,STM32CubeMX进入配置界面,切换到Clock Configuration标签页,将To CPU Clocks修改为600并回车,CubeMX软件将会自动计算其他参数: 按Ctrol+S保存,选择适当的位置保存ioc文件。 2.3 配置串口功能开发板上自带了ST-Link V3调试器,该调试器带有虚拟串口功能。通过查阅原理图,我们知道主控MCU和ST-Link之间的连接关系如下图: 可以看到,ST-Link的虚拟串口和主控芯片的连接关系为:
接下来,需要修改这两个引脚的功能。 修改PD0为UART4_RX功能: 修改PD1为UART4_TX功能: 启用UART4功能,设置为异步,并分配到Boot子项目: 2.4 配置LED引脚为了方便观察CoreMark执行完成了,我们把红色LED的控制引脚也配置一下。查阅原理图,找到USER LED对应部分: 可以看到,红色LED对应的是PM2引脚。 修改PM2引脚为GPIO_Output功能: 将其分配到Boot子项目,并为其设置用户标签(User Label): 2.5 生成CMake项目接下来,CubeMX软件切换到Project Manager标签页,Project Structure勾选 Boot Project,Toolchain/IDE下拉到 CMake: Code Generator部分,勾选Generate peripheral initialization as a pair of '.c/.h' files per peripherals: 最后,点击右上角的Generate Code,生成代码: VSCode导入项目等等操作,本文不再赘述,具体可参考我上一篇帖子: 【STM32H7S78-DK评测】搭建基于ST官方VSCode扩展的STM32开发环境 - STM32团队 ST意法半导体中文论坛 (stmicroelectronics.cn) 三、基础功能支持基础功能支持主要包括两个功能:
下面分别介绍如何实现这两个功能。 3.1 支持记录耗时STM32上,使用HAL库记录耗时非常简单,只需要用:
因此,记录使用HAL_GetTick记录耗时,代码类似:
3.2 支持printf输出到串口CubeMX选择CMake项目后,默认已经生成了 syscalls.c文件,已经实现了支持gcc工具链的printf输出的一半功能。另外一半功能需要手动添加到
完成以上修改之后,就可以适用printf打印了,可以修改main.c,找到其中的循环进行测试:
如无意外,编译、下载、运行可以通过ST-Link的虚拟串口看到如下输出: 3.3 支持printf输出浮点数默认生成的CMake项目不支持浮点数打印,需要修改链接选项,修改文件 在末尾添加如下代码片段:
之后,再次编译,就可以输出浮点数了。 类似的,为了验证可以正常输出浮点数,修改main.c中的循环:
如无意外,编译、下载、运行,可以在串口看到如下输出: 四、移植CoreMark源码4.1 添加CoreMark源码CoreMark代码仓:https://github.com/eembc/coremark.git 将代码下载下来之后,将其中的如下文件到项目的 拷贝后,Boot项目文件结构如下: 4.2 修改 core_portme.c 文件core_portme.c文件中,需要修改的是计时的几个宏定义,具体如下:
4.3 修改 core_portme.h 文件core_portme.h文件,开头部分需要新增如下代码:
4.4 修改 core_main.c 文件coremark源码的core_main.c中定义了main函数,CubeMX生成的main.c中也有main函数,直接编译会产生冲突,因此需要修改core_main.c文件,重命名其中的main函数,并在main.c中调用它。 在core_main.c中,找到main函数,并将其修改为core_main: 4.5 修改 main.c 文件接下来,修改 main.c 文件,开头出添加: 找到while循环,并将其修改为:
4.6 修改 CMakeLists.txt 文件完成以上修改后,还差最后一步,就是让新增的coremark的几个源码文件参与到编译、链接过程中。因此,需要修改 找到其中的target_sources代码片段,将其修改为:
4.7 编译、下载、运行完成上述所有修改后,编译构建,可以看到如下输出: 下载、运行,可以看到串口输出如下: 跑分结果为 106.425 分,这个分数太低了。另外,输出结果中的换行没有从头对齐,但这个问题不大,可以最后再处理,具体处理方法见本文的5.4节。 五、优化CoreMark跑分前面CoreMark跑分较低,接下来尝试通过不同方法提升跑分。 5.1 修改CMake构建类型仔细观察4.7节的构建输出,可以看到Build type为Debug。接下来,将其修改为Release,尝试再次运行CoreMark。 修改 再次编译,可看到FLASH占用少了很多: 下载、运行,可以看到串口输出如下: 这次的分数为230.81,但出现了报错,提示执行时间不足10秒。 修改前面提到的 core_portme.h 中的 ITERATIONS ,将其修改为 3200, 再次编译、下载、运行,串口输出如下: 跑分还是230.81,执行时间变成了13秒多了。 5.2 修改编译优化选项CMAKE_BUILD_TYPE修改为Release后,实际的编译优化选项是 接下来,修改
顺便修改 再次编译,可以看到FLASH占用如下: 再次下载、运行,可以看到串口输出如下: 这次分数来到了447.43,可喜可贺! 然而,按照过往经验,600MHz Cortex-M7 CPU的CoreMark跑分不应该只有400多! 5.3 打开ICache和DCache接下来,修改main.c,在main函数的开头添加如下代码:
再次编译下载运行,可以看到串口输出如下: 执行时间变成了2秒多,有报错。 重新修改 ITERATIONS 为 32000,再次编译下载运行,可以看到串口输出如下: 分数跑到了2410.18,好了,这次的分数差不多可以了。 5.4 解决换行不对齐问题由于CoreMark结果输出使用的换行仅为 为了让没有 修改前为:
修改后为:
完成上述修改后,再次编译下载运行,可以看到串口输出如下: 好了,这下看起舒服多了。 最终成绩:2410.183023 分,和CoreMark官网上查到的STM32H72x/73x系列使用IAR编译器的成绩差不多了: 毕竟IAR是收费的,使用免费的GCC编译,能够跑到这个分数,已经可以了。 5.5 项目最终版源代码整个项目代码,已分享至GitHub: https://github.com/xusiwei/STM32H7S78-DK-CoreMark.git 六、参考链接
|
【STM32H7S78-DK】汽车仪表系统
【STM32H7S78-DK】基于 rtthread 适配 lcd 驱动移植 lvgl
【STM32H7S78-DK评测】TouchGFX (QR Code)二维码生成器
【STM32H7S78-DK】rtthread 增加 psram 内存管理
【STM32H7S78-DK】开箱与rtthread工程初体验
【STM32H7S78-DK评测】-5 LVGL&DMA2D DEMO测试
【STM32H7S78-DK评测】-4 LTDC&DMA2D 基本测试
实战经验 | 从CubeMX下载生成STM32元件封装库
【STM32H7S78-DK评测】移植AI框架TensorFlow【DSP指令加速篇】
【STEVAL-STWINKT1B测评】1、点亮LED
很好的分享,常见问题闭坑了