ARM Cortex M4使用浮点运算单元(FPU)
1.ARM Cortex M4
ARM Cortex-M4处理器是由ARM专门开发的最新嵌入式处理器,在M3的基础上强化了运算能力,新加了浮点、DSP、并行计算等。Cortex-M4处理器的最大亮点之一,也是本文主要描述的一个功能就是增加了一个单精度浮点单元(FPU),能够高效率处理较为复杂的浮点运算,如电机闭环控制、PID算法、快速傅里叶变换等。关于M4与M3的性能对比,官方提供的测试数据如图。
16bit循环计数
32bit循环计数
对于图表,Y轴代表执行给出的计算用的相对的周期数。 因此,循环数越小,性能越好。以Cortex - M3作为参考,Cortex - M4的性能计算,性能比大概为其周期计数的倒数。举例说明,PID功能,Cortex - M4的周期数是与Cortex - M3的约0.7倍,因此相对性能是1/0.7,即1.4倍。
2.使用M4的浮点运算
2.1获取FPU库
M4浮点库集成在Keil中,安装完Keil工具,即可从对应的文件路径获取FPU库。
·对于Keil4,库文件在路径:“..\Keil\ARM\CMSIS”
·对于Keil5,库文件在路径:“..\Keil_v5\ARM\Pack\ARM\CMSIS\4.3.0\CMSIS”,前面“..”是安装的磁盘路径,比如:“D:\Keil_v5\ARM\Pack\ARM\CMSIS\4.3.0\CMSIS”;对于不同版本的的Keil5其中“4.3.0”的命名不一样,如有可能是“4.2.0”。
2.2拷贝库文件
对于一个项目来说,为了工程的完整性和源文的管理,一般将库文件拷贝到项目工程中文件路径下。这里有两种处理用方法。
·使用该目录下的“Lib”库,该文件夹就是FPU相关运算函数库,使用时根据头文件函数名调用库。
·使用该目录下的“DSP_Lib”库,该文件夹是FPU相关运算函数库源码,每个浮点运算函数都提供源码,比较好理解和使用。如下图,各类函数都有分好类,可以查看源码,具体函数功能和描述官方有标准的手册介绍。
鄙人用的是第二种方法,两种方法各有优势,方法一中已将源码编译程库文件,不参与编译过程,只参与链接,编译速度快;方法二,参与编译、链接过程,编译耗时,但使用时可以查看源码,便于理解和使用。
2.3加入FPU库
首先将FPU库的路径加入Keil的编译路径中。
第二步是加入工程,可以全部FPU库函数添加到工程中,但一般根据需要选择性添加使用到的函数库,提高编译速度和节省空间。鄙人暂时用到标准差( standard deviation)和平均值(mean)运算函数,所以仅添加两函数。另外,从命名看,ARM的命名规则比较易懂,基本上看函数名称即可知道该函数的功能,如标准差运算函数arm_std_f32,平均值运算函数arm_mean_f32,等都是以对应术语的英文名称命名。
2.4开启FPU
使能浮点运算,在工程设置中“option for target” 中开启浮点运算功能。
加入FPU库的宏“ARM_MATH_CM4”定义。
在官方提供的对应MCU型号的头文件中,将FPU选择宏开启,如STM32的“stm32f407xx.h”,鄙人用的是LPC4088,头文件为“LPC407x_8x_177x_8x.h”。
#define __FPU_PRESENT 1 /*!< FPU present or not */
2.5使用FPU
使用前,需要在文件头加入浮点库函数头文件,即是#include “arm_math.h”,否则编译时可能会提示警告或者编译错误。然后即是根据库函数的参数类型传入对应类型参数调用该函数。
3.总结
实体测试及综合网友的一些实验,关于FPU的几个总结:
1)编译器未开启FPU功能,代码中配置了FPU,程序依然按照未配置FPU的代码进行处理。
2)编译器开启了FPU功能,代码中未配置FPU,如果代码中带有单精度(float)浮点运算的代码,编译器会使用FPU单元汇编指令,无论芯片是否开启了FPU功能。除非用户在代码中关闭了FPU功能,此时程序执行会出错,直接进入HardFault_Handle。
3)Cortex M4默认的开启浮点运算功能的,但目前M4只支持单精度浮点运算,单精度浮点运算对于大部分场合来说已经足够使用。
4)一般情况下,编译器对于小数处理默认是双精度(double)类型,所以在涉及小数运算时,若要使用FPU功能,应该指定为单精度类型,如:float a = 1.23f * 2.34f。