[技术问答]

STM32F4之FPU与float类型导致的HardFault调试记录

[复制链接]
799|4
手机看帖
扫描二维码
随时随地手机跟帖
zhamatu|  楼主 | 2020-4-27 22:39 | 显示全部楼层
异常现象

正在进行的工作是一份代码的移植,原本在STM32F1处理器上稳定运行的代码移植到STM32F407上,不需要什么改动,功能本身也并不复杂,但是在移植GNSS部分的时候遇到了问题,程序进入HardFault


使用特权

评论回复
zhamatu|  楼主 | 2020-4-27 22:42 | 显示全部楼层
解决过程
首先交代一下两份程序。

需要移植的STM32F1程序是一份已经在产品上使用的程序,代码运行稳定没有问题。
被移植的STM32F4的工程我使用了之前调试的另一个项目的工程,没有使用一个新的工程模板,也没有对这个工程内不使用的代码进行清理。因为这个工程内有我准备使用的uCOS和LUA的代码(当时也调了很久,这是另一个坑)
遇到HardFault首先怀疑是数组下标越接导致,经过定位后发现居然是一条if判断语句

785755ea6ef1b388b6.png

当执行这条简单的数值判断时,触发了HardFault,很明显不是数组下标越接或者是指针非法访问导致。在排除堆栈溢出、中断异常、编译器抽风等问题后,发现出现问题的变量数据类型为float

146405ea6ef2cbac0b.png

并且对float类型的读写访问都会出错,通过反汇编窗口发现是VLDR这条语句引起

960085ea6ef388a15c.png

这时我想起之前在使用这个工程时,为了同时使用uCOS-II和LUA,关闭了FPU,勾选了use microLIB选项(当时uCOS-II使用FPU有些问题,相关的教程也没有现在这么多),找到FPU的设置,果然被关闭了
657285ea6ef4c1eeb3.png
将__FPU_PRESENT设置为1,重新编译下载,恢复正常。现在uCOS-II应该是无法正常运行了,后续再进行调试或者更换系统。

使用特权

评论回复
zhamatu|  楼主 | 2020-4-27 22:43 | 显示全部楼层
问题重现

为了重现这个问题,我在探索者的F4资料中拿出了一个新的LED流水灯的工程。在main函数加入简单的测试代码

int i;
        float f;
        double d;
        i=0;
        f=0;
        d=0;
        i=d;
        d=i;
        i=f;
        f=i;

打开FPU功能,不勾选Use MicroLIB,一切正常

关闭FPU功能,main函数无法进入,直接触发HardFault_Handler

关闭FPU功能,勾选Use MicroLIB,可以进入main函数了,对float和double类型的读写访问都会触发HardFault_Handler

打开FPU功能,勾选Use Micro LIB,一切正常


使用特权

评论回复
zhamatu|  楼主 | 2020-4-27 22:44 | 显示全部楼层
结论
在使用STM32F4时,必须使用FPU,即定义stm32f4xx.h文件种166行#define __FPU_PRESENT 1,否则在进入main函数时候会触发HardFault
如果因为某些原因不能使用FPU,定义#define __FPU_PRESENT 0,那么必须在使用微库,在设置中勾选Use MicroLIB,这时对float类型和double类型读写操作会导致HardFault,暂时没有找到解决办法。如果一定要使用浮点运算,可以考虑使用Q格式

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

504

帖子

1

粉丝