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

开发环境

  1. MCU:STM32F407ZET6
  2. IDE:MDK V5.14.0.0
  3. 软件包:uCOS-II V2.19
  4. 软件包:LUA

异常现象

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

解决过程

首先交代一下两份程序。

  • 需要移植的STM32F1程序是一份已经在产品上使用的程序,代码运行稳定没有问题。
  • 被移植的STM32F4的工程我使用了之前调试的另一个项目的工程,没有使用一个新的工程模板,也没有对这个工程内不使用的代码进行清理。因为这个工程内有我准备使用的uCOS和LUA的代码(当时也调了很久,这是另一个坑)

遇到HardFault首先怀疑是数组下标越接导致,经过定位后发现居然是一条if判断语句在这里插入图片描述
当执行这条简单的数值判断时,触发了HardFault,很明显不是数组下标越接或者是指针非法访问导致。在排除堆栈溢出、中断异常、编译器抽风等问题后,发现出现问题的变量数据类型为float
在这里插入图片描述
并且对float类型的读写访问都会出错,通过反汇编窗口发现是VLDR这条语句引起
在这里插入图片描述

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

问题重现

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

	int i;
	float f;
	double d;
	i=0;
	f=0;
	d=0;
	i=d;
	d=i;
	i=f;
	f=i;
  1. 打开FPU功能,不勾选Use MicroLIB,一切正常
  2. 关闭FPU功能,main函数无法进入,直接触发HardFault_Handler
  3. 关闭FPU功能,勾选Use MicroLIB,可以进入main函数了,对float和double类型的读写访问都会触发HardFault_Handler
  4. 打开FPU功能,勾选Use Micro LIB,一切正常

结论

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

致谢

最后感谢小麦大叔(一名被技术耽误的文坛巨匠)深夜提供帮助,向大家推荐他的博客和文章:

小麦大叔
《人人焦虑的时代,程序员该如何安身立命,我记住了这些…》

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值