以此篇开始,记录项目开发过程中遇到的一些觉得有意思、值得记录的问题。一是供大家做个小参考,二是以后再遇到类似问题,能够快速的解决。
最近同事反馈我一个Rte传输问题,让我帮忙看看。一个Int16类型变量从应用层赋值6,传输到底层的Float32变量,通过CANAPE观测到底层变量的值是奇怪的8.4078E-45。
听到这个背景描述,觉得很有意思,一般来说从int转换成float是会存在精度损失的问题,但不会出现以上这种奇怪的现象。所以我拿到代码,用UDE开始调试起来。因为我是搞底层的,所以我习惯性的先从底层开始往上顺藤摸瓜,定位到Rte以下传输没问题,是应用层组件传输给RTE的时候出问题了。代码大致如下:
ModuleA.h:
extern float AswModeReq;
ModuleA.c:
#include "Module.h"
#define Rte_Write_ModeReq(data) ((Rte_Rx_ModeReq = data), RTE_E_OK)
VAR(Float32, RTE_DATA) Rte_Rx_ModeReq;
void main(void)
{
(void)Rte_Write_ModeReq(AswModeReq);
}
ModuleB.h:
extern Int16 AswModeReq;
ModuleB.c:
#include "ModuleB.h"
Int16 AswModeReq = 6;
刚开始没注意到AswModeReq这个变量定义和声明在不同的模块里,用UDE调试,汇编代码长这样:
感觉哪里不太对劲,然后自己仿照也写了段测试代码,结果值是对的,汇编长这样:
一对比,明白了。第一个没有进行数据类型转换(也就是汇编没有ITOF动作:整形转换成浮点型)。然后将我将十六进制的6以float形式表示,转换如下图:
刚好数据能对上。
然后自己再仔细检查下代码才发现,代码这样写的:模型A声明float类型变量,模型B里定义这个变量但它是整形,而且两个模型还没包含关系,编译器竟然也没报错和警告。。。
后面向Tasking供应商确认了,编译器确实不能识别声明和定义不一致。看来有时候用工具进行静态代码检查还是很有必要的。
总结:模型A声明float类型变量M,模型B里面给变量M定义为int并赋值为6,模型A使用时,编译器将M当成float类型,所以汇编没有ITOF。十六进制的6表示成float形式就是8.4078E-45。