尊敬的 TI 专家:
在花了一些时间调试我的源代码之后、我有理由怀疑 CL2000编译器可能在优化内联函数时会出现错误。
我将尽我所能描述这种奇怪的行为,希望你能证实或反对我的怀疑。
请务必注意、这是一个非常具体的情况、并且对源代码的任何更改 都很可能会使错误"不可见"、即一切似乎都正常运行。
然而,这并不否认存在一个错误, 我想解决这个问题, 希望它将在未来的一些版本中得到解决。
我已经附加了复制所讨论的行为所需的源文件、我将尝试解释特定代码片段背后的逻辑。
首先、在 C 源代码中、我们调用一个 从外设接口(EMIF)读取连续存储器位置的内联函数。 (fpga_values.c、第74行)
/* in header file */
inline static void ElFunc_MEMRD8_L(int32_t address, uint16_t n1, uint16_t n2, uint16_t n3, uint16_t n4, uint16_t n5, uint16_t n6, uint16_t n7, uint16_t n8, int32_t* value1, int32_t* value2, int32_t* value3, int32_t* value4, int32_t* value5, int32_t* value6, int32_t* value7, int32_t* value8){
*value1 = (MEMRD_HWREG_L(address) << n1);
*value2 = (MEMRD_HWREG_L(address + 1 * MEMRD_ADDR_L) << n2);
*value3 = (MEMRD_HWREG_L(address + 2 * MEMRD_ADDR_L) << n3);
*value4 = (MEMRD_HWREG_L(address + 3 * MEMRD_ADDR_L) << n4);
*value5 = (MEMRD_HWREG_L(address + 4 * MEMRD_ADDR_L) << n5);
*value6 = (MEMRD_HWREG_L(address + 5 * MEMRD_ADDR_L) << n6);
*value7 = (MEMRD_HWREG_L(address + 6 * MEMRD_ADDR_L) << n7);
*value8 = (MEMRD_HWREG_L(address + 7 * MEMRD_ADDR_L) << n8);
return;
}
/* in .c source file */
ElFunc_MEMRD8_L(FPGA_ADC1_A0_LSW, 0, 0, 0, 0, 0, 0, 0, 0, &A0_LSW, &A1_LSW, &B0_LSW, &B1_LSW, &C0_LSW, &C1_LSW, &D0_LSW, &D1_LSW);
在该函数后面的某些行中、我们有另一个内联函数、该函数仅将 int32_t 变量转换为 float32_t、如下所示:(fpga_values.c、 第79行)
/* in header file */
inline static float32_t ElFunc_INT32FLP(int32_t input){
return (float32_t)input;
}
/* in .c source file */
...
AIN04_FLP = ElFunc_INT32FLP(B1_LSW);
...
现在、当使用优化 O2时会发生该问题。
506 .dwpsn file "FPGA_values.h",line 45,column 5,is_stmt,isa 0
507 0000004a 8F38 MOVL XAR4,#3671270 ; [CPU_ARAU] |45|
0000004b 04E6
508 0000004c 8AC4 MOVL XAR4,*+XAR4[0] ; [CPU_ALU] |45|
509 0000004d A800! MOVL @||B1_LSW||,XAR4 ; [CPU_ALU] |45|
510 .dwpsn file "FPGA_values.h",line 34,column 3,is_stmt,isa 0
511 0000004e E2AF MOV32 R2H,*+XAR4[0] ; [CPU_FPU] |34|
0000004f 02C4
512 .dwpsn file "FPGA_values.h",line 46,column 5,is_stmt,isa 0
513 00000050 8F38 MOVL XAR4,#3671272 ; [CPU_ARAU] |46|
00000051 04E8
514 .dwpsn file "FPGA_values.h",line 34,column 3,is_stmt,isa 0
515 00000052 E689 I32TOF32 R2H,R2H ; [CPU_FPU] |34|
00000053 0012
在"fpga_values.lst"文件中、在标有507的行(文件中的第581行)上、我们可以看到 XAR4加载了#3671270 (0x3804E6)、 在@508和509 (文件中为583和584)行中、我们可以看到、该存储器位置的值被存储在 XAR4中、之后存储在 Δ I B1_LSW 中。 这正是我们需要的。
问题出在下一条(FPU)指令中。 在第511行(文件中为586)、编译器认为寄存器 XAR4仍有一个地址、并尝试向寄存器 R2H 加载该地址的值。 这种假设是完全错误的、因为此时寄存器 XAR4不再包含地址、而是包含在行508 (文件中为583)上读取的真实值。 看看源代码,正确的指令应该是 MOV32 RH2、XAR4或 MOV32 RH2、@|b1_lsw||或类似这些行的内容。
其余的代码似乎可以正常运行(将 RH2寄存器置为浮点等)、但将错误的值存储在有问题的行(511/file 584)上、很容易引起硬故障和 NMI、当然会产生错误的结果。
在文件 CL2000_TMS320F28388D.bat 中、您可以看到编译器选项(我尝试了版本22.6.0和22.6.1、但结果相同)。 您还可以使用此脚本编译源文件。
我想补充一点、这个测试用例是手动调整的软件生成的 C 代码(因此是"奇怪"的编码标准)的结果。 我们使用可生成 C 源文件的图形编程软件、这是内联函数(和优化)对我们至关重要的主要原因。
我们期待收到您的回复、
桑德罗·马格塔