0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浮点库应用,你也有困惑吗?

恩智浦MCU加油站 来源:未知 2023-12-21 08:55 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

今天小编想要给大家带来的是最近在调试一个项目时候发现的怪事,同样的函数库在使用不同的IDE时,得到的运行结果竟然是不一致的。相信眼尖的读者朋友已经从标题中猜出一二了,正是因为库中依赖了浮点计算库所导致的问题。那么就请和小编一起,探究下详细的来龙去脉吧!

项目背景

首先再详细描述以下项目背景:我们使用了一个由GCC工具链构建的函数库,编译器选项为-mfloat-abi=hard,即在编译时,使能了硬件浮点单元指令加速。但在我们将该库与Keil项目链接后,发现结果不正确。当然,我们最先怀疑的当然是库编译的有问题啦。但是奇怪的事情发生了,我当我们使用GCC工具链链接编译相同的工程,并运行后,得到了正确的结果。那么可以基本确定,库应该是没有问题的。那么问题出在哪呢?

问题分析

由于小编所拿到的库并不包含调试信息,只能通过一些技术手段进行破解。通过反汇编库代码,我们发现库依赖了一些浮点计算库的C函数,如sqrtf、expf等,为了简便,让我们称之为xxf函数,由于GCC并没有提供其具体实现,因此需要由库的使用者链接这些函数,而经过进一步的debug,我们发现这些函数导致了错误的结果,换句话说,这些函数的返回值是错的。

问题调试

那就有意思了,为了简单起见,让我们先编写一段简单的测试代码来复现这个问题,代码很简单,我们直接定义一个开平方根的函数:

#include "math.h"

float calc_sqrt(float a){

return sqrtf(a);

}

使用gcc工具链对其进行编译:

arm-none-eabi-gcc.exe -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard test.c -fshort-wchar -c -o test.o

随后,随便找到一个Keil的测试工程,我们这里选择一个Hello_World示例工程,将编译出来的.o文件添加到工程中:

wKgZomWDjhGANp5cAABcyFsEcJc683.png

并在主程序中添加调用代码:

float calc_sqrt(float a)

volatile float a = calc_sqrt(4.0f);

编译链接下载程序,并让程序停在函数调用处:

wKgZomWDjhKAUXnTAADNmNIH8Rw407.png

单步进入calc_sqrt函数内部,到这里,我们可以发现对这些函数的调用顺序是正确的。通过将参数传递给S0(对于float)如下所示,S0中寸的就是待计算的数据4.0f:

wKgZomWDjhKAcUdQAAFHqs3OJMk254.png

wKgZomWDjhKAbZ7dAAA743Nmdr0045.png

看起来好像没有问题,再进一步现在让我们检查由Keil链接的sqrtf函数的汇编实现:

wKgZomWDjhKAF50tAADszXvbpi8487.png

相信大家发现了奇怪的事情了,链接的sqrtf将S0中的值传递给S0,而此时R0的值其实为0,但正如之前所说,浮点值已经由库的代码传递给了S0。因此,由于S0中实际要计算的值被临时替换了,就导致了一个错误的结果。

wKgZomWDjhKAFognAABSVmp7PxU258.png

这里要强调一下,如果在Keil中直接调用sqrtf时候,或是使用keil编译器所编译出来的.o文件,Keil运行时库会使用“__hardfp_sqrtf”作为sqrtf的混淆名称:

wKgZomWDjhKAZvr5AACqgxPX2Ic445.png

而因为我们所使用库来自GCC工具链,因此Keil并不会对其进行替换,而是会将C库中叫做sqrtf的函数直接链接进去,而这个函数的默认实现,是使用R0作为参数传递的寄存器。这也就导致,实际要被计算的数丢失,最终导致结果计算错误。

那么怎么解决这个问题,让keil不去链接这个奇怪的sqrtf呢,这就要用到Keil的一个小技巧了:

float $Sub$$sqrtf(float a){

return __builtin_sqrtf(a);

}

这样一来,调用sqrtf函数的地方,就会编程对$Sub$$sqrtf的调用:

wKgZomWDjhKAMFbbAAE1zkGftN4411.png

wKgZomWDjhOACcEzAAIb8mxu1DA400.png

而结果也变为正确的结果2.0了:

wKgZomWDjhOAJ6olAABTCNVByDY135.png

当然,大家可能会想啊,那我开了gcc优化之后,是不是就可以自动展开sqrtf了呢?让我们来看看:

arm-none-eabi-gcc.exe -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard test.c -fshort-wchar -c -o3 -o test.o

代码并没有变化:

wKgZomWDjhOAE65GAAEt3Qti-14440.png

结论

小编想用这个例子和大家说明下,在涉及到跨工具链开发时,一定要注意浮点库的使用或依赖问题,由于不同编译器对于浮点运算的实现可能有些许不同,会导致意想不到的奇怪问题出现。最好的方案,还是根据不同的工具链都构建一个专属的库来使用。

END

更多恩智浦AI-IoT市场和产品信息,邀您同时关注“NXP客栈”微信公众号

wKgZomWDjhOACI5YAABCdkRE230322.jpg      

NXP客栈


恩智浦致力于打造安全的连接和基础设施解决方案,为智慧生活保驾护航。

长按二维码,关注我们

