ZHCUCF7 October   2024 TMS320C28341 , TMS320C28342 , TMS320C28343 , TMS320C28343-Q1 , TMS320C28344 , TMS320C28345 , TMS320C28346 , TMS320C28346-Q1

 

  1.   1
  2.   摘要
  3.   商标
  4. 1简介
  5. 2C28 到 C29 的 CPU 迁移
    1. 2.1 用例
    2. 2.2 主要差异
    3. 2.3 源代码迁移
      1. 2.3.1 C/C++ 源代码
        1. 2.3.1.1 pragma 和属性
        2. 2.3.1.2
        3. 2.3.1.3 内联函数
        4. 2.3.1.4 内联汇编
        5. 2.3.1.5 关键字
        6. 2.3.1.6 数据类型差异
        7. 2.3.1.7 迁移工具支持
      2. 2.3.2 汇编语言源代码
    4. 2.4 工具链迁移
      1. 2.4.1 编译器
      2. 2.4.2 链接器
      3. 2.4.3 CCS 工程迁移
  6. 3CLA 到 C29 的 CPU 迁移
    1. 3.1 用例
    2. 3.2 主要差异
    3. 3.3 源代码迁移
      1. 3.3.1 C/C++ 源代码
        1. 3.3.1.1 数据类型差异
        2. 3.3.1.2 迁移 CLAmath.h 函数和内联函数
        3. 3.3.1.3 将 C28 和 CLA 迁移到相同的 C29 CPU
        4. 3.3.1.4 将 C28 和 CLA 迁移到不同的 C29 CPU
      2. 3.3.2 汇编语言源代码
    4. 3.4 工具链迁移
  7. 4参考资料

数据类型差异

数据类型差异 - 表 2-2 中总结并突出显示了此上下文中的主要差异。

表 2-2 数据类型主要差异
类型 C28 CLA C29 ARM
char 16 16 8 8
short 16
int 16 32 32 32
long 32
long long (COFF) 64 32

不适用

64
long long (EABI) 64
float 32
double (COFF) 32 32

不适用

64
double (EABI) 64
long double (COFF) 64 32

不适用

64
long double (EABI) 64
指针 32 16 32 32

用户需要特别注意数据类型:

  1. int(C28 16 位与 C29 32 位)- 如果用户代码出现“int”,建议使用以下方法进行迁移:
    1. 将用户代码中出现的所有“int”更改为固定宽度类型 int16_t。这可确保代码中没有任何中断,并且保留了原始数据宽度。
      1. C29 编译器有一个名为 c29clang-tidy 的工具,用于检查是否出现“int”和“unsigned int”,此处对该工具进行了讨论(在 c29migration-c28-int-decls 下)
    2. 理想场景 - 用户代码中未出现任何“int”,仅包含可移植的固定宽度类型,如 int16_t、int32_t。在这种情况下,不进行任何更改即可移植代码。
  2. char(C28 16 位与 C29 8 位)- 如果用户代码出现“char”,或者出现“int8_t”或“uint8_t”:
    1. 一开始,将所有出现的“char”更改为“int16_t”可能就像迁移方法那样,因为它会保留用户原始代码中存在的位宽。但这可能会导致意外的构建时问题,更糟糕的是,会导致难以检测运行时故障。这是因为,不同类型的指针混叠是不合法的。但是 char 比较特殊,可与其他指针类型混叠。换句话说,可以通过指向 char 的指针访问任何对象。如果现在将 char 更改为 int16_t,就会违反 char 独自拥有的这一“特权”。
    2. 因此,建议的迁移方法是不对代码进行任何更改,或者最好是将用户代码中出现的所有“char”都更改为“int8_t”。即便是这种方法,也会导致出现一些问题:
      1. 如果用户代码中出现“char”,但实际存在 16 位依赖关系,则需要将其更改为 int16_t。例如,分配的数据超出 8 位范围,需要 16 位范围。C29 编译器有一个名为 c29clang-tidy 的工具,用于检查对“char”类型表达式的运算是否超出了 8 位类型的范围,此处对该工具进行了讨论(在 c29migration-c28-char-range 下)
      2. 如果用户代码包含指向“char”的指针和相关偏移,或针对此类指针的算术运算。C29 编译器有一个名为 c29clang-tidy 的工具,用于检查基于 char/int 的指针的指针算术运算,其位跨度在 C28 到 C29 之间变化,此处对该工具进行了讨论(在 c29migration-c28-types 和 c29migration-c28-suspicious-dereference 下)。
      注: 请注意,将“char”更改为“int8_t”后,指针混叠不是问题。
  3. 数据类型差异导致的 sizeof() 差异 - 表中对此进行了总结,这些差异会导致使用标准库函数调用时出现行为差异:
    sizeof(char) sizeof(short) sizeof(int) sizeof(long)
    C28 1 1 1 2
    C29 1 2 4 4
    1. 如果使用硬编码大小,C29 编译器有一个名为 c29clang-tidy 的工具,用于检查没有 sizeof() 表达式的库调用,此处对该工具进行了讨论(在 c29migration-c28-stdlib 下)。
    2. 逐字节处理值的函数(如 memset)不会从 C28 移植到 C29。如果 memset 与 sizeof(int)、sizeof(int16_t)、sizeof(char) 或 sizeof(int8_t) 一起使用,则 C28 和 C29 的行为不同。请考虑以下 memset 示例。一些受影响的函数包括 memset、memccpy、memchr、strncmp。
memset(buf,5,2 * sizeof(char));
Byte address offset at buf: 0 8 16 24 32 40 48 56 64
C28:                        5    5          
C29:                        5 5  
memset(buf,5,2 * sizeof(short));
Byte address offset at buf: 0 8 16 24 32 40 48 56 64
C28:                        5    5          
C29:                        5 5  5 5
memset(buf,5,2 * sizeof(int));
Byte address offset at buf: 0 8 16 24 32 40 48 56 64
C28:                        5    5          
C29:                        5 5  5 5   5 5   5 5
其他函数(如 memcpy)也会出现行为差异,即使它们不是按字节操作也是如此。请考虑以下 memcpy 示例。
memcpy(dst,src,4 * sizeof(char));
Byte address offset at dst: 0 8 16 24 32 40 48 56 64
C28:                        1 2  3 4   5 6   7 8
C29:                        1 2  3 4
注意 memcpy 的使用方法,为了在 C28 和 C29 上获得相同的行为,可以使用 CHAR_BIT(在 limits.h 中定义)。
#if(CHAR_BIT == 16)
memcpy(dst,src,4 * sizeof(char));
#endif
#if(CHAR_BIT == 8)
memcpy(dst,src,4 * sizeof(char) * 2);
#endif
Byte address offset at dst: 0 8 16 24 32 40 48 56 64
C28:                        1 2  3 4   5 6   7 8
C29:                        1 2  3 4   5 6   7 8
注: 使用 C 头文件 stdint.h 可以移植固定宽度类型。