FPU 即浮点运算单元(Float Point Unit)。浮点运算,对于定点 CPU(没有 FPU 的 CPU)
来说必须要按照 IEEE-754 标准的算法来完成运算,是相当耗费时间的。而对于有 FPU 的 CPU
来说,浮点运算则只是几条指令的事情,速度相当快。
STM32F4 属于 Cortex M4F 架构,带有 32 位单精度硬件 FPU,支持浮点指令集,相对于
Cortex M0 和 Cortex M3 等,高出数十倍甚至上百倍的运算性能。
STM32F4 硬件上要开启 FPU 是很简单的,通过一个叫:协处理器控制寄存器(CPACR)
的寄存器设置即可开启 STM32F4 的硬件 FPU,该寄存器各位描述如图 51.1.1.1 所示:
图 51.1.1.1 协处理器控制寄存器(CPACR)各位描述
这里我们就是要设置 CP11 和 CP10 这 4 个位,复位后,这 4 个位的值都为 0,此时禁止访
问协处理器(禁止了硬件 FPU),我们将这 4 个位都设置为 1,即可完全访问协处理器(开启
硬件 FPU),此时便可以使用 STM32F4 内置的硬件 FPU 了。CPACR 寄存器这 4 个位的设置,
我们在 system_stm32f4xx_c 文件里面开启,代码如下:
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
……//省略部分代码
}
此部分代码是系统初始化函数的部分内容,功能就是设置 CPACR 寄存器的 20~23 位为 1,
以开启 STM32F4 的硬件 FPU 功能。从程序可以看出,只要我们定义了全局宏定义标识符
__FPU_PRESENT 以及__FPU_USED 为 1,那么就可以开启硬件 FPU。其中宏定义标识符
__FPU_PRESENT 用来确定处理器是否带 FPU 功能,标识符__FPU_USED 用来确定是否开启FPU 功能。
实际上,因为 F4 是带 FPU 功能的,所以在我们的 stm32f4xx.h 头文件里面,我们默认是定
义了__FPU_PRESENT 为 1。大家可以打开文件搜索即可找到下面一行代码:
#define __FPU_PRESENT 1
但是,仅仅只是说明处理器有 FPU 是不够的,我们还需要开启 FPU 功能。开启 FPU 有两
种方法,第一种是直接在头文件 STM32f4xx.h 中定义宏定义标识符__FPU_USED 的值为 1。也
可以直接在 MDK 编译器上面设置,我们在 MDK5 编译器里面,点击
按钮,然后在 Target
选项卡里面,设置 Floating Point Hardware 为 Use Single Precision,如图 51.1.1.2 所示:
图 51.1.1.2 编译器开启硬件 FPU 选型
经过这个设置,编译器会自动加入标识符__FPU_USED 为 1。这样遇到浮点运算就会使用
硬件 FPU 相关指令,执行浮点运算,从而大大减少计算时间。
最后,总结下 STM32F4 硬件 FPU 使用的要点:
1, 设置 CPACR 寄存器 bit20~23 为 1,使能硬件 FPU。
2, MDK 编译器 Code Generation 里面设置:Use FPU。
经过这两步设置,我们的编写的浮点运算代码,即可使用 STM32F4 的硬件 FPU 了,可以
大大加快浮点运算速度。
转了等于我会了~真是个小机灵鬼呢~
附:UCOSIII移植过程中,似乎是低版本的不支持FPU,在移植到STM32F4系列时,有浮点计算时任务不执行,在PendSv_Handle中,并未对浮点处理寄存器做进出栈的操作。最新的ucosIII好似更新到了V3.09版本呢,官网的Release文档也有相关FPU的更新说明,但是我依然选择在UCOSIIIde V3.0.4版本上更新,借助网络上前辈的荫,成功解锁了UCOSIII移植到STM32F4系列的FPU使用