FPU简介

近年,在Cortex-M3之后ARM公司又推出Cortex-M4内核,ARM Cortex-M4处理器是由ARM专门开发的最新嵌入式处理器,在M3的基础上强化了运算能力,新加了浮点、DSP、并行计算等。Cortex-M4处理器的最大亮点之一,也是本文主要描述的一个功能就是增加了一个单精度浮点单元(FPU),能够高效率处理较为复杂的浮点运算,如电机闭环控制、PID算法、快速傅里叶变换等。

Cortex-M4的指令集分两部分,一部分是在M3的指令集外增加了一些扩展功能。另一部份就是用于FPU单元的单精度浮点运算指令。

浮点运算指令都是V开头的汇编指令,用于FPU单元的单精度浮点运算,只有当FPU开启后才能使用这些指令,否则会产生硬fault异常。

单精度浮点单元(FPU),能够高效率处理较为复杂的浮点运算,如电机闭环控制、PID算法、快速傅里叶变换等。关于M4与M3的性能对比,官方提供的测试数据如图。

 

DSP库

如果要使用FPU单元来进行浮点运算,就需要在工程中加入DSP库。

FPU属于ARM架构一部分,不是厂商MCU特有,所以在ARM包安装中已经包含。

在keil包路径下能找到

D:\EmbededSofts\KeilMDK5_PACKS\ARM\CMSIS-DSP\1.14.2\Source

关于这个函数库的详细信息,请移步官网:

arm_math.h File Reference

DSP库主要包含以下几个分库:

BasicMathFunctions

基本数学函数:提供浮点数的各种基本运算函数,如向量加减乘除等运算。

CommonTables

arm_common_tables.c文件提供位翻转或相关参数表。

ComplexMathFunctions

复杂数学功能,如向量处理,求模运算的。

ControllerFunctions

控制功能函数。包括正弦余弦,PID电机控制,矢量Clarke变换,矢量Clarke逆变换等。

FastMathFunctions

快速数学功能函数。提供了一种快速的近似正弦,余弦和平方根等相比CMSIS计算库要快的数学函数。

FilteringFunctions

滤波函数功能,主要为FIR和LMS(最小均方根)等滤波函数。

MatrixFunctions

矩阵处理函数。包括矩阵加法、矩阵初始化、矩阵反、矩阵乘法、矩阵规模、矩阵减法、矩阵转置等函数。

StatisticsFunctions

统计功能函数。如求平均值、最大值、最小值、计算均方根RMS、计算方差/标准差等。

SupportFunctions

支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。

TransformFunctions

