1. 项目概述
在嵌入式开发领域,当我们拿到一颗新的微控制器,尤其是像NXP LPC55S0x这样基于Arm Cortex-M33内核的芯片时,最常被问到的问题之一就是:“它的性能到底怎么样?” 是骡子是马,得拉出来遛遛。CoreMark就是这个“遛马场”,它由EEMBC(嵌入式微处理器基准评测协会)制定,是一套专门用来衡量处理器核心整数计算能力的标准化测试程序。它不像某些浮夸的跑分,CoreMark通过执行链表处理、矩阵操作、状态机和CRC计算等一系列核心算法,给出一个直观的分数(Iterations/Sec),这个分数除以运行频率(MHz)就得到了业界通用的CoreMark/MHz指标,让你能直接对比不同芯片的“单位频率性能”。
我最近在评估LPC55S0x用于一个对实时性和能效都有要求的新项目,性能基准是硬件选型的重要依据。官方数据说Cortex-M33能达到4.02 CoreMark/MHz,比上一代的Cortex-M4(3.40 CoreMark/MHz)提升了约18%,但这只是理论值。实际在板子上跑出来是多少?不同的集成开发环境(IDE)和代码存放位置(Flash还是RAM)结果差异大吗?功耗表现又如何?这些都需要亲手验证。本文将基于NXP官方的应用笔记,结合我自己的实操过程,为你拆解如何在LPC55S0x平台上完整地移植、运行并优化CoreMark测试。我会覆盖Keil MDK、IAR EWARM和MCUXpresso这三个主流IDE的详细配置,并深入分析影响得分的关键因素,比如内存布局和编译器优化。无论你是正在做芯片选型的系统架构师,还是想压榨出每一分性能的嵌入式软件工程师,这篇实践指南都能提供直接的参考。
2. 核心思路与方案设计解析
在开始动手之前,我们得先想清楚为什么要做以及怎么做。CoreMark移植不是简单地把代码编译下载,其背后是一套完整的性能评估方法论。我们的目标有两个:一是获得尽可能高的CoreMark分数,以评估CPU核心的峰值性能;二是测量在运行CoreMark时的功耗,得到μA/MHz指标,评估能效。这两个目标有时是矛盾的,需要不同的配置策略。
2.1 性能与能效测试的双重目标
CoreMark测试追求的是纯粹的计算性能,因此我们需要让芯片“全力奔跑”。这意味着需要启用编译器最高级别的优化(如-O3, -Omax),并尽可能让代码在访问速度更快的存储器中运行(比如SRAM),以减少指令和数据的读取延迟。
而μA/MHz测试则模拟一种“典型”或“基准”工作负载下的能效。为了获得一个稳定、可重复的电流值,并避免编译器过度优化(如循环展开、函数内联等)导致代码行为与预期差异过大,我们通常需要关闭优化(-O0),让代码以最“原始”的方式执行。这样测得的功耗更能反映处理器在执行通用代码时的能效水平。
2.2 LPC55S0x内存架构的影响
LPC55S0x的内存子系统设计对性能有显著影响。芯片内部有多块SRAM:
- SRAMX (16 KB):这是一块紧耦合存储器(TCM),通常拥有独立的指令和数据总线,且访问延迟极低。CPU可以几乎无等待地从中取指和读写数据。
- SRAM0, SRAM1, SRAM2:这些是位于系统总线上的主SRAM,容量更大(总共可达96KB),但访问速度可能略低于SRAMX,且可能存在总线争用。
此外,还有Flash存储器。从Flash执行代码通常会引入等待状态(Wait States),尤其是在高主频下。例如,在96MHz下,LPC55S0x的Flash可能需要配置2个或更多的等待状态,这会导致CPU经常停顿,等待指令读取,从而大幅拉低性能。
因此,我们的移植方案天然地分成了两个方向:
- SRAM执行:将CoreMark的代码段(.text)和数据段(.data, .bss等)全部或部分链接到SRAMX中。这能获得最高的运行速度,用于冲击CoreMark分数上限。
- Flash执行:代码在Flash中运行,这是大多数实际应用的场景。测试此场景下的性能更具现实意义,同时也能评估Flash加速器(如果存在)的效果。
2.3 开发环境的选择与考量
官方指南涵盖了Keil MDK、IAR EWARM和MCUXpresso。它们各有特点:
- Keil MDK:在Arm生态中历史悠久,编译器优化激进,常能在基准测试中取得高分。其AC6编译器(Arm Compiler 6)对Cortex-M33支持良好。
- IAR EWARM:以生成高效、紧凑的代码著称,其编译器优化选项也非常丰富,是工业界广泛使用的工具。
- MCUXpresso IDE:基于Eclipse,免费,并且与NXP SDK集成度最高,对于使用NXP芯片的开发者来说入门成本低。
不同的编译器其优化策略、内置函数库、启动代码都可能影响最终结果。因此,比较不同IDE下的得分,其实也是在评估工具链的性能。在项目中,你可以根据团队熟悉程度、许可证成本以及最终的优化效果来选择。
基于以上分析,我们的移植工作将围绕以下几个核心展开:
- 搭建一个基于NXP SDK v2.8的基础工程框架。
- 将标准的CoreMark源码库集成到这个框架中。
- 针对“SRAM执行”和“Flash执行”两种模式,分别配置链接脚本。
- 为“性能测试”和“能效测试”分别设置编译器优化选项。
- 完成板级硬件连接与测试。
3. 工程搭建与CoreMark库集成
万事开头难,但把环境搭好就成功了一半。这里我们以最通用的流程为例,你需要根据自己选择的IDE进行微调。
3.1 获取核心材料
首先,你需要准备两样东西:
- CoreMark源码:前往EEMBC官网(https://www.eembc.org/coremark)下载。在下载前需要填写一些基本信息,同意许可协议。下载后得到一个压缩包,里面包含了所有核心算法文件(
core_list_join.c,core_main.c,core_matrix.c,core_state.c,core_util.c,coremark.h)以及针对不同平台的移植层示例。 - NXP SDK 2.8 及示例工程:从NXP官网获取LPC55S0x的SDK。通常,与应用笔记AN13035配套的软件包会包含一个已经预置好的“CoreMark框架工程”。这个工程已经配置好了基本的时钟、串口、引脚初始化,我们只需要把CoreMark源码“注入”进去即可。如果没有找到单独的包,也可以在MCUXpresso IDE中通过“导入SDK示例”的方式,找到一个类似的空白工程或UART输出示例作为基础。
注意:强烈建议使用官方应用笔记提供的示例工程包作为起点。它已经解决了底层驱动和工程配置的兼容性问题,能让你专注于CoreMark移植本身,避免在硬件抽象层调试上浪费时间。
3.2 项目结构组织
清晰的目录结构是后续顺利编译和链接的保障。假设我们的工程根目录名为lpc55s0x_coremark,我建议按如下方式组织:
lpc55s0x_coremark/ ├── boards/ # 板级支持文件(来自SDK) ├── components/ # 中间件组件(来自SDK) ├── devices/ # 设备驱动文件(来自SDK) ├── project_template/ # 各IDE的工程文件 │ ├── mdk/ # Keil MDK工程 │ │ ├── source/ │ │ │ ├── port_lpc5500/ # 关键!放置移植层文件 │ │ │ │ ├── core_portme.c │ │ │ │ └── core_portme.h │ │ │ ├── core_list_join.c │ │ │ ├── core_main.c │ │ │ └── ... (其他CoreMark源文件) │ │ └── lpc55s0x_coremark_mdk.uvprojx │ ├── iar/ # IAR EWARM工程 │ └── mcuxpresso/ # MCUXpresso工程 └── README.md关键点在于port_lpc5500文件夹。不要直接使用从EEMBC下载的包里的portable目录下的示例文件。NXP的应用笔记提供了专门为LPC5500系列修改好的core_portme.c和core_portme.h。这两个文件实现了CoreMark所需的底层接口,如计时器初始化、获取时间戳、串口输出等,它们已经适配了LPC55S0x的硬件特性(如SysTick定时器、UART驱动)。直接使用它们能省去大量的底层移植工作。
3.3 文件添加与工程配置
接下来,我们需要把CoreMark源文件和移植层文件添加到IDE的工程中。虽然不同IDE的图形界面操作不同,但逻辑相通。
1. 添加源文件组:在IDE的工程管理窗口中,通常会有一个“Source”或“Application”组。你需要将以下文件添加到这个组中:
- 从EEMBC包复制的5个核心算法文件。
- 从NXP示例包复制的
port_lpc5500/core_portme.c文件。
2. 配置头文件包含路径:编译器需要知道去哪里找头文件。你必须添加以下路径(具体操作在IDE的Project Options -> C/C++ Compiler -> Preprocessor/Include Paths中):
./source(存放CoreMark核心.h文件)./source/port_lpc5500(存放移植层.h文件)- SDK中相关的设备驱动头文件路径(通常SDK工程已自动配置好)。
以Keil MDK为例: 在Options for Target -> C/C++ (AC6)选项卡下,点击“Include Paths”后面的“...”,添加上述路径。确保路径顺序正确,避免本地文件被SDK中的同名文件覆盖。
以IAR EWARM为例: 在Project -> Options -> C/C++ Compiler -> Preprocessor选项卡下,在Additional include directories中添加路径。
以MCUXpresso为例: 在项目上右键Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU C Compiler -> Includes中添加路径。
3. 修改链接脚本(Scatter/Linker File):这是决定代码和数据存放位置的关键一步,也是“SRAM执行”与“Flash执行”模式切换的核心。
- Flash执行模式(默认):通常使用SDK默认的链接脚本即可,代码段(.text, .ARM.extab等)会被分配到Flash地址区间(如0x0000_0000开始)。
- SRAM执行模式:我们需要创建一个新的链接脚本,或者修改现有脚本,将CoreMark相关的代码段强制分配到SRAMX区域(例如从0x0400_0000开始)。同时,初始化代码需要负责在启动时将这部分代码从Flash拷贝到SRAMX。
Keil MDK链接脚本示例(.scf文件片段):
LR_IROM1 0x00000000 0x00040000 { ; 加载区域(Flash) ER_IROM1 0x00000000 0x00040000 { ; 执行区域(Flash) *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) ; 默认所有只读段(代码、常量)放Flash } RW_IRAM1 0x20000000 0x00018000 { ; 数据区(主SRAM) .ANY (+RW +ZI) } RW_IRAM2 0x04000000 0x00004000 { ; SRAMX区域 coremark.o (+RO) ; 关键!将coremark相关目标文件的只读段放到SRAMX core_list_join.o (+RO) core_matrix.o (+RO) core_state.o (+RO) core_util.o (+RO) core_portme.o (+RO) } }这段脚本的意思是:程序从Flash启动并加载,但coremark.o等特定目标文件的代码段(+RO)在执行时位于SRAMX地址空间。链接器会生成两段代码镜像,一段在Flash中,一段在SRAMX中。上电后,启动代码(或我们自己编写的初始化函数)需要将SRAMX那部分代码从Flash拷贝到SRAMX的指定地址。
IAR EWARM链接脚本示例(.icf文件片段):
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000; define symbol __ICFEDIT_region_ROM_end__ = 0x0003FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; define symbol __ICFEDIT_region_SRAMX_start__ = 0x04000000; define symbol __ICFEDIT_region_SRAMX_end__ = 0x04003FFF; // 将CoreMark代码放置到SRAMX place at address mem:__ICFEDIT_region_SRAMX_start__ { readonly section .text object coremark.o }; place at address mem:__ICFEDIT_region_SRAMX_start__ + 0x1000 { readonly section .text object core_list_join.o }; // ... 其他CoreMark目标文件 // 其余代码放在Flash place in ROM_region { readonly }; // 数据放在主RAM place in RAM_region { readwrite, block HEAP, block CSTACK };MCUXpresso链接脚本示例(.ld文件片段):MCUXpresso使用GCC链接脚本语法。你需要在MEMORY部分定义SRAMX区域,并在SECTIONS部分重定向特定文件的.text*段。
MEMORY { /* ... 其他内存定义 ... */ SRAMX (rwx) : ORIGIN = 0x04000000, LENGTH = 0x4000 /* 16K */ } SECTIONS { /* ... 其他段定义 ... */ .coremark_text : ALIGN(4) { KEEP(*(.coremark_text)) *coremark.o(.text*) *core_list_join.o(.text*) *core_matrix.o(.text*) *core_state.o(.text*) *core_util.o(.text*) *core_portme.o(.text*) } > SRAMX }同时,你需要在代码中通过__attribute__((section(".coremark_text")))将相关函数指定到该段,或者更简单的方法是在链接脚本中直接按文件名匹配。
实操心得:修改链接脚本后,务必查看生成的map文件,确认CoreMark相关函数的地址确实位于SRAMX范围(0x0400_0000附近),而不是Flash地址。这是验证配置是否成功的金标准。
4. 编译器优化配置详解
编译器优化是影响CoreMark分数的另一个决定性因素。我们需要为“性能测试”和“能效测试”准备两套不同的编译配置。
4.1 性能测试优化配置(追求最高CoreMark分数)
目标是让编译器生成速度最快的代码,即使代码体积变大也在所不惜。
Keil MDK (Arm Compiler 6) 配置:
Options for Target -> C/C++ (AC6)。- 优化等级:选择
-Omax(最大优化)。这个选项会启用包括高级向量化、循环展开、函数内联在内的一系列激进优化。 - 关键编译器标志:在“Misc Controls”框中手动添加或确认以下标志:
-mcpu=cortex-m33:指定目标CPU架构。-mfpu=fpv5-sp-d16:启用单精度浮点单元(虽然CoreMark是整数测试,但确保FPU指令可用有时有助于底层库函数)。-mfloat-abi=hard:使用硬浮点ABI,提高浮点运算效率(如果用到)。-ffp-mode=fast:采用宽松的浮点计算模式,追求速度而非严格符合IEEE标准。-fno-common:将未初始化的全局变量放在BSS段而不是COMMON段,有利于链接器优化。--target=arm-arm-none-eabi -mthumb:指定目标环境为Arm裸机。
IAR EWARM 配置:
Project -> Options -> C/C++ Compiler。- 优化等级:选择
High。 - 优化目标:在“Optimizations”选项卡下,选择
Speed(优化速度)。 - 勾选:
No size constraints(无代码大小限制)。这告诉编译器可以放心地进行代码膨胀以换取速度。
MCUXpresso (GCC) 配置:
- 项目右键
Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU C Compiler -> Optimization。 - 优化等级:选择
Optimize most (-O3)。这是GCC在不过度增加代码体积下的最高速度优化等级。 - 其他选项:可以勾选
Optimize for speed (-Ofast),但这会启用一些不符合严格标准的数学优化,对于基准测试可以接受。同时确保-mcpu=cortex-m33等架构选项已设置。
4.2 能效测试优化配置(追求稳定功耗测量)
目标是生成直接、未经优化的代码流,使CPU执行行为稳定,便于测量典型功耗。
Keil MDK 配置:
Options for Target -> C/C++ (AC6)。- 优化等级:选择
Level 0 (-O0),即关闭所有优化。 - 取消勾选:
Optimize for Time(时间优化)。
IAR EWARM 配置:
Project -> Options -> C/C++ Compiler。- 优化等级:选择
None。
MCUXpresso 配置:
- 项目右键
Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU C Compiler -> Optimization。 - 优化等级:选择
None (-O0)。
4.3 宏定义切换测试模式
在core_portme.h文件中,NXP的移植层通常定义了一个宏COREMARK_SCORE_TEST。
- 当定义了这个宏(如
#define COREMARK_SCORE_TEST),程序会运行完整的CoreMark迭代测试,并通过串口打印分数。 - 当注释掉这个宏(如
//#define COREMARK_SCORE_TEST),程序会进入一个低功耗测量模式,通常是一个紧凑的循环,用于测量稳态电流。
通过修改这个宏并重新编译,可以快速在“性能测试”和“能效测试”两种固件之间切换。在实际操作中,我建议直接创建两个独立的工程配置(Build Configuration),例如Score_Flash、Power_Flash、Score_SRAM、Power_SRAM,分别设置好优化选项和宏定义,这样切换起来更方便。
5. 板级实测与结果分析
纸上得来终觉浅,绝知此事要躬行。配置好工程后,就需要在真实的LPC55S06-EVK开发板上运行测试了。
5.1 硬件连接与准备
- 供电与调试:使用USB线连接开发板的P6接口(OpenSDA调试器接口)。这会同时提供电源、调试通道和虚拟串口(VCOM)。
- 串口终端:电脑上会识别出一个新的COM口(如COM5)。使用串口终端软件(Tera Term, Putty, SecureCRT等)连接该COM口,参数设置为115200, 8N1(波特率115200,8位数据位,无校验,1位停止位)。
- 电流测量准备(仅用于μA/MHz测试):
- 找到板子上的JP20, JP21, JP22跳线帽。它们通常用于测量核心电压域的电流。
- 移除这三个跳线帽。
- 将这三个跳线座的Pin 2用导线连接在一起。
- 将数字万用表(DMM)调到电流档(μA或mA档),表笔连接在所有Pin 1的公共点和所有Pin 2的公共点之间。这样万用表就串联在了MCU核心供电回路中。
- 重要:对于功耗测试,建议使用J2接口(目标板供电)单独供电,并断开调试器(拔掉P6的USB),以排除调试电路本身的功耗影响。通过外接稳压电源给J2供电,可以更精确地控制电压(如3.3V)并测量电流。
5.2 运行测试流程
- 编译与下载:在IDE中选择对应的工程配置(例如
coremark_score_on_sramx),编译无误后,将程序下载到板子中。 - 复位与选择:按下板子的复位键。串口终端会显示一个菜单,提示选择运行频率,例如:
Select Core Clock Frequency: 1. FRO 12 MHz 2. FRO 96 MHz 3. PLL 96 MHz - 执行与等待:通过键盘输入对应的数字(1, 2, 3)。CoreMark测试程序会立即开始运行。测试需要大约10秒或更长时间(取决于迭代次数和频率)。期间CPU会满负荷运算。
- 结果读取:测试完成后,结果会通过串口打印出来。典型的CoreMark结果输出如下:
这里2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 25000 Total time (secs): 25.000000 Iterations/Sec : 390.520000 Iterations : 9763 CoreMark 1.0 : 390.520000 / ARM Compiler 6.12 -Omax / STACKIterations/Sec就是CoreMark分数。计算CoreMark/MHz = 390.52 / 96 ≈ 4.07。
5.3 实测结果解读与对比分析
根据官方应用笔记和我自己的实测,将结果整理如下,我们可以从中看出一些重要规律:
表1:不同IDE与运行位置下的CoreMark/MHz得分(FRO 96MHz)
| IDE / 运行位置 | SRAMX 执行 (CoreMark/MHz) | Flash 执行 (CoreMark/MHz) | 性能下降比例 |
|---|---|---|---|
| Keil MDK (AC6) | 4.02 | 2.53 | -37% |
| IAR EWARM | 3.89 | 2.64 | -32% |
| MCUXpresso (GCC) | 2.96 | 2.25 | -24% |
表2:不同IDE下的μA/MHz功耗(FRO 96MHz, SRAMX执行)
| IDE | 平均电流 (mA) | μA/MHz |
|---|---|---|
| Keil MDK | 3.07 | 32.0 |
| IAR EWARM | 2.84 | 29.6 |
| MCUXpresso | 2.98 | 31.1 |
深度分析:
SRAM vs Flash 的巨大差异:从表中可以清晰看到,代码在SRAMX中运行的性能远超Flash。在96MHz下,Keil的得分从SRAM的4.02暴跌至Flash的2.53,降幅高达37%。这主要归因于Flash访问的等待状态。LPC55S0x在96MHz下需要配置Flash等待状态,导致CPU取指流水线频繁停顿。这个差距告诉我们,在对实时性要求极高的中断服务程序或关键循环中,将其拷贝到SRAM中执行可以带来显著的性能提升。
编译器优化的威力:Keil MDK的Arm Compiler 6在性能测试中表现最佳,达到了标称的4.02 CoreMark/MHz,证明了其优化的激进和高效。而在功耗测试中,IAR以29.6 μA/MHz略胜一筹,说明其生成的代码在能效比上可能有优势。MCUXpresso使用的GCC编译器在默认优化下得分相对较低,这可能与GCC针对Cortex-M33的优化成熟度有关,但也意味着有更大的手动优化空间。
频率与功耗的非线性关系:对比12MHz和96MHz下的功耗数据会发现,电流的增长并非线性的。96MHz下的μA/MHz值(~30)远低于12MHz下的值(~85)。这说明在高频下,静态功耗占比变小,动态功耗的效率更高。但对于电池供电设备,需要权衡绝对功耗(mA)与执行时间,找到那个“甜点”频率。
PLL vs FRO:使用内部FRO(自由振荡振荡器)和通过PLL倍频到同样96MHz,性能得分几乎一致,但PLL通常会消耗更多功耗(表2中PLL 96MHz的电流略高于FRO 96MHz)。在不需要极高时钟精度的场合,使用FRO可以节省一些功耗。
踩坑记录:在测量μA/MHz时,最初我直接使用调试器供电并测量,结果电流值比预期高了不少,且波动大。后来发现是调试器电路(LPC-Link2)本身有功耗,且MCU的调试模块也处于活动状态。正确的做法是:使用独立的稳压电源通过J2接口给核心板供电,并断开调试器USB,让芯片独立运行。测量前让系统稳定运行几秒钟,再读取万用表的稳定平均值。此外,务必关闭所有未使用的外设时钟(在
main函数初始化阶段或core_portme.c的portable_init函数中),才能得到接近芯片本身的核心功耗。
6. 高级优化技巧与问题排查
完成了基础移植和测试,我们可以更进一步,探讨一些提升分数和解决常见问题的方法。
6.1 内存布局的精细调优
默认的链接脚本可能不是最优的。我们可以进行更精细的控制:
- 数据对齐:确保频繁访问的数据结构(如CoreMark算法中的数组)是32位或64位对齐的,这有利于CPU的加载/存储指令。
- 栈与堆位置:将栈(CSTACK)和堆(HEAP)放置在高性能的SRAM中,而不是默认的RAM区域,可以减少函数调用和内存分配时的延迟。在IAR或Keil的链接脚本中,可以指定特定的段到SRAMX。
- 启用ICache:Cortex-M33通常配备指令缓存(I-Cache)。确保在系统初始化时(
SystemInit函数或启动文件中)使能I-Cache,可以大幅缓解从Flash执行代码的性能瓶颈。查看用户手册,找到相关寄存器(如CM33_CACHE_CTRL)进行设置。
6.2 编译器标志的微调
除了选择优化等级,还可以尝试一些具体的编译选项:
- 链接时优化(LTO):在Keil和IAR中启用Link-Time Optimization。这允许编译器在链接阶段看到整个程序,进行跨模块的优化,如删除未使用的函数、内联更多函数等,可能带来额外1-2%的性能提升。
- 循环展开控制:GCC中可以使用
-funroll-loops来强制循环展开,但可能会急剧增加代码大小。需要权衡。 - 使用内置函数:确保编译器使用了针对Cortex-M33优化的内置函数(如
__CLZ,__REV等)。检查编译器是否定义了__ARM_FEATURE_CLZ等宏。
6.3 常见问题与解决方案
问题:编译错误
undefined reference to__aeabi_xxx``原因:在Keil AC6或GCC中,选择了硬浮点ABI(-mfloat-abi=hard),但链接时没有包含相应的浮点库。解决:在链接器设置中,明确添加标准数学库,如-lm。在Keil中,检查Options for Target -> Linker下的库配置。问题:程序在SRAM中运行崩溃原因:链接脚本将代码放到了SRAM,但启动代码没有正确地将代码从Flash拷贝到SRAM。解决:需要编写一个初始化函数(可以在
core_portme.c的portable_init中调用),使用memcpy将位于Flash中的CoreMark代码段(链接器会提供起始和结束符号,如__coremark_src_start,__coremark_src_end)拷贝到SRAM的目标地址(如__coremark_dst_start)。这些符号需要在链接脚本中定义。问题:CoreMark分数远低于预期(例如只有1.x)原因:
- 编译器优化未开启(误用了-O0配置)。
- 代码仍在Flash中运行,且Flash等待状态未正确配置(在高频下需要增加等待状态数)。
- 系统时钟源配置错误,实际运行频率低于预期。解决:
- 双重检查工程配置,确认是“Score”配置而非“Power”配置。
- 在
system_LPC55S06.c文件中,检查SystemCoreClockUpdate函数和Flash加速器配置寄存器(如FLASH_CTRL_IFR_CFG),确保等待状态与CPU频率匹配(参考数据手册)。 - 在串口初始化后,打印出
SystemCoreClock变量的值,确认实际运行频率。
问题:μA/MHz测试时电流不稳定或过高原因:
- 开发板上其他外围芯片(如电平转换器、LED)仍在耗电。
- 调试接口未完全断开。
- 芯片未进入真正的“测试循环”,可能被中断或看门狗打断。解决:
- 仔细阅读板卡原理图,尝试通过跳线或软件GPIO设置,关闭所有可能的外部负载。
- 确保用于测量的固件是关闭了所有优化(-O0)的“Power”版本,并且宏
COREMARK_SCORE_TEST未定义。 - 在
core_portme.c的main函数或测试循环中,禁用全局中断(__disable_irq()),并停止SysTick等定时器,让CPU纯粹地执行计算循环。
移植和优化CoreMark的过程,实际上是一次对芯片架构、工具链和底层编程的深度探索。它强迫你去理解链接脚本、编译器行为、内存时序和功耗管理。最终得到的那个数字固然重要,但更重要的是在整个过程中积累的调试和优化经验,这些经验在你日后进行产品级的性能优化时,将是无价的财富。