54. 浮点运算单元
一、FPU简介
FPU 即浮点运算单元(Float Point Unit)。浮点运算,对于定点 CPU(没有 FPU 的 CPU)来说必须要按照 IEEE-754 标准的算法来完成运算,是相当耗费时间的。而对于有 FPU 的 CPU 来说,浮点运算则只是几条指令的事情,速度相当快。
STM32F407 属于 Cortex M4 架构,带有 32 位单精度硬件 FPU,支持浮点指令集,相对于 Cortex M0 和 Cortex M3 等,高出数十倍甚至上百倍的运算性能。
STM32F407 硬件上要开启 FPU 是很简单的,通过一个叫:协处理器控制寄存器(CPACR)的寄存器设置即可开启 STM32F407 的硬件 FPU,该寄存器各位描述如下所示:
这里我们就是要设置 CP11 和 CP10 这 4 个位,复位后,这 4 个位的值都为 0,此时禁止访问协处理器(禁止了硬件 FPU),我们将这 4 个位都设置为 1,即可完全访问协处理器(开启硬件 FPU),此时便可以使用 STM32F407 内置的硬件 FPU 了。CPACR 寄存器这 4 个位的设置,我们在 system_stm32f4xx.c 文件中的 SystemInit() 函数里面开启,代码如下:
/**
* @brief Setup the microcontroller system
* Initialize the FPU setting, vector table location and External memory
* configuration.
* @param None
* @retval None
*/
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
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#endif /* USER_VECT_TAB_ADDRESS */
/* Configure the FPU */
#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,以开启 STM32F407 的硬件 FPU 功能。从程序可以看出,只要我们定义了全局宏定义标识符 __FPU_PRESENT
以及 __FPU_USED
为 1,那么就可以开启硬件 FPU。其中宏定义标识符 __FPU_PRESENT
用来确定处理器是否带 FPU 功能,标识符 __FPU_USED
用来确定是否开启 FPU 功能。
实际上,因为 STM32F407 是带 FPU 功能的,所以在我们的 stm32f407xx.h 头文件里面,我们默认是定义了 __FPU_PRESENT
为 1。
但是,仅仅只是说明处理器有 FPU 功能是不够的,我们还需要开启 FPU 功能。开启 FPU有两种方法,第一种是直接在头文件 stm32f407xx.h 中定义宏定义标识符 __FPU_USED
的值为 1。
如果使用 MDK,也可以在 Target 选项卡里面,设置 Floating Point Hardware 为 Use Single Precision,此时默认会把编译器中的 __FPU_USED 宏的值设置为 1。