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.

TMS320F280039C: memcpy function and #pragma CODE_SECTION(".TI.ramfunc")

Part Number: TMS320F280039C

Tool/software:

Hi Champ,

I am asking for my customer.

Referring to this post, 

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1085141/tms320f280049-introduction-to-memcpy-function

As the linker command file has created an output section named .TI.ramfuncs, user must manually do the FLASH to RAM copy with the memcpy in the application code before any of the functions in the Ramfuncs section are called.

But from our test, we have seen the #pragma CODE_SECTION(".TI.ramfunc") also does the same thing, to allocate space for the symbol that is loaded to flash and executed from RAM.

By trying to comment out the memcpy in the application code, ONLY leave the line #pragma CODE_SECTION(ADCC1_ISR, ".TI.ramfunc") before ADCC1_ISR and have Load at One Address, Run from a Different Address in the linker command file as shown below. In the compiled .map file, the ADCC1_ISR.obj was born at the load address of the flash and it was still mapped to the RAM w/o the memcpy line to do the FLASH to RAM copy.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* In a C file */
// memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); // comment out the memcpy
#pragma CODE_SECTION(ADCC1_ISR, ".TI.ramfunc")
__interrupt void ADCC1_ISR( void )
{
...
}
/* In a linker command file */
.TI.ramfunc : LOAD = FLASH_BANK0_SEC1|FLASH_BANK0_SEC2 | FLASH_BANK0_SEC3 | FLASH_BANK0_SEC4,
RUN = RAMLS0_1_2_3,
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
LOAD_END(RamfuncsLoadEnd),
RUN_START(RamfuncsRunStart),
RUN_SIZE(RamfuncsRunSize),
RUN_END(RamfuncsRunEnd),
ALIGN(4)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

1. Would the expert please clarify is #pragma CODE_SECTION(".TI.ramfunc") doing the exact same things as memcpy to have the symbol loaded to flash and executed from RAM ? since it was seen the .obj of the symbol was also mapped to the RAM and executing the symbol from RAM.

2. If not, please explain what are the two differences ?

3. Are these two must be tied and used together, to have the symbol executing from outpst section ".TI.ramfunc" ?

I'd appreciate any insights you can provide.

Thanks and regards,

Johnny

  • Your understanding is partially correct.  The compiler option --ramfunc causes all the functions in that file to be placed in the section named .TI.ramfunc.  At compile time, that is all that happens.  For one function, you can do the same thing with #pragma CODE_SECTION(".TI.ramfunc").  

    To understand the code in the linker command file, please search the article Linker Command File Primer for the part titled Load at One Address, Run from a Different Address.  Note how the copy from the load address to the run address does not occur automatically.  In your case, the memcpy must execute.  Otherwise, the code for the functions in .TI.ramfunc are not at the run address when a call to one of those functions occurs.

    Thanks and regards,

    -George

  • Hi George,

    Thanks for the reply.

    What is the default compiler option --ramfunc without any selection, leaving a blank space there ?

    In your case, the memcpy must execute.  Otherwise, the code for the functions in .TI.ramfunc are not at the run address when a call to one of those functions occurs.

    If the case is w/o memcpy execution and w/o compiler option --ramfunc here, does that mean that though it could still see the code allocated a space in RAM with #pragma CODE_SECTION from the map file, during run time, it may face the issue that the program counter flies off when executing the line of code for the function since it is not at the run address, right ? 

    If there is another section named XX which is also loading somewhere on flash and running a specific RAM, saying GSRAM, do I need a separate line of memcpy as below ?  

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* In a cmd file */
    XX : LOAD = FLASH_BANK0_SEC4,
    RUN = RAMGS0_1,
    LOAD_START(XXfuncsLoadStart),
    RUN_START(XXfuncsRunStart),
    LOAD_SIZE(XXfuncsLoadSize),
    ALIGN(4)
    /* In a C file */
    extern Uint16 XXfuncsRunStart, XXfuncsLoadStart, XXfuncsLoadSize;
    memcpy((uint16_t *)&XXfuncsRunStart, (uint16_t *)&XXfuncsLoadStart, (uint16_t)&XXfuncsLoadSize);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Then, do I need addition a line for #pragma CODE_SECTION ("XX") in front of the function to have the function to execute from GSRAM ? or could I skip the line #pragma CODE_SECTION ("XX") then also achieve the same goal for executing from GSRAM.

    I am still confused which line (memcpy / #pragma) is exactly having the function executing from RAM here, trying to make it clear here.

    Appreciate your patience.

    Thanks and regards,

    Johnny

  • What is the default compiler option --ramfunc without any selection, leaving a blank space there ?

    --ramfunc=on

    If the case is w/o memcpy execution and w/o compiler option --ramfunc here, does that mean that though it could still see the code allocated a space in RAM with #pragma CODE_SECTION from the map file, during run time, it may face the issue that the program counter flies off when executing the line of code for the function since it is not at the run address, right ? 

    Yes

    If there is another section named XX which is also loading somewhere on flash and running a specific RAM, saying GSRAM, do I need a separate line of memcpy as below ?  

    Yes

    Then, do I need addition a line for #pragma CODE_SECTION ("XX") in front of the function to have the function to execute from GSRAM ?

    Yes

    or could I skip the line #pragma CODE_SECTION ("XX") then also achieve the same goal for executing from GSRAM.

    The #pragma makes it easy to write linker command file code which creates the output section that contains the functions, then allocate that output section to different load and run addresses.  There are ways to do it without a pragma and without --ramfunc=on.  But they are more difficult.  Just use the easy way.

    I am still confused which line (memcpy / #pragma) is exactly having the function executing from RAM

    You need both.  There are probably a few different ways to think it through.  I break it down here into 3 steps.

    1. Get all the functions into a section with the same name.  If you use --ramfunc=on, then that name is .TI.ramfunc.  An alternative is to apply #pragma CODE_SECTION to each function.
    2. Write linker command file code which creates an output section with that name.  Because all of the functions are in input sections with a matching name, they are collected into this output section.  Allocate that section to different load and run addresses.
    3. Before any of these functions are called, use memcpy to copy the code for the functions from the load address to the run address.

    Thanks and regards,

    -George