引言
在进行嵌入式MCU的软件开发时,如何才能达到CPU内核的最高性能,仅仅是简单的配置内部时钟倍频模块——比如PLL/FLL产生CPU内核和内部总线允许运行的最高频率——就可以了吗?
答案是否!定!的!
真实情况是:除了工作频率之外,还有很多其他的很多因素,比如CPU的指令和数据Cache、Flash工作频率、应用程序的编译优化、数据指令存储地址的优化,以及硬件FPU指令的使用等众多的因素都将影响嵌入式MCU CPU内核最高性能的发挥。
下面,我就业界广泛使用的NXP S32K1xx系列汽车级通用MCU为例,给大家详细介绍一下其CPU内核性能优化,希望能够抛砖引玉,对大家有所启发和帮助。
S32K1xx系列MCU采用ARM的Cortex M0+ (S32K11x) 和Cortex M4F (S32K14x) 系列CPU内核,主频可达到最高48MHz和112MHz (HSRUN模式):↓↓↓
为了帮助大家理解本文内容,这里有必要先简要介绍一下S32K1xx系列MCU的系统级架构互联框图和具体S32K11x与S32K14x两个子系列的功能差异。
S32K14x系列MCU的内核、存储、时钟和外设模块及系统功能模块 (SWD/JTAG调试接口) 系统级架构互联框图如下:↓↓↓
S32K11x系列MCU的内核、存储、时钟和外设模块及系统功能模块 (SWD调试接口) 系统级架构互联框图如下:↓↓↓
S32K11x和S32K14x系列MCU的功能特性比较如下表:↓↓↓
1.CPU内核的指令和数据Cache是否使能 (S32K14x系列only)
从以上介绍可知,S32K14x系列MCU使用ARM Cortex M4F (简称CM4F) 内核的Code Bus上有4KB指令和数据缓存-Cache,可以帮助提供CPU内核工作时对P-Flash和SRAM_L区域的指令和数据访问效率。
4KB指令和数据缓存-Cache使能后可以将CM4F内核最近一段时间内访问指令和数据缓存在Cache中,每次M4F内核取指和取数据中会优先查询Cache内容,若其中已经存在,则Cache Hit (命中),直接为M4F内核使用,而无需重新访问P-Flash和SRAM_L存储区域,从而减少了内核执行代码的等待周期,通过了CPU内核的工作性能。
Tips
默认S32K14x系列MCU的M4F内核指令和数据Cache时是关闭的,需要在MCU启动 (startup) 过程中,通过以下代码配置LMEM->PCCCR寄存器使能:↓↓↓
/* Flush and enable I cache and write buffer */ LMEM->PCCCR = LMEM_PCCCR_ENCACHE_MASK | LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_GO_MASK;
LMEM->PCCCR寄存器定义如下:↓↓↓
2.Flash的工作频率是否配置到允许运行的最高频率
属于嵌入式MCU的S32K1xx系列MCU的代码是存储在Flash上本地执行的,而非像x86 CPU和MPU那样是拷贝到SRAM中执行的,所以Flash的工作频率决定了其取指和数据 (代码中的常数和字符串) 的快慢。
S32K1xx 系列MCU在不同的工作模式 (HSRUN (S32K14x only)、RUN和VLPR) 下运行的Flash工作最高频率如下:↓↓↓
Tips
默认S32K1xx SDK的Clock_Manager组件中,Flash的工作频率 (SLOW_CLK) 的配置并非其运行的最高运行频率,需要确认和调整。↓↓↓
Flash指令和数据预取功能是否使能
Tips
默认S32K1xx SDK的Clock_Manager组件中,Flash的工作频率 (SLOW_CLK) 的配置并非其运行的最高运行频率,需要确认和调整。↓↓↓
3.Flash指令和数据预取功能是否使能 S32K1xx系列MCU的Flash模块读buffer的推测 (speculation) 和预取 (prefetch) 功能与CPU的Cache功能类似,只是前者可以优化的地址范围较小32B (128-bit/16B buffer size), 而后者的可以优化4KB的地址范围内的指令和数据读取。
默认Flash指令和数据预取功能是使能的
运行Flash Program驱动时,需要关闭CPU Cache和Flash预取功能
寄存器MSCM->OCMDR0/1/2分别用于配置S32K1xx系列MCU的P-Flash、D-Flash和EEERAM的读推测 (speculation) 和预取 (prefetch) 功能 (EEERAM无指令和数据推测与预取功能)。
寄存器MSCM->OCMDR0/1/定义如下:↓↓↓
寄存器MSCM->OCMDR2定义如下,无OCM1控制位:↓↓↓
寄存器MSCM->OCMDR0/1/2的默认值如下:↓↓↓
Tips
通过以下代码可以配置使能S32K1xx系列MCU的Flash读buffer的推测(speculation)和预取(prefetch)功能:↓↓↓
1./* enable the P-Flash data and instruction speculate & prefetch function*/
2.MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x0u) ;
3./* enable the D-Flash data and instruction speculate & prefetch function*/
4.MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x0u) ;
←左右滑动,查看完整代码→
Tips
通过以下代码可以配置关闭S32K1xx系列MCU的Flash读buffer的推测(speculation)和预取(prefetch)功能:↓↓↓
1./* disable the P-Flash data and instruction speculate & prefetch function*/
2.MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x3u) ;
3./* disable the D-Flash data and instruction speculate & prefetch function*/
4.MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x3u) ;
←左右滑动,查看完整代码→
4.编译器 (compiler) 优化配置,使用-Ospeed最大优化运行速度/性能
根据编译原理的知识可知,任何用户高级语言 (C/C++) 开发的应用程序编译时,编译结果的运行速度 (Speed) 与其储存所占用的存储器大小 (Size) 二者通常是相互矛盾,不可兼得的;即可以通过牺牲MCU的Flash存储器空间来换取更快的执行速度,或者反之。
因此,一个嵌入式MCU的CPU内核性能是否可以发挥到最大,让代码执行得足够快,跟其所使用的应用程序开发工具链的C/C++和汇编语言编译器及其编译优化目标/等级关系十分密切。
使用任何工具链时,新建应用工程的编译器优化都是关闭的(-O0),需要用户自己配置开启才能启用。
Tips
相对而言,无优化时,专业的Keil和IAR编译器编译结果明显优于S32DS使用的GCC;S32DS提供的GCC优化选项十分粗略,具体的优化详解并不清楚,所以建议客户慎用。
关于S32DS的GCC编译器优化选项配置,请参考如下文章:《S32DS GNU GCC编译优化选项与配置方法详解及S32 SDK代码编译优化选项设置建议》。
5.将频繁访问的数据 (.bss段、.data段和堆栈(heap & stack)) 放置在SRAM_U区,实现真正的哈弗CPU架构
根据文章引言部分的介绍可知,S32K14x系列MCU的SRAM由SRAM_L和SRAM_U两个区域组成,SRAM_L区域通过ARM CM4F内核的Code Bus总线访问,而SRAM_区域则通过ARM CM4F内核的System Bus总线访问,所以只有将应用程序频繁访问的数据(.bss段、.data段和堆栈(heap & stack))放置在SRAM_U区,程序运行时才是真正的哈架构,数据和指令总线独立工作,此时CPU内核工作效率最高。↓↓↓
Tips
默认S321xx SDK提供的链接文件中,将.data段放在SRAM_L区域中,而将.bss段和堆栈(heap & stack)放在SRAM_U区域中,其原因如下:
1.可以充分利用MCU的SRAM资源,若全部数据都放在SRAM_U区域,会浪费掉SRAM_L区域;
2.相对而言,.程序运行时,bss段和堆栈 (heap & stack) 比.data段访问频率更高。
S32K11x系列MCU只有1KB的MTB SRAM映射在SRAM_L区域,MTB (Micro Trace Buffer) 通常作为程序/指令调试跟踪功能缓存使用,在默认的SDK链接文件中未被分配使用。
6.使用硬件FPU可以将CPU浮点数计算性能提高1个数量级 (S32K14x系列only)
最后,若使用应用程序用使用到了浮点数计算,则要充分利用S32K14x系列MCU CM4F内核集成的硬件FPU,因为其有专门的指令集和寄存器资源,可以与CM4F内核的整数指令同时执行。因此,相同内核工作频率下,可以将浮点数计算速度提高一个数量级:↓↓↓
Tips
新建工程时,默认配置未使用硬件FPU;若应用代码中出现浮点数运行,则会调用整数指令模拟的库函数实现,执行效率低。
使能FPU后,浮点数运算编译结果反汇编代码如下,会使用v打头的FPU指令集。↓↓↓
关于S32K14x的FPU使用方法,请参考文章:《S32K14x系列MCU使用Tips之硬件FPU特性介绍和使用详解。
总结
本文详细介绍了S32K1xx系列MCU的CPU内核性能优化方法——CPU的指令和数据Cache、Flash工作频率与读buffer的指令和数据预测预取、应用程序的编译优化、数据指令存储地址的优化以及硬件FPU指令的使用。
希望对大家都能够从本文有所收获,掌握S32K1xx系列MCU的CPU内核性能优化方法,并由此及彼,推一返三,真正理解嵌入式MCU CPU内核性能的优化思想和方法!
(本文转载自微信公众号「汽车电子expert成长之路」,你可点击【阅读原文】查看原文,并与作者互动交流)
作者:NXP 文章出处:NXP客栈
|