最近把玩了一下STM32F4开发套件,对F4的性能不是很了解,今天可算是对F4的FPU有了深刻印象。由于在STM32F103上跑UCOS非常带劲,所以也想在F4上移植一下UCOS好好爽一把。正是这个想法我就去查关于在F4上移植UCOS的资料,看到一个让我感到非常奇怪的东西,有两个版本的ucos移植,第一种是带FPU,第二种是不带的。我就开始去查F4上FPU的资料,想看看到底是个什么特殊的东西。一查就查出了很多之前没想到的问题。网上有很多人出现这样一个问题:在MDK中设置了运用FPU但是当程序中运行到关于浮点型运算的时候就会跳入硬件错误的死循环里。对于这个问题我也写了一个程序试了试,我在程序中加入了两句:
float a;
a = 3.14;
最后仿真查看的时候发现程序运行到a = 3.14的时候就跑到硬件错误那里。不遇到问题还好,现在遇到了问题的赶紧查。好在网上资源丰富啊,找到了一个解决的方法:
虽然编译器正确产生了V指令来进行浮点运算,但是因为system_stm32f4XXX.c文件没有启用FPU,因此CPU执行时只认为是遇到非法指令而跳转到HardFault_Handler()中断中原地踏步。因此要保证这个错误不发生,必须要在system_init()函数里面添加如下代码:/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
将问题解决后我感觉FPU的故事还没有完毕定还有好戏在后面。继续查资料又有了新的发现:
对于复杂运算,比如三角函数,开方等运算,如果编程时还是使用math.h头文件,那是没法提升效率的:因为math.h头文件是针对所有ARM处理器的,其运算函数都是基于定点CPU和标准算法(IEEE-754),并没有预见使用FPU的情况,需要很多指令和复杂的过程才能完成运算,也就增加了运算时间。因此要充分发挥M4F的浮点功能,就需要使用固件库自带的arm_math.h,这个文件根据编译控制项(__FPU_USED == 1)来决定是使用那一种函数方法:如果没有使用FPU,那就调用keil的标准math.h头文件中定义的函数;如果使用了FPU,那就是用固件库自带的优化函数来解决问题。
但需要注意,如果你直接使用sin()、cos()、sqrt()这样的函数,那结果还是调用keil的math.h完成三角函数的计算。就要使用arm_sin_f32()或者arm_cos_f32(),用法不变,这两个函数的原型分别在arm_sin_f32.c和arm_cos_f32.c中。通过对256点三角函数表的查询和插值算法得到任意角度的精确函数值,这就比“原装”的sin()、cos()快多了。
我认为F4中FPU的故事应该不只这些,还有我没发现的就希望网友告诉我啦!!!