恩智浦MCU加油站


这是由恩智浦官方运营的公众号,着重为您推荐恩智浦MCU的产品信息、开发技巧、教程文档、培训课程等内容。

wKgZomWDjhOAHK_FAAATNlPH08Y075.jpg  

长按二维码,关注我们


原文标题:浮点库应用,你也有困惑吗?

文章出处:【微信公众号:恩智浦MCU加油站】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    147

    文章

    18613

    浏览量

    387149
  • 恩智浦
    +关注

    关注

    14

    文章

    6051

    浏览量

    134611

原文标题:浮点库应用,你也有困惑吗?

文章出处:【微信号:NXP_SMART_HARDWARE,微信公众号:恩智浦MCU加油站】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何使用 ARM FPU 加速浮点计算?

    之前的文章:浮点数在计算机中的存储 —— IEEE 754标准[1](可点击阅读原文查看)。 二、浮点支持软件fplib 1. fplib介绍ARM Cortex-M处理器中计算浮点
    发表于 11-19 06:51

    浮点指令(三)

    浮点指令以及简单解释 fcvt.s.d fcvt.s.d rd, rs1, rs2//f[rd] = f32f64(f[rs1]) 双精度向单精度浮点转换(Floating-point
    发表于 10-24 13:38

    浮点指令(二:双精度)

    浮点指令以及简单解释 fadd.d fadd.d rd, rs1, rs2//f [rd] = f [rs1] + f [rs2] 双精度浮点加(Floating-point Add
    发表于 10-24 13:00

    浮点指令(一:单精度)

    浮点指令以及简单解释 fadd.s fadd.s rd, rs1, rs2//f [rd] = f [rs1] + f [rs2] 单精度浮点加(Floating-point Add
    发表于 10-24 11:42

    浮点指令(七:寄存器)

    UFunderflow NXinexact,不精确根据IEEE-754标准,浮点运算需要指定舍入模式(rounding mode),这有助于确定误差范围和编写数值。最准确且最常见的舍入模式是舍入到最近的偶数(RNE
    发表于 10-24 08:28

    浮点指令扩展中部分问题的解决与分享

    经过数周的前期准备与研读代码,我们组终于正式开始对浮点指令进行扩展并不出意外地遇到了一些小问题,本篇文章针对这些问题作出解决方法的分享。 一. 在e203_exu_decode中,发现变量
    发表于 10-24 08:14

    浮点舍入模式介绍(六)

    浮点舍入模式 为什么要舍入? 因为单精度浮点数只取23位尾数(除去隐藏位),而一些运算不可避免的得到的尾数会超过23位,因此需要考虑舍入。 根据 IEEE-754 标准, 浮点数运算需要指定舍入
    发表于 10-24 07:57

    (九)浮点乘法指令设计

    浮点乘法算法 设a = {sa,ea,fa},b = {sb,eb,fb}为两个IEEE754单精度浮点数,试计算c = {sc,ec,fc} = a b。c的绝对值|c| = |a||b
    发表于 10-24 07:11

    浮点运算单元的设计和优化

    浮点运算单元的设计和优化可以从以下几个方面入手: 1.浮点寄存器设计:为了实现浮点运算指令子集(RV32F或者RV32D),需要添加一组专用的浮点寄存器组,总共需要32个通用
    发表于 10-22 07:04

    risc-v中浮点运算单元的使用及其设计考虑

    RISC-V浮点运算单元(floating-point unit,简称FPU)是一种专门用于执行浮点运算的硬件加速器,其作用是提高浮点运算速度,在科学计算、图像处理和机器学习等应用领域有着广泛
    发表于 10-21 14:46

    RISCV F扩展简介——浮点寄存器

    寄存器之间传输数据。同时也有一些指令用于整数寄存器和浮点寄存器之间的直接数据交互。 上图为浮点寄存器,浮点寄存器与通用整数寄存器基本一致,唯一的区别在于其f0寄存器不需要硬件接0.
    发表于 10-21 08:50

    gcc工具链无法汇编硬件浮点指令fsqrt问题

    团队在项目推进过程中发现,Linux环境下,math中的sqrt()函数无论是在浮点数的gcc工具链中还是整数的gcc工具链中,综合的结果都是以整数指令来模拟。 若果想要进一步地节约时间,我们
    发表于 10-20 06:19

    HAL和标准会选择哪种

    HAL和标准会选择哪种
    发表于 03-10 06:25

    西门子TIA Portal如何比较两个浮点数相等

    概述: 由于浮点数的定义规则,导致浮点数不能通过二进制精确表示,所以在浮点数计算过程中,会出现两个值一样的浮点数进行比较相等计算时结果并不相等的情况。下面先设计一个实例说明该问题,并给
    的头像 发表于 01-06 10:07 1171次阅读
    西门子TIA Portal如何比较两个<b class='flag-5'>浮点</b>数相等

    【RA-Eco-RA4E2-64PIN-V1.0开发板试用】RA4E2的DSP浮点性能的软件浮点测试和硬件浮点测试对比

    , atan,等等基本操作。 当然为了测试出硬件浮点运算性能,这里很有必要在测试一下软件浮点运算能力,方便做个测试对比,怎么做软件浮点运算呢? 这个可以使用开源Qfplib,这是国外
    发表于 12-30 17:55