变换功能。包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT(RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。

对于一个项目来说,为了工程的完整性和源文的管理,一般将库文件拷贝到项目工程中文件路径下。这里有两种处理用方法。

--使用该目录下的“Lib”库,该文件夹就是FPU相关运算函数库,使用时根据头文件函数名调用库。

--按照常规方式直接拷贝函数库源码,每个浮点运算函数都提供源码,比较好理解和使用。各类函数都有分好类,可以查看源码,具体函数功能和描述官方有标准的手册介绍。

两种方法各有优势,方法一中已将源码编译程库文件,不参与编译过程,只参与链接,编译速度快,但是看不到源码,也就是跳转时无法找到定义;方法二,参与编译、链接过程,编译耗时,但使用时可以查看源码,便于理解和使用。

CMSIS DSP的.LIB库文件

考虑到方便用户使用,ARM官方已编译好Cortex-M各型号的.lib库(静态库)文件,并放置于Lib文件夹。

库文件能在KEIL包的安装路径中找到

D:\EmbededSofts\KeilMDK5_PACKS\ARM\CMSIS\5.6.0\CMSIS\DSP\Lib\ARM

DSP库函数的声明位域头文件arm_math.h中,用户只要简单地将该头文件和.lib文件添加到自己的工程中,即可呼叫DSP库函数。该头文件对于浮点运算单元(FPU)的变量同样适用。  

这几种库有啥区别?

arm_cortexM4b_math.lib代表设备为大端模式;

arm_cortexM4bf_math.lib代表设备为浮点大端模式

其中arm_cortexM4l_math.lib代表设备为小端模式

其中arm_cortexM4lf_math.lib代表设备为浮点小端模式

对于F407来说,使用arm_cortexM4lf_math.lib即可。

当导入了该库之后,就不用再添加对应的源文件了,只需要添加对应的头文件即可。

Keil运行环境配置

第一步

首先,我们在例程工程目录下新建:DSP_LIB 文件夹,存放我们将要添加的文件:

arm_cortexM4lf_math.lib 和相关头文件,如下图所示:

Include 文件夹,则是直接拷贝:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0LibrariesCMSISInclude 这个 Include 文件夹,里面包含了我们可能要用到的相关头文件。

然后,打开工程,新建 DSP_LIB 分组,并将 arm_cortexM4lf_math.lib 添加到工程里面,如下图所示:

第二步, 添加头文件包含路径

添加好.lib 文件后,我们要添加头文件包含路径,将第一步拷贝的 Include 文件夹和DSP_LIB文件夹,加入头文件包含路径,如下图所示:

第三步, 添加全局宏定义

FPU单元是指的芯片上的一个独立于CPU处理的浮点运算单元,整个单元在大多数厂家的芯片中都是可以被使能和关闭的。相对于芯片,编译器也设置了相应的FPU功能开启/关闭的选项,在编译时需要告诉编译器是否开启FPU功能。编译器一旦开启FPU功能,在处理单精度浮点运算的语句时就会用带V-开头的汇编指令进行编译。

如果编译器使能了FPU功能,而芯片未开启FPU单元,程序运行到浮点语句时就会出现异常。相反,如果编译器未使能FPU功能,芯片即使开启了FPU单元,程序还是会按照未使能FPU的代码进行处理。

为了使用 DSP 库的所有功能,我们还需要添加几个全局宏定义:

1__FPU_USED

2__FPU_PRESENT

3ARM_MATH_CM4

4__CC_ARM

5ARM_MATH_MATRIX_CHECK

6ARM_MATH_ROUNDING

 致此,配置已完成。

以下为选读内容

其中,也可以不添加__FPU_PRESENT,在工程里开启即可。

在官方提供的对应MCU型号的头文件中,将FPU选择宏开启,如STM32的“stm32f407xx.h”

一般来说,默认就是开启的。

但是,仅仅只是说明处理器有 FPU 是不够的,我们还需要开启 FPU 功能。开启 FPU 有两种方法,第一种是直接在头文件 STM32f4xx.h 中手动定义宏定义标识符__FPU_USED 的值为 1。也可以直接在 MDK 编译器上面设置,我们在 MDK5 编译器里面,点击 按钮,然后在 Target 选项卡里面,设置 Floating Point Hardware Use Single Precision

经过这个设置,编译器会自动加入标识符__FPU_USED 1。这样遇到浮点运算就会使用

硬件 FPU 相关指令,执行浮点运算,从而大大减少计算时间。

关于这两个宏定义的由来

经验证,使用硬件 FPU 和不使用硬件 FPU 对比,同样的条件下,快了近 10 倍,充分体现了 STM32F4 硬件 FPU 的优势。

注意

Cortex M4默认的开启浮点运算功能的,但目前M4只支持单精度浮点运算,单精度浮点运算对于大部分场合来说已经足够使用。

一般情况下,编译器对于小数处理默认是双精度(double)类型,所以在涉及小数运算时,若要使用FPU功能,应该指定为单精度类型,如:float a = 1.23f * 2.34f。

#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"

明明已经定义了__FPU_PRESENT             1

也勾选了__FPU_USED

可能勾选没有生效,直接加上这两个宏定义即可

1__FPU_USED

2__FPU_PRESENT

补充

请问对于m4内核的MCU,DSP库的指令与FPU是什么关系?

FPU跟DSP没有必然联系,即使没有FPU的Cortex M3,比如stm32f103,也可以用int模拟固定长度的浮点数来做DSP;但有了FPU以后算浮点快很多,就可以用浮点变量来做DSP。

ST官方以前是有stm32f103的DSP库的,我还用它做过FFT。后来ST改了产品线的定位以后,这个stm32f103的DSP库就下不到了,也许是为了控制用户过度到stm32f3和f4系列吧。stm32f3和f4的定位才是数字信号处理。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