This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F280049:为什么这个转换是必需的?

Guru**** 2927270 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1376798/tms320f280049-why-is-this-cast-necessary

器件型号:TMS320F280049

工具与软件:

鉴于这种"简单"的代码截短:

if ( meta_data_size_announced != (uint16_t)(MIN_META_DATA_SIZE + name_size_from_meta_data() + custom_meta_data_size_from_meta_data() ) )
{
    return reset_state();
}

为什么需要以上的转换(uint16_t 为!=运算符的右侧)? 我在!=运算符的左侧和右侧有值31、并期望该表达式产生 false、即使没有该转换也是如此。

MIN_META_DATA_SIZE 定义为:

#define MIN_META_DATA_SIZE ( \
     1 /* Firmware Name Size */ \
  +  1 /* Firmware Major Version */ \
  +  1 /* Firmware Minor Version */ \
  +  2 /* Firmware Type */ \
  +  2 /* Hardware Type */ \
  +  8 /* Device ID */ \
  +  8 /* Flags / Reserved */ \
  +  4 /* Custom Meta Data Size */ )

`NAME_SIZE_FROM_META_DATA ()`和`CUSTOM_META_DATA_SIZE_FROM_META_DATA ()`声明如下:

static size_t name_size_from_meta_data(void);
static uint32_t custom_meta_data_size_from_meta_data(void);

`meta_data_size_announced`是 uint16_t 类型的静态变量 `NAME_SIZE_FROM_META_DATA`在给定情况下返回4、`custom_meta_data_SIZE_FROM_META_DATA ()`返回0。

除了添加上述转换、我还找到了其他几种方法来获得所需的结果:

-禁用优化(而不是 --opt_level=4)

-删除对 `custom_meta_data_size_frome_meta_data ()`的调用

-使用另一个编译器,如 clang

我看到效果、用 20.2.2和 22.6.0版本的 TI 编译器。

提前感谢、此致、

