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() 函数里面开启,代码如下:

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_PRESENT宏

  但是,仅仅只是说明处理器有 FPU 功能是不够的,我们还需要开启 FPU 功能。开启 FPU有两种方法,第一种是直接在头文件 stm32f407xx.h 中定义宏定义标识符 __FPU_USED 的值为 1。

如果使用 MDK,也可以在 Target 选项卡里面,设置 Floating Point Hardware 为 Use Single Precision,此时默认会把编译器中的 __FPU_USED 宏的值设置为 1。

posted @ 2024-02-04 18:29  星光映梦  阅读(31)  评论(0编辑  收藏  举报