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.

CCS/TMS570LS3137: Copy code from flash to ram to run

Part Number: TMS570LS3137

Tool/software: Code Composer Studio

Hi,

I'm using GCC compiler,I want to copy code from flash to ram to run after initialization is complete,what should I do?

Thanks.

  • I'm not aware of any examples.  What follows is a rough sketch of one way to do it.  I did not test this out.  There are probably some minor errors that need to be corrected.

    Compile your code with the option -ffunction-sections .  This puts each function in its own section with a name such as .text.name_of_function.

    In the linker command file have something similar to ...

    ram_functions :
    {
        rf_load = LOADADDR(ram_functions);
        rf_run = .;
        rf_size = SIZEOF(ram_functions);
        *(.text.function1)
        *(.text.function2)
        *(.text.function3)
    } > RAM AT> FLASH

    This creates an output section named ram_functions.  The input sections are the .text section for the named functions.  Replace function1, function2, etc. with the names of the functions desired.  The symbols that begin rf_ are used to perform the copy from FLASH to RAM.  The last line allocates this output section to the RAM memory range for run, and the FLASH memory range for load.

    The code that does the copy will look similar to ...

    extern char rf_run[], rf_load[], rf_size[];
    ...
    memcpy(rf_run, rf_load, (size_t) rf_size);

    The general documentation for the GCC linker includes some examples.  But this example more directly demonstrates what you want to do.

    Please let me know if this example helps you resolve your problem.

    Thanks and regards,

    -George

  • Hi George,

    Here is my ld file,how should I modify it?

    Thanks.

    /*----------------------------------------------------------------------------*/
    /* sys_link.ld                                                              */
    /*                                                                            */
    /* (c) Texas Instruments 2009-2013, All rights reserved.                      */
    /*                                                                            */
    /*----------------------------------------------------------------------------*/
    /* Entry Point */
    ENTRY(_c_int00)
    /* Highest address of the stack */
    _estack = 0x8040000;    /* end of 256K RAM */
    /* Generate a link error if heap and stack don't fit into RAM */
    _Min_Heap_Size = 0x400;      /* required amount of heap  */
    /* Specify the memory areas */
    MEMORY
    {
      VECTORS(rx)     : ORIGIN = 0x00000000, LENGTH = 0x00000020
      FLASH  (rx)     : ORIGIN = 0x00000020, LENGTH = (0x0017FFE0 + 0x00180000)
      CPU_STACK (rw)  : ORIGIN = 0x08000000, LENGTH = 0x00001500 /* Stack is configured in sys_core.asm */
      RAM (xrw)       : ORIGIN = 0x08001500, LENGTH = 0x0003EB00
      MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
    }
    /* Define output sections */
    SECTIONS
    {
      /* The ISR vector goes first into RAM */
      .intvecs :
      {
        . = ALIGN(4);
        KEEP(*(.intvecs)) /* ISR vector */
        . = ALIGN(4);
      } >VECTORS
      /* The program code and other data goes into RAM */
      .text :
      {
        . = ALIGN(4);
        *(.text)           /* .text sections (code) */
        *(.text*)          /* .text* sections (code) */
        *(.glue_7)         /* glue arm to thumb code */
        *(.glue_7t)        /* glue thumb to arm code */
        *(.eh_frame)
        KEEP (*(.init))
        KEEP (*(.fini))
        . = ALIGN(4);
        _etext = .;        /* define a global symbols at end of code */
      } >FLASH
      /* Constant data goes into RAM */
      .rodata :
      {
        . = ALIGN(4);
        *(.rodata)         /* .rodata sections (constants, strings, etc.) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
        . = ALIGN(4);
      } >FLASH
       .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM
        .ARM : {
        __exidx_start = .;
          *(.ARM.exidx*)
          __exidx_end = .;
        } >FLASH
      .preinit_array     :
      {
        PROVIDE_HIDDEN (__preinit_array_start = .);
        KEEP (*(.preinit_array*))
        PROVIDE_HIDDEN (__preinit_array_end = .);
      } >FLASH
      .init_array :
      {
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array*))
        PROVIDE_HIDDEN (__init_array_end = .);
      } >FLASH
      .fini_array :
      {
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP (*(SORT(.fini_array.*)))
        KEEP (*(.fini_array*))
        PROVIDE_HIDDEN (__fini_array_end = .);
      } >FLASH
      /* used by the startup to initialize data */
      _sidata = LOADADDR(.data);
      
      /* Initialized data sections goes into RAM, load LMA copy after code */
      .data :
      {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start */
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end */
      } >RAM AT> FLASH
      /* Uninitialized data section */
      . = ALIGN(4);
      .bss :
      {
        /* This is used by the startup in order to initialize the .bss secion */
        _sbss = .;         /* define a global symbol at bss start */
        __bss_start__ = _sbss;
        *(.bss)
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        _ebss = .;         /* define a global symbol at bss end */
        __bss_end__ = _ebss;
      } >RAM
      PROVIDE ( end = _ebss );
      PROVIDE ( _end = _ebss );
      /* MEMORY_bank1 section, code must be located here explicitly            */
      /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
      .memory_b1_text :
      {
        *(.mb1text)        /* .mb1text sections (code) */
        *(.mb1text*)       /* .mb1text* sections (code)  */
        *(.mb1rodata)      /* read-only data (constants) */
        *(.mb1rodata*)
      } >MEMORY_B1
      /* Remove information from the standard libraries */
      /DISCARD/ :
      {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
      }
      
      .ARM.attributes 0 : { *(.ARM.attributes) }
    }
  • user6343407 said:
    Here is my ld file,how should I modify it?

    Add in the ram_function lines from my first post.  Put them inside the SECTIONS directive, before the definition of the .text output section.  

    The memcpy that copies those functions from flash to RAM must occur before any call to those functions.

    Have you noticed that your current linker script already does something similar for the .data section?

    user6343407 said:
      /* used by the startup to initialize data */
      _sidata = LOADADDR(.data);
      
      /* Initialized data sections goes into RAM, load LMA copy after code */
      .data :
      {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start */
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end */
      } >RAM AT> FLASH

    Search the source code for the symbol _sidata to see how this section is copied from flash to RAM.

    Thanks and regards,

    -George

  • Hi George,

    I found the source code for the symbol _sidata in startup.c:

    extern uint32 _sidata, _sdata, _edata;
    uint32 *src, *dst;

    src = &_sidata;
    dst = &_sdata;

    while (dst < &_edata)
    {
    *dst++ = *src++;
    }

    I have some questions about the functions in ram_runction.Are these functions in the main.c?For example,here is my main.c:

    int main(void){

    function_a();

    function_b();

    function_c();

    return 0;

    }

    so the ram_function will be:

    ram_functions :
    {
        rf_load = LOADADDR(ram_functions);
        rf_run = .;
        rf_size = SIZEOF(ram_functions);
        *(.text.a)
        *(.text.b)
        *(.text.c)
    } > RAM AT> FLASH
    But if my main.c is modified, do I have to modify the ram_function?Is there any way I don’t need to modify the ram_function every time?Can I just copy the main function?Like this:
    ram_functions :
    {
        rf_load = LOADADDR(ram_functions);
        rf_run = .;
        rf_size = SIZEOF(ram_functions);
        *(.text.main)
    } > RAM AT> FLASH
    Or use wildcard:
    ram_functions :
    {
        rf_load = LOADADDR(ram_functions);
        rf_run = .;
        rf_size = SIZEOF(ram_functions);
        *(.text.*)
    } > RAM AT> FLASH
    Thanks.
  • I think you need some general background in GCC linker scripts.  The attached file is the slides from a presentation titled: A Primer on Linker Scripts and Command Files.  Please read through the first part, which focuses on GCC linker scripts.

    A Primer on Linker Scripts and Command Files.pdf

    user6343407 said:

    I found the source code for the symbol _sidata in startup.c:

    extern uint32 _sidata, _sdata, _edata;
    uint32 *src, *dst;

    src = &_sidata;
    dst = &_sdata;

    while (dst < &_edata)
    {
    *dst++ = *src++;
    }

    This is a alternative to the memcpy method I use in my example.  Use whichever method you prefer.

    Throughout this thread, I use the term ram functions to refer to the functions which are loaded to flash, but are copied to RAM for execution.

    The ram functions can be in any source file.  The linker script finds them by name.  If, in the source code, the name of a ram function is function_a, then the linker script entry that corresponds to it must match that function name exactly ...

        *(.text.function_a)

    Note this entry ...

    user6343407 said:
     *(.text.main)

    ... corresponds to the function main.  No other functions, including the functions called by main, correspond to that entry.

    Don't do this ...

    user6343407 said:
    Or use wildcard:
    ram_functions :
    {
        rf_load = LOADADDR(ram_functions);
        rf_run = .;
        rf_size = SIZEOF(ram_functions);
        *(.text.*)
    } > RAM AT> FLASH

    That specification collects all of the functions.

    Thanks and regards,

    -George

  • Hi George,

    So the correct syntax is:

    ram_functions :

    {

       rf_load = LOADADDR(ram_functions);

       rf_run = .;

       rf_size = SIZEOF(ram_functions);

       *(.text.function_a)

       *(.text.function_b)

       *(.text.function_c)

    } > RAM AT> FLASH

    If the functions called by main has changed,the ram_function should also be changed,is that right?

    Thanks.

  • user6343407 said:
    If the functions called by main has changed,the ram_function should also be changed,is that right?

    The ram functions will always be exactly the ones you name in the linker script, without regard to whether those functions are called by main.

    Thanks and regards,

    -George

  • Hi George,

    After reading the pdf you provided,I have two questions:

    Dose the ram_functions need to begin with a dot "."?Because the output_section_name begin with a dot in my ld file.

    Do I need to add the options: -fdata-sections and --gc-sections?

    Thanks.

  • Hi George,

    My colleague wants to know whether the code must be copied from flash to ram to run?Can the code be run without being copied to ram?What situations need to run in ram,such as when using flash API?Can you answer that? I will convey it to my colleague.

    Thanks.

  • user6343407 said:
    Dose the ram_functions need to begin with a dot "."?

    No.  It is a widely observed convention for an output section name to begin with a dot.  But it is not a requirement.

    user6343407 said:
    Do I need to add the options: -fdata-sections and --gc-sections?

    They are not required for correct execution of your code.  That said, these options are commonly used to effect the automatic removal of functions and data that is not needed by the program.

    Thanks and regards,

    -George

  • user6343407 said:
    My colleague wants to know whether the code must be copied from flash to ram to run?Can the code be run without being copied to ram?What situations need to run in ram,such as when using flash API?Can you answer that? I will convey it to my colleague.

    These are questions of a system design nature for which I lack the expertise and perspective to answer.  I can tell you the compiler makes no presumption about whether the code for a function is in flash or RAM.  

    Thanks and regards,

    -George

  • Hi George,

    I copy the code to ram according to your method,but the function did not run,I don't know what went wrong,can you give me an example for reference?

    Thanks.

  • I'm sorry, but I don't have any examples for reference.  As I explained in my first post, my suggested solution is only a rough sketch that I did not test.  You need to use your debug skills to work out what went wrong, and then correct it.

    Thanks and regards,

    -George