搜索
bottom↓
回复: 62

求助:MDK中 sprintf 输出浮点数据出错

  [复制链接]

出0入0汤圆

发表于 2009-3-26 13:56:53 | 显示全部楼层 |阅读模式
我采用的系统是LPC2214+IS25616 跑的UC/OSII 2.83 ,使用分散加载描述文件
LR_IROM1 0x00000000 0x00040000                                                                         ;; Load region
{
    ER_IROM1 0x00000000        0x00040000
    {
        vectors.o (VECT, +First)
        init.o (INIT)
        * (+RO)
    }
    RW_IRAM1 0x40000050     0x00002FC0                ;// Origination Point of Internal SRAM
    {                                  ;// 0x40000000 ~ 0x4000003F for Vector(Redundancy)
      
      os_core.o (+RW,+ZI)  
      ltc1606.o (+RW,+ZI)
      ;appPara.o (+RW,+ZI)
      app.o (+RW,+ZI)      
      ;  .ANY (+RW,+ZI)
    }     

    RW_RAM1 0x80000000 0x00060000  
        {  ; RW data
                   .ANY (+RW +ZI)
          }

    ARM_LIB_HEAP  0x80060000 EMPTY  0x00020000    {}   
    ARM_LIB_STACK 0x40004000 EMPTY -0x00001000   {}
}
用串口输出调试信息, 程序在添加全局变量的时候会出现sprintf 输出的浮点数不正常,要么是000.00格式或者是乱的数字中间添加很多0,前提是输出的浮点数值不是零,ULINK仿真时能看到内存中的数据正常。将新添加的全局变量转移到另外一个*.C文件中声明,sprintf的错误可能会消失。
再者,改变C代码的优化级别,sprinf输出浮点数出错的现象可能还会出现。在默认级别(2)中串口输出的字符串(通过sprintf先放到字符型数组中)正常的时候,换到级别(0),输出的浮点数就会出错。


麻烦大家给个建议,我该从什么地方去查这个错误原因,如何改正。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2009-3-26 13:58:55 | 显示全部楼层
//全局变量
char ErrOutStr[128];
float Voltage;
float Current;

//函数内部变量
int len;

len=0;
len+=sprintf(ErrOutStr+len,"Single:  %E    V@   %E    mA ,",(float)Voltage,(float)Current);

出0入0汤圆

 楼主| 发表于 2009-3-30 16:09:34 | 显示全部楼层
我遇到的这个问题跟代码优化还有影响,MDK优化级别如下,采用Level 0就会出错,采用Level 2出错的几率很小,目前的代码在Level 2下编译是通过的,在Level 0下sprintf()函数就不正常。
控制编译器的代码优化:
Default: 缺省情况下,使用编译器的默认设置或在目标或文件组上层选项对话框中的设置。
Level 0 (-O0): 关闭所有的优化,除了一些简单的源级转换。
Level 1 (-O1): 关闭掉那些严重影响调试的优化。
Level 2 (-O2): 生成完全的优化代码。由于目标代码到源代码的映射并不是很清晰,所以这样生成的代码可能会对调试有所影响。

会不会是我的编译环境那个参数的配置有问题,有遇到类似问题的给指点一下,谢谢

出0入0汤圆

 楼主| 发表于 2009-4-9 09:17:19 | 显示全部楼层
问题解决,UCOSII的任务堆栈没有8字节对齐,在声明任务堆栈时,强制8字节对齐就可以了,系统默认是4字节对齐,

出0入0汤圆

发表于 2010-5-16 12:06:20 | 显示全部楼层
呵呵,顶一下,也遇到类似问题,根据提示已经正常,多谢!

出0入0汤圆

发表于 2010-6-4 14:53:13 | 显示全部楼层
回复【3楼】shandong
问题解决,ucosii的任务堆栈没有8字节对齐,在声明任务堆栈时,强制8字节对齐就可以了,系统默认是4字节对齐,
-----------------------------------------------------------------------

三楼所说的强制8字节对齐是什么意思,能否解释一下,我也遇到这样的问题,输出打印浮点数是全为0,。

出0入0汤圆

 楼主| 发表于 2010-6-12 11:28:40 | 显示全部楼层
__align(8) static  OS_STK       AppTaskStartStk[APP_TASK_START_STK_SIZE];

出0入0汤圆

发表于 2010-6-13 19:41:07 | 显示全部楼层
楼主是怎么找到这个问题的,能分享么?

出0入0汤圆

发表于 2010-8-2 13:19:06 | 显示全部楼层
非常感谢,照您的思路,问题已解决,但是能否解释下其中的原因,这种错误跟字节对齐有什么关系?

