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.

Compiler/TMS320F28379D: memcpy function receives size input as a pointer

Part Number: TMS320F28379D


Tool/software: TI C/C++ Compiler

Hi everyone,

I've noticed in TI examples that memcpy function receives size input as a pointer, something like this:

memcpy((uint32_t *)&Cla1funcsRunStart, (uint32_t *)&Cla1funcsLoadStart, (uint32_t)&Cla1funcsLoadSize);

Why is third parameter (Cla1funcsLoadSize) sent as an address to register that holds the size value? The memcpy function prototype in C99 is defined as:

void* memcpy( void *dest, const void *src, size_t count );

I didn't find anything about this in the TI C/C++ compiler manual (spru514q).

  • Hi Marko,

    The usage of memcpy is correct. The function call parameters should use the & symbols.

    Did you check the post at e2e.ti.com/.../198742

    Thanks,
    Katta
  • Dear Katta,

    Thank you for your reply.

    Yes, I've checked those posts, but unfortunately they do not answer my question.

    I managed to find the memcpy source code in the TI compiler directory:

    #include <string.h>
    
    void *memcpy(void * __restrict to, const void * __restrict from, size_t n)
    {
         size_t rn;
    
         for (rn = 0; rn < n; rn++)
             ((unsigned char *)to)[rn] = ((const unsigned char *)from)[rn];
         return to;
    }

    Let me describe what I'm confused about. The "to" and "from" inputs are memory addresses where the original code is, and where the original code needs to be copied. The "n" input is not a pointer (i.e., a memory addresses), but an unsigned integer that tells the memcpy function how many "memory locations" need to be copied. However, in all your examples you call the memcpy function as follows:

    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (uint32_t) &RamfuncsLoadSize);

    I get why the first two inputs have the "&" operator - to send the actual memory location where the original code is, and where the code needs to be copied. But what I don't get is the third input:

    (uint32_t) &RamfuncsLoadSize

    This will send the memory location where the RamfuncsLoadSize is placed, but not the actual size. Here is the simple program that does not work with the "&" operator near the third input:

    #include <stdio.h>
    
    void *memcpy(int * to, const int * from, unsigned n)
    {
        printf("size in memcpy is %u\n", n);
        
        size_t rn;
    
        for (rn = 0; rn < n; rn++)
            ((unsigned int *)to)[rn] = ((const unsigned int *)from)[rn];
        return to;
    }
    
    int main()
    {
        int src[2] = { 1, 2 };
        int dst[2];
        int size = sizeof(src) / sizeof(int);
        
        printf("size is %d (0x%08X)\n", size, &size);
        
        // Does work
        memcpy(&dst, &src, size);
        
        // Does not work!
        //memcpy(&dst, &src, (unsigned)&size);
        
        printf("src = {%d,%d}\n", src[0], src[1]);
        printf("dst = {%d,%d}\n", dst[0], dst[1]);
    
        return 0;
    }

    I'm trying to understand where does the "&" operator near the third input come from. Is this some compiler-specific stuff, or the way the linker does things? I was unable to find any documentation that describes this.

  • Hi Marko,

    The variables RamfuncsRunStart, RamfuncsLoadStart, RamfuncsLoadSize come from the linker command file. In fact, they are not variables, but symbols defined by the linker at addresses equal to the start and size of the memory sections

    For example:
    .TI.ramfunc : {} LOAD = FLASHD,
    RUN = RAMD0,
    LOAD_START(_RamfuncsLoadStart),
    LOAD_SIZE(_RamfuncsLoadSize),
    LOAD_END(_RamfuncsLoadEnd),
    RUN_START(_RamfuncsRunStart),
    RUN_SIZE(_RamfuncsRunSize),
    RUN_END(_RamfuncsRunEnd),
    PAGE = 0, ALIGN(4)


    In case linker links the section ramfunc at address 0x1000 to 0x1100, it adds additional symbols at 0x1000, 0x1100 and at 0x100 with names RamfuncsLoadStart, RamfuncsLoadEnd, RamfuncsLoadSize respectively. It is not the values at those location that matters, but the addresses.

    You can also check the .map file to get a better idea. It shows those symbols and the corresponding addresses. That is the reason why we use & with those symbols

    Hope this helps!

    Regards,
    Veena

  • I get it now. My mistake is that I thought that the three memcpy inputs were VARIABLES, instead of just SYMBOLS defined by linker.

    Thank you for your help!