欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

极品的C语言错误

发布时间:2025/5/22 编程问答 34 豆豆
生活随笔 收集整理的这篇文章主要介绍了 极品的C语言错误 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

 
     今天在测试硬件通信模块时候发现一个奇怪的问题,发送数据和接收数据进行比较复制时候频繁数据错误。

     测试流程如下:发送一个字节和接收一个字节,进行比较,当返回数据和发送数据不相等的时候,错误计数器累加。
数据收发抽象如下: uint16 i = 0; uint16 j = 0; uint32 error_num = 0; XX_send_data(i++);      j = XX_rece_data();     if(i != (j + 1)) { error_num++; } 这段代码按照理论上来说,只要发送数据i和接收数据一样,那错误计数器应该不会出错,但是实际上出错了,最开始怀疑是由于FPGA硬件模块数据发送和接收时序有问题,但是多次大批量功能仿真以及时序仿真都没问题。 这下我就开始怀疑这段短小的C程序是否工作正常,因此, 在error_num++这句话这里打断点,查看每次出错数据都是i=0,j=65535的时候出错,为什么会全部出错在这里呢? 百思不得其解,后来询问资深工程师飞哥,飞哥一看就看出问题出现在哪里了,让我汗颜呀!!~~ 原来错误是这样发生的:(程序运行在32位处理器) 这段程序从表面上看是没有任何问题的,但是细致分析就会发现,当i=65535发送数据,发送完成后执行i++,i此时变为0,j调用接收函数后,返回值正确也是65535,但是,那看来问题就出现在if(i != (j+1))这里了。 原来, j+1 这种算术运算的运算值是默认存到32寄存器中,因此j+1运算结果为32位数据,因此,当j=65535时候,(j+1)实则为65536,(0 != 65536),因此产生不匹配。错误码自加。 有很多种方法消除这种错误,修改代码如下即可解决问题。 uint16 i = 0;      uint16 j = 0;      uint32 error_num = 0;        XX_send_data(i++);      j = XX_rece_data();          if(i !=(uint16) (j + 1)) {           error_num++;      } 终于找到问题了,看来以后写代码还得仔细了,吸取教训。 // 看了回复,发现很多人都以纯软件的方式来理解这段代码,但是嵌入式C语言里面一定要详细和处理器行为结合起来,以下添加详细解释   这张截图为这段代码对应的汇编代码,详细阅读这段汇编代码即可找出问题所在。 第一句汇编代码ldhu r3,-10(fp)  意思为从内存或者cache中加载一个半字,并且扩展成无符号类型,这句话就是把变量i加载到寄存器R3中,R3为32位寄存器,这时候虽然变量i为uint16但是比较的时候还是变成了32位 第二句汇编代码ldhu r2,-12(fp)  同上一句话一样,这里是加载变量j到寄存器R2中 第三句汇编代码addi r2,r2,1    /*问题所在*/  这句话就是执行的j+1,可见结果是保存在r2中,r2为32位宽的寄存器,所以当i=0,j=65535时,j+1 = 65536并未溢出,而是直接赋值给r2,此时r2即为65536,r3为0 最后一句汇编代码 beq r3,r2,0x800258<main+92>这句话是比较r3和r2的值,如果相等就跳转到0x800258<main+92>这个地址执行程序。如果不相等就直接运行下一句语句,也就是error_num++ 从上面的分析看出,嵌入式行业一定要对处理器非常熟悉,出现些稀奇古怪的问题,才能最终找到问题所在。

转载于:https://www.cnblogs.com/linjie-swust/archive/2012/05/28/2522187.html

总结

以上是生活随笔为你收集整理的极品的C语言错误的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。