用gcc-arm-none-eabi编译的代码在Cortex-M4 MCU上计算sqrt结果不正确的问题

某项目在一款 Cortex-M4 MCU 上需要做一些浮点运算,用C写的代码,编译器用的是 gcc-arm-none-eabi-10.3-2021.10。结果发现运算结果总是不正确,查了很久找不出原因,最后好不容易才发现是调用数学库函数 sqrt 计算平方根竟然计算结果不正确!sqrt 的返回值竟然直接等于输入参数!难道编译器有bug?搜索发现 8 年前就有人遇到过同样问题:

https://stackoverflow.com/questions/20729794/sqrt-function-on-stm32-arm-doesnt-work

但是并没有找到原因。

我换了不同版本的 gcc-arm-none-eabi 试,都有同样问题,如果这真的是编译器的 bug,应该是已经存在很多年了。

后来发现这个 bug 并不是 100% 必现,如果程序里换一个位置调用 sqrt,计算结果又是正确的,不知道什么情况下才会触发这个 bug。

如何解决?一种办法是自己写一个 sqrt 函数,并不复杂,也有很多开源代码可以参考,但是性能未必理想。

查阅资料得知实际上 Cortex-M4 本身就支持硬件 sqrt 指令,也就是 VSQRT.F32 指令,只需要 14 个机器周期即可完成。ARM 自家的 armcc 编译器(也就是 Keil MDK 缺省的编译器)对 VSQRT.F32 指令支持得很好,C 代码里只需要调用函数 __sqrtf,编译器就会直接调用 VSQRT.F32 指令,经过实际验证确实如此。然而 gcc-arm-none-eabi 貌似不行,它不支持 __sqrtf,而且似乎也无法编译生成调用 VSQRT.F32 指令的代码,至少我找了很多资料都没找到办法。但是我这个项目只能使用 gcc 编译,最后我想到了嵌入式汇编,直接用嵌入式汇编在 C 代码里写了个调用 VSQRT.F32 计算平方根的函数,简单粗暴但非常有效:

	inline float MySqrt(float x)
	{
		float out;
		__asm__("VSQRT.F32 %0,%1" : "=t"(out) : "t"(x));
		return out;
	}

如果大家有能让 gcc-arm-none-eabi 生成调用 VSQRT.F32 指令的代码的方法,也希望不吝赐教。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值