FPU与VFP最全面解释

本文希望能将FPU以及ARM中的FPU介绍清楚。

1. FPU(Floating-Point Unit)

浮点运算单元是处理器内部用于执行浮点数计算的逻辑部件,或者说硬件电路。不是所有的处理器都有该功能。浮点运算满足IEEE 754的标准,所谓IEEE 754标准,定义了浮点数字的存储和计算方式、计算异常等,比如IEEE 754标准准确地定义了单精度(32位)和双精度(64位)浮点格式。
对于含有FPU的处理器,我们可以通过控制编译选项的方式使编译器编译出的代码使用FPU指令。

2. -mfloat-abi=name来指定浮点运算处理方式

gcc为例,对应的-mfloat-abi参数值有三个:soft,softfp,hard。

  1. soft是指所有浮点运算全部在软件层实现,比如ARM提供了一个「浮点支持软件库」用于计算浮点数:fplib。使用软件的方式来计算浮点最终是通过执行了很多的指令来完成一次运算,不仅慢而且程序体积大。fplib提供的 API 以__aeabi开头,比如:__aeabi_fadd:计算两个float型浮点数加法(float占4个字节,32位)
  2. softfp是指浮点运算的实际计算是在FPU上来做,但是传递浮点运算的参数是用整形的通用寄存器(r0-r3)来传递的。比如float fadd(float a, float b),a和b实际上是通过r0,r1传入到被调函数的,结果也是通过r0传出的。
  3. hard与softfp的区别是不仅运算实际发生在FPU上,浮点参数的传递使用的也是浮点专用寄存器。以上同样的例子,a和b是通过s0, s1寄存器来传的,结果是通过s0传出的。softfp和hard两种模式不兼容,所以你不能将一个使用softfp方式的库和另外一个使用hard的库或目标文件链接起来。因为如此,armv7有些编译好的库(比如glibc使用softfp)没法在使用另一种使用hard的应用中编译。
    在这里插入图片描述

使用软件库编译出的代码实例:
在这里插入图片描述
使用hard编译出的使用FPU的代码实例:
在这里插入图片描述

3. -mfpu=name来指定浮点协处理的类型

在ARM中的FPU被称为VFP(Vector Floating Point),即向量浮点运算,之所以称为“向量”浮点是因为在ARMv6及以前这个扩展不只是用于增加浮点数计算处理,同时也用于类似向量的SIMD浮点数计算处理。在ARMv7架构中,这种使用VFP来处理向量浮点数据的方式不建议采用,相关的功能可以使用“先进SIMD扩展”来替代。而vfp经过几代的发展和完善,出现了vfpv3, vfpv4, fpv5等多个版本,每个版本又可以配置为不同的使用方式,所以,这个-mfpu参数就是指定所采用的vfp硬件。
在文档《Arm Compiler for Embedded Reference Guide》中列举了可以使用的值,可选类型如none, softvfp,vfpv3,vfpv3-d16,vfpv3-d16-fp16,vfpv3xd, neon, vfpv4,fpv4-sp-d16,fpv5-d16,fpv5-sp-d16等。简单从文档中摘出几个:

  • none, softvfp: Use either -mfpu=none or -mfpu=softvfp to prevent the compiler from using hardware-based floating-point functions. If the compiler encounters floating-point types in the source code, it uses software-based floating-point library functions. This option is similar to the -mfloatabi=soft option.
  • vfpv3: Enable the Armv7 VFPv3 Floating-point Extension. Disable the Advanced SIMD extension.
  • vfpv3-d16: Enable the Armv7 VFPv3-D16 Floating-point Extension. Disable the Advanced SIMD extension.
  • vfpv3-fp16: Enable the Armv7 VFPv3 Floating-point Extension, including the optional half-precision extensions. Disable the Advanced SIMD extension.
  • vfpv4:Enable the Armv7 VFPv4 Floating-point Extension. Disable the Advanced SIMD extension.
  • neon-vfpv4:Enable the Armv7 VFPv4 Floating-point Extension and the Advanced SIMD extension.
  • fpv5-sp-d16: Enable the Armv7 FPv5-SP-D16 Floating-point Extension for single precision only.

如果你对d16之类的后缀感兴趣,下面这张浮点寄存器表可能解答你的疑惑,其中D代表double,64bit寄存器,sp表示single precision, 表示只允许32位单精度浮点计算:
在这里插入图片描述
还有个小问题就是vfpv3, vfpv4, vfpv5之间有什么区别呢?从维基百科ARM architecture family 4.10章节中摘录如下:https://en.wikipedia.org/wiki/ARM_architecture_family#Floating-point_(VFP)

  • VFPv1
    Obsolete
  • VFPv2
    An optional extension to the ARM instruction set in the ARMv5TE, ARMv5TEJ and ARMv6 architectures. VFPv2 has 16 64-bit FPU registers.
  • VFPv3 or VFPv3-D32
    Implemented on most Cortex-A8 and A9 ARMv7 processors. It is backward-compatible with VFPv2, except that it cannot trap floating-point exceptions. VFPv3 has 32 64-bit FPU registers as standard, adds VCVT instructions to convert between scalar, float and double, adds immediate mode to VMOV such that constants can be loaded into FPU registers.
  • VFPv3-D16
    As above, but with only 16 64-bit FPU registers. Implemented on Cortex-R4 and R5 processors and the Tegra 2 (Cortex-A9).
  • VFPv3-F16
    Uncommon; it supports IEEE754-2008 half-precision (16-bit) floating point as a storage format.
  • VFPv4 or VFPv4-D32
    Implemented on Cortex-A12 and A15 ARMv7 processors, Cortex-A7 optionally has VFPv4-D32 in the case of an FPU with Neon. VFPv4 has 32 64-bit FPU registers as standard, adds both half-precision support as a storage format and fused multiply-accumulate instructions to the features of VFPv3. 相比v3增加了半精度和乘加指令的支持。
  • VFPv4-D16
    As above, but it has only 16 64-bit FPU registers. Implemented on Cortex-A5 and A7 processors in the case of an FPU without Neon.
  • VFPv5-D16-M
    Implemented on Cortex-M7 when single and double-precision floating-point core option exists. 单双精度可以选择。

