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
    +关注

    关注

    146

    文章

    16022

    浏览量

    343680
  • 恩智浦
    +关注

    关注

    14

    文章

    5715

    浏览量

    100782

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

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

收藏 人收藏

    评论

    相关推荐

    verilog语音实现浮点运算

    Verilog可以通过使用IEEE标准的浮点数表示来实现浮点运算。下面是一个基本的Verilog模块示例,展示了如何进行加法、乘法和除法等常见的浮点运算操作: module
    发表于 03-25 21:49

    一文带你秒懂IEEE 754浮点

    一、简介1、常见的浮点数表示方式是IEEE754标准,它规定了浮点数的存储格式和运算规则,这个标准定义了两种浮点数表示:单精度和双精度。2、任何一个浮点数的二进制数可以写为:NUM
    的头像 发表于 03-18 08:09 925次阅读
    一文带你秒懂IEEE 754<b class='flag-5'>浮点</b>数

    使用的H7系列MX编写代码后生成静态文件,如何更改静态工程也使用硬件双精度浮点数?

    使用的H7系列MX编写代码后生成静态文件, 在调用该静态文件并编译报错,如下: 然后我查看了静态工程的编译指令: 而APP程序的编译指令: 想请教一下,该如何更改静态工程
    发表于 03-12 06:15

    stm32f407浮点运算速度

    支持硬件浮点运算单元(FPU),可以提供快速和高效的浮点运算性能。本文将详细介绍 STM32F407 的浮点运算速度。 浮点运算是很多应用中常用的一种运算类型,特别是对于需要进行较复杂
    的头像 发表于 01-04 10:58 1267次阅读

    modbus浮点数怎么读取

    Modbus是一种通信协议,常用于工业自动化系统中的设备之间的通信。它支持多种数据类型,包括整数、浮点数、字符串等。浮点数在工业领域中广泛应用,因此了解如何读取和处理Modbus浮点数是非
    的头像 发表于 12-28 14:38 1707次阅读

    浮点LMS算法的FPGA实现

    引言 LMS(最小均方)算法因其收敛速度快及算法实现简单等特点在自适应滤波器、自适应天线阵技术等领域得到了十分广泛的应用。为了发挥算法的最佳性能,必须采用具有大动态范围及运算精度的浮点运算,而浮点
    的头像 发表于 12-21 16:40 308次阅读

    单精度和双精度浮点数的区别

    单精度和双精度是计算机中表示浮点数的两种不同的精度。在计算机中,浮点数用来表示带有小数部分的实数,而单精度和双精度用来表示浮点数的精确程度不同。在以下文章中,我将详细介绍单精度和双精度浮点
    的头像 发表于 12-15 10:25 2607次阅读

    单精度和双精度浮点数的区别

    在计算机科学和数值计算中,浮点数是一种用于表示实数的数据类型。浮点数有两种精度级别:单精度和双精度。这两种精度级别在表示范围、精度和存储空间等方面都有所不同。本文将详细介绍单精度和双精度浮点数的区别
    的头像 发表于 12-13 10:55 1523次阅读

    圆形连接器选型:几个容易让人“困惑”的术语

    圆形连接器选型:几个容易让人“困惑”的术语
    的头像 发表于 12-06 18:11 476次阅读
    圆形连接器选型:几个容易让人“<b class='flag-5'>困惑</b>”的术语

    ARM编译器ARM C和C++浮点支持用户指南

    ARM浮点环境是二进制浮点算术的IEEE 754-1985标准的实现。 ARM系统可能具有: ·VFP协处理器。 ·没有浮点硬件。 如果您为具有硬件VFP协处理器的系统进行编译,则ARM编译器会利用
    发表于 08-16 07:36

    RealView编译工具浮点支持指南

    ARM体系结构的应用程序二进制接口(ABI)是一系列规范,描述了将源程序转换为目标文件的特定于处理器的方面。 任何符合ABI相关方面的工具链生成的对象文件都可以链接在一起,以生成最终的可执行映像或
    发表于 08-12 07:27

    C浮点数与字符转换工具

    C浮点数与字符转换工具免费下载。
    发表于 06-19 18:17 0次下载

    在FPGA上优化实现复数浮点计算

    点击上方 蓝字 关注我们 高性能浮点处理一直与高性能 CPU 相关联。在过去几年中,GPU也成为功能强大的浮点处理平台,超越了图形,称为GP-GPU(通用图形处理单元)。新创新是在苛刻的应用中实现
    的头像 发表于 06-10 10:15 403次阅读
    在FPGA上优化实现复数<b class='flag-5'>浮点</b>计算

    浮点加法是如何计算的

    嗨!我试着写点关于浮点数的东西,我发现自己对这个 64 位浮点数的计算方法很好奇:     >>> 0.1 + 0.2 0.30000000000000004 我意识到我并没有完全理解它是如何计算
    的头像 发表于 05-26 15:26 687次阅读

    esp8266的哪个Modbus RTU可以获得大约32位浮点实数?

    1. 有谁知道 esp8266 的哪个 Modbus RTU 可以获得大约 32 位浮点实数 2. 我有一个通过 modbus rtu 通信并返回 4 字节真实数据的传感器 2.494E+9 如何将其转换为浮点数符合 IEEE
    发表于 05-08 08:14