出0入4汤圆

发表于 2010-10-6 15:43:46 | 显示全部楼层
我也遇到这个问题了,我用的是STM32,我的现象表现是使用sprintf处理浮点数时,系统就发生了HardFault中断,直接死在这个函数里面了。我不明白,为什么会发生“HardFault”

void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

按照楼主的方法已经解决,但不知道原因。

出0入0汤圆

 楼主| 发表于 2010-10-10 13:28:56 | 显示全部楼层
这个问题折磨我好几个月,后来是对比UC的堆栈格式参照MDK的手册,把毛病该好了,过去很久了,忘记了当时从那个文档中参考的了

出0入0汤圆

 楼主| 发表于 2010-10-10 13:43:13 | 显示全部楼层
沉了N久的帖子,竟然又浮起来了,看来遇到这个问题的朋友不少,对大家有帮助就好。

出0入0汤圆

发表于 2011-2-26 22:45:04 | 显示全部楼层


__align(8) static OS_STK stkMainTask[512];

OSTaskCreate(mainTask, (void *)0, &stkMainTask[sizeof(stkMainTask) / 4 - 1], 4);

加了对齐关键字,
在任务函数中调用还是出问题,在main()中调用sprintf输出浮点正常。

出0入0汤圆

发表于 2011-2-27 10:03:37 | 显示全部楼层
发现8字节对齐前后堆栈数组在SRAM中的地址分配没有变化(OS_STK 是 INT32U),开始地址是8的整数倍,元素脚标+1,地址+4

出0入0汤圆

发表于 2011-3-14 15:27:20 | 显示全部楼层
呵呵, 很幸运,刚出问题就搜到这个帖子了~~~~ 谢谢各位

出0入0汤圆

发表于 2011-5-10 21:46:31 | 显示全部楼层
不知道我的是不是也是这个问题,用的ti的cm3,用了ucos,老是出现faultIsr,明天去看看

出0入0汤圆

发表于 2011-5-25 10:47:14 | 显示全部楼层
非常经典的贴,解决了我的问题

出0入0汤圆

 楼主| 发表于 2011-6-1 19:07:05 | 显示全部楼层
类似问题在LPC1765 ucosii也出现了,这次堆栈字节对齐也没有用了。用的是ZLG的模板。请教过ZLG的技术支持也没解决,得到的答复是在MDK中不能调用sprintf函数。后来花了点时间把UCOS网站上的st的一个例程修改了一下,用在我的项目中,问题解决,具体原因我还没有找到,等有时间再找。

出0入0汤圆

发表于 2011-9-29 10:11:38 | 显示全部楼层
mark,我以前遇到过这问题

出0入0汤圆

发表于 2011-9-30 09:47:46 | 显示全部楼层
vsprintf吧,跟我以前出的问题一样。

出0入0汤圆

发表于 2011-11-21 09:46:56 | 显示全部楼层
MARK!!

出0入0汤圆

发表于 2011-12-30 15:39:10 | 显示全部楼层
目前也遇到这样子的问题了
double dblTemp;
dblTemp = 26.7;
使用JLink-8调试的时候看到,dblTemp:5.935375013444e-308;
sprintf(acBuffer, "%f", dblTemp);
输出即为0

出0入0汤圆

发表于 2011-12-30 15:55:16 | 显示全部楼层
我的问题刚开始的时候以为是uCOS任务堆栈太小了,但是开到了4096,还是不行,所以如下添加:
__align(8) static OS_STK AppTaskXXXStk[4096];
就可以了。
正在疑惑中,以下是网络上摘录的,应该是数据对其问题。
昨天跟一个朋友讨论一个问题:

float n1=3.0;
double n2=3.0;
long n3=2000000000;
long n4=1234567890;
printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);


在x86 32位机上执行,输出结果是:0 1074266112 0 1074266112
按照我的理解,float和long在32位机下都占4个字节,即使无法格式化为long进行输出,后面的值也不至于都出问题。


实际里面涉及以下的知识,
1. 把上面的代码反汇编可以看到:
mov    0x80494b4,%eax
mov    %eax,0x18(%esp)
mov    0x80494b0,%eax
mov    %eax,0x14(%esp)
fldl   0x80494a8
fstpl  0xc(%esp)
flds   0x80494a0
fstpl  0x4(%esp)
movl   $0x8048478,(%esp)
call   0x804828c <printf>
我先后把这几个变量定义成了局部和全局的进行了测试,这段是用全局的汇编码。
关键是这几句:
fldl   0x80494a8
fstpl  0xc(%esp)
flds   0x80494a0
fstpl  0x4(%esp)
fldl把浮点地址交给浮点运算寄存器,浮点寄存器是64为精度的,然后fstpl再把值取出按照64位入栈,表象就是按照double类型入栈了。所以虽然内存中单精度浮点数是以4字节存储的,但编译器把它转成了8字节进行处理。
所以最后在栈里的存储就成了
| 00 00 00 00 |<--ESP
| 40 40 00 00 |
| 00 00 00 00 |
| 40 40 00 00 |
| 49 96 02 d2 |
| 77 35 94 00 |<--EBP


