SPRUIY8 October   2024 F29H850TU , F29H859TU-Q1 , TMS320C28341 , TMS320C28342 , TMS320C28343 , TMS320C28343-Q1 , TMS320C28344 , TMS320C28345 , TMS320C28346 , TMS320C28346-Q1

 

  1.   1
  2.   Abstract
  3.   Trademarks
  4. 1Introduction
  5. 2C28 to C29 CPU Migration
    1. 2.1 Use Cases
    2. 2.2 Key Differences
    3. 2.3 Source Code Migration
      1. 2.3.1 C/C++ Source Code
        1. 2.3.1.1 Pragmas and Attributes
        2. 2.3.1.2 Macros
        3. 2.3.1.3 Intrinsics
        4. 2.3.1.4 Inline assembly
        5. 2.3.1.5 Keywords
        6. 2.3.1.6 Data Type Differences
        7. 2.3.1.7 Tooling support for Migration
      2. 2.3.2 Assembly Language Source Code
    4. 2.4 Toolchain Migration
      1. 2.4.1 Compiler
      2. 2.4.2 Linker
      3. 2.4.3 CCS Project Migration
  6. 3CLA to C29 CPU Migration
    1. 3.1 Use Cases
    2. 3.2 Key Differences
    3. 3.3 Source Code Migration
      1. 3.3.1 C/C++ Source Code
        1. 3.3.1.1 Data Type Differences
        2. 3.3.1.2 Migrating CLAmath.h Functions and Intrinsics
        3. 3.3.1.3 Migrating C28 and CLA to the Same C29 CPU
        4. 3.3.1.4 Migrating C28 and CLA to Different C29 CPUs
      2. 3.3.2 Assembly Language Source Code
    4. 3.4 Toolchain Migration
  7. 4References

Data Type Differences

Data type differences - the key differences in this context are summarized and highlighted in Table 2-2.

Table 2-2 Data Type Key Differences
Type C28 CLA C29 ARM
char 16 16 8 8
short 16
int 16 32 32 32
long 32
long long (COFF) 64 32

N/A

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

N/A

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

N/A

64
long double (EABI) 64
Pointers 32 16 32 32

The user needs to pay careful attention to data types:

  1. int (C28 16-bit vs C29 32-bit) - If the user's code has occurrences of "int", the following is recommended for migration:
    1. Change all occurrences of "int" in user code to a fixed-width type int16_t. This ensures nothing in the code breaks, and original data widths are retained.
      1. The C29 compiler has a tool called c29clang-tidy which checks for occurrences of "int" and "unsigned int", which is discussed here (under c29migration-c28-int-decls)
    2. Ideal scenario - user code does not contain any occurrences of "int", instead only contains portable fixed-width types like int16_t, int32_t. In this case, the code is portable without any changes.
  2. char (C28 16-bit vs C29 8-bit) - If the user's code has occurrences of "char" or "int8_t" or "uint8_t":
    1. At the outset, changing all occurrences of "char" to "int16_t" may seem like the migration approach, since it is retaining the bit-width present in the user's original code. However, this can lead to unexpected build-time issues, or worse, hard to detect run-time failures. This is because it is not legal for pointers of different types to alias. Char, however, is special and may alias with other pointer types. In other words, any object can be accessed through a pointer to char. So if you now change char to int16_t, you will violate this "special privilege" that char alone has.
    2. Therefore, the recommended approach to migration is to make no changes to the code, or preferably, change all occurrences of "char" in user code to "int8_t". Even this approach has some problematic scenarios:
      1. If user code contains "char" occurrences but really has 16-bit dependency, which needs to be changed to int16_t. For example, assigned data that is out of 8-bit range and needs 16-bit range. The C29 compiler has a tool called c29clang-tidy that checks for operations on "char" typed expressions that would be out of range for an 8-bit type, which is discussed here (under c29migration-c28-char-range)
      2. If user code contains pointers to "char" and associated offsets, or arithmetic on such pointers. The C29 compiler has a tool called c29clang-tidy that checks for pointer arithmetic on char/int-based pointers, whose bit stride changes between C28 to C29, which is discussed here (under c29migration-c28-types and c29migration-c28-suspicious-dereference).
      Note: Note that Pointer aliasing is not an issue with changing "char" to "int8_t".
  3. Differences in sizeof() due to the data type differences - This is summarized in the table, and leads to differences in behavior when using standard library function calls:
    sizeof(char) sizeof(short) sizeof(int) sizeof(long)
    C28 1 1 1 2
    C29 1 2 4 4
    1. If a hardcoded size is used, the C29 compiler has a tool called c29clang-tidy which checks for library calls without a sizeof() expression, which is discussed here (under c29migration-c28-stdlib).
    2. Functions which work on values byte-by-byte, like memset, do not port from C28 to C29. If memset is used with sizeof(int), sizeof(int16_t), sizeof(char), or sizeof(int8_t), the behavior is different between C28 and C29. Consider the following example with memset. Some of the functions that are affected are 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
Differences in behavior occur with other functions like memcpy as well, even if they don't operate byte wise. Consider the following example with 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
Note how with memcpy, in order to obtain the same behavior on both C28 and C29, CHAR_BIT (defined in limits.h) can be used.
#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
Note: The portability of fixed-width types is possible with the use of C header stdint.h.