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.

Strange Behaviour of memcpy() [TI compiler version V6.0.2, Target - TMS320F28335]

Other Parts Discussed in Thread: TMS320F28335

Hi,

I'm facing a strange behaviour of memcpy function in the below code when compiled with TI compiler version V6.0.2 for the target TMS320F28335.

//-------- Code Starts Here--------------

#include <stdio.h>

float var1;

unsigned int var2;

unsigned long var2;

void main(void) {

     var2 = 0x0200;

     memcpy(&var1, &var2, 4);

}

//----------Code Ends Here---------------

Issue:

The above code is expected to copy 4 bytes from var2 into var1. However when compiled and executed in target (TMS320F28335) which has 16 bit data in each address, I noticed 8 bytes (4 x 16 bits) are copied from the source to the destination. This results in modifying the contents of unexpected memory address thereby crashing my program. I understood that it was due to incorrect behavior of the memcpy function for a 16bit data in the memory address (Because memcpy assumes the memory address contains 8 bit data and increments the source address 4 times, however it is a 16bit data). Could any one please confirm my understanding is correct? Also please suggest me to use the CGT version in which this issue has been fixed.

Thanks,

Anand

 

  • Your code presumes ...

    • char is 8 bits
    • int is 32 bits
    • float is 32 bits

    But on C2000 ...

    • char is 16 bits
    • int is 16 bits
    • float is 32 bits

    I suggest you use the types from stdint.h instead of presumptions about the sizes of the built-in types.  There is nothing in stdint.h about a integer type that is the same size as a float.  It is very common for float to be 32-bits, so your code could presume that int32_t is a good type to use for that purpose.  Unfortunately, there is no way to check that presumption at build time.  You could have a runtime check like ...

    if (sizeof(float) != sizeof(int32_t))
       { abort_some_obvious_way_here(); }

    For more on this topic, please see this wiki article.

    Thanks and regards,

    -George

  • George Mock said:
    Unfortunately, there is no way to check that presumption at build time.

    See the 2nd answer in Conditional Compilation and compile time evaluation of expressions in ANSI C for to stop compilation when a data type is the wrong size.

  • George Mock said:

    Your code presumes ...

    • char is 8 bits
    • int is 32 bits
    • float is 32 bits

    But on C2000 ...

    • char is 16 bits
    • int is 16 bits
    • float is 32 bits

    Agreed. Earlier I used incorrect data type for var2. Now I corrected the datatype of var2 to unsigned long (32 bits). Still I'm facing the same strange behaviour of the memcpy function. Any advice on this George?

  • Anand Venkatesan said:
    Now I corrected the datatype of var2 to unsigned long (32 bits). Still I'm facing the same strange behaviour of the memcpy function. Any advice on this George?

    Section 6.4 Data Types of the TMS320C28x Optimizing C/C++Compiler v6.1 User's Guide SPRU514E contains the following note:
    NOTE: TMS320C28x Byte is 16 Bits

    By ANSI/ISO C definition, the sizeof operator yields the number of bytes required to store an object. ANSI/ISO further stipulates that when sizeof is applied to char, the result is 1. Since the TMS320C28x char is 16 bits (to make it separately addressable), a byte is also 16 bits. This yields results you may not expect; for example, size of (int) = = 1 (not 2). TMS320C28x bytes and words are equivalent (16 bits). To access data in increments of 8 bits, use the __byte() and __mov_byte() intrinsics described in Section 7.4.5.

    I.e. sizeof(float) = 2. What this means is that the following copies 4 16-bit words:

         memcpy(&var1, &var2, 4);

    And to copy the correct amount of data should be written as:
         memcpy(&var1, &var2, sizeof(var1));
  • Also, please #include <string.h> in order to properly declare memcpy.

    The notion of copying an integer representation as raw bits into a float variable is almost certainly not necessary for the application.