2. printf的处理方式是将输入参数按照字符串进行格式化解析,由于输入的是ld ld ld ld,按照4字节依次进行取值,就得到了上面的结果。


3. float是单精度浮点,遵从IEEE754, S(1)-E(8)-M(23)。3二进制位11,表示为:1.1×2^1 => 指数部分127+1=128-


>10000000,小数部分为1,因此其浮点表示为:
0 10000000 10000000000000000000000,也就是上面1中看到的0x40400000,打印出的十进制就是1074266112。

出0入0汤圆

发表于 2011-12-31 01:00:13 | 显示全部楼层
其实就是地址越界的问题:如果一个字符串在地址0处(0x10,20,30)截断了str函数就出错了,所有的str函数都是这样的

出0入0汤圆

发表于 2012-3-28 19:19:50 | 显示全部楼层
也遇到类似的问题了,mdk中double无法作为局部变量,没办法一直用全局变量代替的,研究下大家的方法有用否

出0入0汤圆

发表于 2012-7-3 15:53:14 | 显示全部楼层
vsprintf

__align(8) static  OS_STK       AppTaskStartStk[APP_TASK_START_STK_SIZE];

...对齐就好用了。
看来还有很多要学的。
23楼解释很到位..

出0入0汤圆

发表于 2012-7-12 10:29:04 | 显示全部楼层
曾几何时,也遇见了这样的问题,郁闷了很久,后来干脆自己想办法写程式转换~~~

出0入0汤圆

发表于 2012-7-14 09:09:59 | 显示全部楼层
不错,学习

出0入0汤圆

发表于 2012-10-23 16:37:59 | 显示全部楼层
你好,我也是在mdk中ucos系统中snprintf输出浮点数死机,按照那您的解决方法字节对齐还是不能解决,请问您还有别的解决方法吗?谢谢!!

出0入0汤圆

发表于 2012-10-23 17:32:09 | 显示全部楼层
shandong 发表于 2011-6-1 19:07
类似问题在LPC1765 ucosii也出现了,这次堆栈字节对齐也没有用了。用的是ZLG的模板。请教过ZLG的技术支持也 ...

请问LPC1765+UCOS的snprintf不能输出浮点数的问题找到没有?谢谢!

出0入0汤圆

 楼主| 发表于 2012-10-24 16:49:46 | 显示全部楼层
放弃ZLG的移植的UCOS模板

出0入0汤圆

发表于 2012-10-31 20:21:13 | 显示全部楼层
太好了 问题解决了

出0入0汤圆

发表于 2012-12-21 12:35:44 | 显示全部楼层
不会都是地址越界产生的问题吧???

出0入0汤圆

发表于 2013-5-3 15:08:15 | 显示全部楼层
我的也出现这个问题,但是按照楼主修改还是不行。为什么呢?

出0入0汤圆

发表于 2013-5-3 15:17:24 | 显示全部楼层
RadioDisney 发表于 2011-2-26 22:45
__align(8) static OS_STK stkMainTask[512];

OSTaskCreate(mainTask, (void *)0, &stkMainTask, 4);

我的也是这样啊,加了后没有效果。还是一样会进hardfault

出0入0汤圆

发表于 2013-5-9 14:45:21 | 显示全部楼层
我也遇到了这个问题
只要是调用 sprintf(),里面出现%f 就进hardfault中断 (注:没有操作系统,裸奔的,改成8字对齐也没用,stack 和 heap 设成4096了,还是不行)

出0入0汤圆

发表于 2014-3-10 15:48:01 | 显示全部楼层
这个问题还没有彻底解决,盼高手出现。。。

出0入4汤圆

发表于 2014-4-17 12:16:12 | 显示全部楼层
bruce_helen 发表于 2014-3-10 15:48
这个问题还没有彻底解决,盼高手出现。。。

编译器 use microLIB 去掉 应该就OK了吧

出0入0汤圆

发表于 2014-4-17 18:15:33 | 显示全部楼层
acmilannast 发表于 2014-4-17 12:16
编译器 use microLIB 去掉 应该就OK了吧

没有用,能试的方法都试了。最后都没解决。
最近发现使用FreeRTOS就没这个问题,打印浮点数稳稳的。估计跟OS的底层堆栈操作有关。