Torsten

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Torsten:

    一般情况下、铸件通常用于此类情况、以确保正确进行比较(本质上、确保您将苹果与苹果进行比较)。 在这种情况下、由于"meta_data_size_announced"定义为 uint16_t 类型、因此比较的另一侧应转换为与之匹配。  

    转换内容由"min_meta_data_size"、"name_size_frome_meta_data()"返回的 size_t 类型以及从"custom_meta_data_size_frome_meta_data()"返回的 uint32_t 类型组成。 当这些值一起使用时、它们可能受整数提升规则的约束(也就是说、不会得到 unint16_t out)。

    不同的编译器/优化会以不同的方式处理这些情况、但转换可以明确确保使用两个 uint16_t 值来避免任何疑问并保持一致性。  

    此致、

    Allison

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Allison、

    但是、在什么规则下、是否允许编译器比较31和31是不同的? 通常、编译器应应用隐式转换以找到可以使用的运算符!=的实现。 那么、什么隐式转换可以将31转换为不等于31的值呢?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我怀疑编译器出了问题。  这样的情况通常会打开一些很容易被忽略的小细节。  在这种情况下、对于包含问题比较的源文件、 请按照 如何提交编译器测试用例一文中的说明进行操作

    谢谢。此致、

    -George.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、George:

    感谢您的参与。 请查看随附的源文件的预处理器输出、其中包含有问题的代码行。 如果当前注释掉的转换为 uint16_t 没有注释掉、或者未应用优化、行2285可以正常工作。 源文件翻译如下:

    /Applications/ti/ti-cgt-c2000_22.6.0.LTS/bin/cl2000 --compile_only --c_file=/Users/todi/bootloader/c2000/bootloader/meta_data.c -DAPPLICATION_BEGIN_ADDR=0x00082000 -DAPPLICATION_FLASH_SIZE=0x1dff8 -DAPP_STARTUP_DELAY=2000 -DBOOTLOADER_KEY_ADDR=0x08000A -DCAN_BAUDRATE=1000000 -DCAN_BAUDRATE_1000000=1 -DCAN_MESSAGE_ID=256 -DCAN_MESSAGE_ID_SIZE=3 -DCPU1=1 -DCROSSCOMPILING=1 -DCRYPTO_IV_LENGTH=96 -DCRYPTO_KEY_LENGTH=128 -DCRYPTO_SUPPORT=1 -DCRYPTO_SUPPORT_CLIENT_LIB=1 -DDEVICE_NAME=f28004x -DEXTERNAL_OSCILLATOR_FREQUENCY=20000000 -DHAS_DRIVER_LIB -DMAX_APPLICATION_FLASH_SIZE=0x1DFF8 -DPROJECT_VERSION_MAJOR=1 -DPROJECT_VERSION_MINOR=7 -DTARGET_MC_FAMILY_F28004X=1 -DTORROX_BOOTLOADER_NAME=c2000 -DVALUE_OF_UNUSED_FLASH_MEMORY_BYTE=0xff -D_FLASH --include_path=/Users/todi/bootloader/c2000/drivers --include_path=/Users/todi/bootloader/library --include_path=/Applications/ti/c2000/C2000Ware_5_02_00_00/device_support/f28004x/common/include --include_path=/Applications/ti/c2000/C2000Ware_5_02_00_00/device_support/f28004x/headers/include --include_path=/Applications/ti/c2000/C2000Ware_5_02_00_00/driverlib/f28004x/driverlib --include_path=/Users/todi/bootloader/c2000/client_lib --include_path=/Applications/ti/ti-cgt-c2000_22.6.0.LTS/include --silicon_version=28 --large_memory_model --unified_memory --cla_support=cla1 --float_support=fpu32 --fp_mode=relaxed --tmu_support=tmu0 --vcu_support=vcu2 --display_error_number --symdebug:dwarf --c99 --gen_func_subsections --gen_data_subsections=on --opt_level=4 -DNASSERT --preproc_with_comment --preproc_with_compile --output_file=CMakeFiles/bootloader.out.dir/meta_data.c.obj

    谢谢、此致、

    Torsten

    e2e.ti.com/.../meta_5F00_data.pp.txte2e.ti.com/.../meta_5F00_data.c.obj.txt

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您提供测试用例。  我仍然无法解释发生了什么。  我使用了构建选项、并添加了 -- src_interlist .  这使编译器保留生成的汇编文件、并在其中添加注释、以便更易于理解。  下面的附件是汇编文件的一小部分、重点介绍问题发生的位置。  请注意、我无法运行代码。  我检查一下、首先是基于您的上述描述的假设。  其中一个假设是该函数 READ_UINT32 返回0。  这一推定是否正确?

    谢谢。此致、

    -George.

    e2e.ti.com/.../file.asm

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,`custom_meta_data_size_frome_meta_data ()`只是转发到`read_uint32 ()`,它在具体示例中返回0。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    遗憾的是、我找不到编译器生成的代码有任何问题。  下面的附件类似于上次的附件。  但我在开头添加了一个注释块、说明了3种假设。  在汇编指令中、我添加了注释、它们始终以开头 ;;;; .  下面是一个例子...

        MOVZ      AR5,*+XAR4[0]         ; [CPU_ALU] |2284| 
    	;;; AR5 = 4
    

    这意味着、在该指令完成执行后、寄存器 AR5包含值4。  它以...结束。

        B         $C$L31,EQ             ; [CPU_ALU] |2284| 
    	;;; Branch taken
    

    但事实并非如此。  采用此条件分支。  控制返回到下一条指令。  这不是预期的行为。  这意味着,在途中的某个地方,这些指令不符合我所描述的。  回想一下、我无法执行代码。  但您可以这么做。  请单步执行这些说明、并告诉我我的第一个意见是错误的。

    谢谢。此致、

    -George.

    e2e.ti.com/.../0181.file.asm

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、George:

    我单步执行代码后发现 ,末尾的`read_uint32()`仅返回0 ,当被转换为 uint16_t 时 如果没有这个符号、该函数返回0x01000000。 此函数在 PC (sizeof (uint32_t)=4)上非常精确地发挥作用、但在 C2000上不能找到、如果我回答正确、相同的表达式会生成2。

    static uint32_t custom_meta_data_size_from_meta_data(void)
    {
        size_t size_pos = MIN_META_DATA_SIZE - sizeof( uint32_t );
        assert( meta_data_size == MIN_META_DATA_SIZE );
    
        return read_uint32_t( &meta_data[ size_pos ] );
    }
    

    我目前不理解的唯一一件事就是为什么这在没有优化的情况下工作。 但最有可能的是,我也做了一些愚蠢的事情。

    非常感谢您的大力支持!

    此致

    Torsten

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不确定函数是什么 custom_meta_data_size_frome_meta_data 用于计算。  但这里对问题有一种猜测。   考虑一下当您将公里数和英里数混在一起时会发生什么情况。  我怀疑两者之间会出现类似的情况 MIN_META_DATA_SIZE 大小 .  。 大小 运算符返回类型的大小(以数字表示) 字符 -宽单位。  在 C28x 上、A 字符 因此为16位 sizeof (uint32_t) 2。  考虑将其更改为在位方面有效。  有点像……

    (MIN_META_DATA_SIZE_IN_BITS - sizeof (uint32_t)* char_bit)/char_bit

    char_bit 在标准头文件中定义的 limits.h .  是类型的位数 字符 .  在大多数编译器上、它是8。  但在 C28x 上为16。

    谢谢。此致、

    -George.

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是一个很好的建议!