此外,关于VFP架构和功能上的一些解释可以参考:《ARM Compiler armasm User Guide Version 5.06》 VFP Programming一节,写得比较清楚: https://developer.arm.com/documentation/dui0473/m/vfp-programming/architecture-support-for-vfp

4. NEON和VFP

在上面的一些介绍中,可以看到NEON经常和VFP一起出现,ARM中的NEON即SIMD(单指令多数据)技术,是一种真正的向量化运算方式,他们之所以耦合在一起是因为他们公用浮点寄存器。
在这里插入图片描述在这里插入图片描述
这里插一句题外话,如果想入门ARM SIMD编程,【张先轶】SIMD向量化编程入门——https://www.bilibili.com/video/BV1KZ4y1Y7VH/?spm_id_from=333.337.search-card.all.click&vd_source=d9ead405209236cb507b6c90c75777f9 这个课程可以借鉴。

以下是NEON与VFP的几点异同。

  1. ARM架构中支持 没有NEON和VFP, 只有VFP,NEON和VFP都有 三种配置,不支持只有NEON的配置。
  2. NEON使用32个双精度浮点寄存器,即32D,因此如果一些VFP配置D16则就无法使用NEON了。
  3. NEON不支持双精度浮点的计算,也不支持如square root和divide等一些比较复杂的浮点运算。
5. 编译工具中配置FPU

在上述2和3中描述了如何配置编译选项能够让编译器编译出来使用FPU指令的代码,那对于没有makefile的GUI用户如何设置呢?
MDK:
在这里插入图片描述
IAR:
在这里插入图片描述
ARM Cortex - M4内核中将 FPU 作为协处理器设计的,所以通过设置协处理器访问控制(CPACR,Co-processor access control register)来控制是否使能FPU。在这些工具软件中使能FPU后,编译器会设置宏定义__FPU_USED == 1,该配置将在代码中启用FPU硬件。

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
 SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif
参考:
  1. ARM技术杂谈:何谓FPU、VFP、ASE、NEON、MPE、SVE、SME以及MVE —— https://www.eefocus.com/article/521046.html
  2. Armv8上不弃不离的NEON/FPU —— https://www.jianshu.com/p/a19cc2ca59da
  3. ARM FPU 加速浮点计算 介绍 —— https://blog.csdn.net/u014436243/article/details/122078377
  4. ARM Cortex-A Series Programmer’s Guide for ARMv7-A —— https://developer.arm.com/documentation/den0013/d/Introducing-NEON/NEON-architecture-overview/Commonality-with-VFP
  5. ARM Cortex-M7 Processor Technical Reference Manual r0p2:About the FPU —— https://developer.arm.com/documentation/ddi0489/b/floating-point-unit/about-the-fpu
  6. IEEE 754浮点数标准详解 —— http://c.biancheng.net/view/314.html
  7. arm浮点运算 —— http://t.zoukankan.com/-9-8-p-9254964.html
  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CubeMX是STMicroelectronics公司开发的一款集成开发环境(IDE)软件,用于开发STM32微控制器。FPU浮点单元(Floating Point Unit)的缩写,是CPU的一个组件,用于执行浮点运算。在使用CubeMX软件进行STM32的开发时,可以通过配置使得FPU能够被使用。 使用FPU可以加快程序执行浮点运算的速度,特别是在涉及到大量的浮点运算时。对于一些需要高精度计算或者需要频繁处理浮点数的应用程序,启用FPU可以显著提高程序的运算性能。通常,启用FPU需要在程序中进行一些特殊的配置,以便将浮点数数据类型与处理器的FPU相关部分相关联。 在CubeMX中,可以通过简单的界面操作对FPU进行相应的配置。首先,需要选择正确的STM32系列和型号,并将相应的时钟设置和其他外设配置完成。然后,在“配置”选项卡中,可以找到“启用浮点单元”选项,勾选启用FPU,并选择想要使用的FPU类型(如单精度硬件浮点单元或双精度硬件浮点单元)。 通过这样的配置,生成的CubeMX代码将自动包含关于FPU的初始化和配置代码。这样,开发人员就可以在程序中使用浮点数数据类型,以及进行浮点数的运算。在运行时,FPU将会处理这些浮点运算,提供更高的计算性能。 总之,CubeMX为STM32的开发提供了便捷的图形化界面,同时也提供了对FPU的配置,使得开发人员能够方便地启用FPU,提高程序的浮点运算性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值