出0入0汤圆

发表于 2014-4-26 15:28:17 | 显示全部楼层
我的环境是ucosii,8字节对齐后确实可以了

出0入0汤圆

发表于 2014-6-6 14:51:59 | 显示全部楼层
留名,技术贴

出0入0汤圆

发表于 2014-7-12 16:04:53 | 显示全部楼层
问题解决了 ,真是太好了 ,谢谢 楼主 无私的分享

出0入0汤圆

发表于 2014-9-10 15:09:01 | 显示全部楼层
谢谢楼主,找到解决办法了

出0入0汤圆

发表于 2014-9-17 10:23:43 | 显示全部楼层
bruce_helen 发表于 2013-5-3 15:17
我的也是这样啊,加了后没有效果。还是一样会进hardfault

请问 是否 使用了 static 变量?

我用ucos  在中断中加了 static变量就不能输出浮点 注销掉static就ok

出0入0汤圆

发表于 2014-9-17 11:05:18 | 显示全部楼层
street 发表于 2014-9-17 10:23
请问 是否 使用了 static 变量?

我用ucos  在中断中加了 static变量就不能输出浮点 注销掉static就ok ...

忘了,但是加不加static有什么影响么?

出0入0汤圆

发表于 2014-9-17 12:00:44 | 显示全部楼层
哦 ,你当时怎么解决的?
我现在遇到的问题是:sprintf 如果在其他文件中使用了static 变量,该文件没有在main中include。无任何引用,sprintf 对浮点数转换就不成功,输出0.00,但是可以输出整型。
删除掉static,输出正常。 编译器是 stm32 MDK。

出0入0汤圆

发表于 2014-9-17 22:06:39 | 显示全部楼层

呵呵,顶一下,

出0入0汤圆

 楼主| 发表于 2014-9-24 14:55:29 | 显示全部楼层
这么老的一个帖子又被翻出来了,看来还是有人跟我当初一样,走了弯路。细节很重要,近期要开始磊代码了。

出0入0汤圆

发表于 2014-10-8 09:47:17 | 显示全部楼层
问题解决了 ,真是太好了 ,谢谢 楼主 无私的分享

出0入0汤圆

发表于 2014-11-17 10:15:44 | 显示全部楼层
技术贴,必须要留名~~

出0入0汤圆

发表于 2015-3-18 08:52:39 | 显示全部楼层
解决我的问题了

出0入0汤圆

发表于 2015-4-25 10:51:06 | 显示全部楼层
非常感谢,用了ucos在计算float时总是出错,现在问题算是解决了

出0入0汤圆

发表于 2015-5-18 22:15:31 | 显示全部楼层
谢谢楼主   

出0入0汤圆

发表于 2015-5-19 08:58:42 | 显示全部楼层
总算清楚一点优化级别不同的影响了。

出0入0汤圆

发表于 2015-5-19 09:31:00 | 显示全部楼层
本帖最后由 ilcvm 于 2015-5-19 09:45 编辑

是堆栈8字节对齐问题  http://infocenter.arm.com/help/i ... 205ic/Cacbjbad.html
CM3提供自动对齐功能,启动时配置STKALIGN位即可。STM32下的具体操作代码是
SCB->CCR |= 0x200;


出0入10汤圆

发表于 2015-6-19 23:33:52 | 显示全部楼层
今天用snprintf也遇到这个问题了

出0入0汤圆

发表于 2015-8-12 17:15:53 | 显示全部楼层
shandong 发表于 2009-4-9 09:17
问题解决,UCOSII的任务堆栈没有8字节对齐,在声明任务堆栈时,强制8字节对齐就可以了,系统默认是4字节对 ...

请问为啥要8字节对齐呢?

出0入0汤圆

 楼主| 发表于 2015-8-12 17:40:19 | 显示全部楼层
可能跟系统的存取指令有关系,没有深入研究,见谅

出0入0汤圆

发表于 2015-11-28 01:18:20 | 显示全部楼层
给楼主32个赞!!!!!找了好久了!

出0入0汤圆

发表于 2017-4-28 11:14:46 | 显示全部楼层
我用的是ucos-ii,新增了两个消息队列后,用printf输出浮点数就出问题了,不管实际值是多少输出全部是0.000。起初以为是任务栈分配太小的缘故,改动后发现不是这个的问题。把两个消息队列去掉后,printf就能正常输出浮点数。
今天看到这个帖子,并且根据楼主的介绍改了以后就正常了。

出0入0汤圆

发表于 2018-8-13 20:39:38 | 显示全部楼层
....感谢分享,UCOSII遇到。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 14:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表