HOWTO: Execute a library function from RAM memory using GNU build tools

Document created by stanish Employee on Mar 15, 2019
Version 1Show Document
  • View in full screen mode

The document describes the steps that need to be done in order to place and execute a library function from a custom memory section - typically RAM using GNU Build tools. The instructions are applicable to any GNU tool-chain. It is demonstrated on a New S32DS Project created in S32 Design Studio for ARM.

Lets assume that we'd like to execute memcpy() function from the standard library (NewLib).

 

1) The first step is to exclude specific library object file(s) from the input section (using EXCLUDE_FILE) so they will not be linked into the standard .text* flash section. 

The input section associated with EXCLUDE_FILE shall not interfere with the same input section used later in section list (e.g. with *(.text*) input section deleted from the list below). EXCLUDE_FILE in behaves the same was as *.(text*) rule - it only exclude selected file(s) but places all the remaining (non-excluded) input data.

 

/* The program code and other data goes into internal flash */
  .text :
  {
    . = ALIGN(4);
    *(.text)                 /* .text sections (code) */

     /* Exclude file(s) from NewLib libc.a from .text.* section  */    
     *(EXCLUDE_FILE (*libc.a:lib_a-memcpy-stub.o) .text*)  

    *(.rodata)               /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)              /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)               /* glue arm to thumb code */
    *(.glue_7t)              /* glue thumb to arm code */
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
  } > m_text

 

2) Now let's place the memcpy object into a code_ram section which is already defined in the project .ld file. This section is dedicated to a code that shall be executed from RAM (startup routine initializes this section). For more details see HOWTO: Run a routine from RAM in S32 Design Studio  .

 

The following line places the code (.text* section) from the object file (lib_a-memcpy-stub.o) from the standard NewLib (libc.a) 

 

*libc.a:lib_a-memcpy-stub.o (.text*)

 

into .code section:

.code : AT(__CODE_ROM)
  {
    . = ALIGN(4);
    __CODE_RAM = .;
    __code_start__ = .;      /* Create a global symbol at code start. */
    __code_ram_start__ = .;

    *(.code_ram)             /* Custom section for storing code in RAM */

    *libc.a:lib_a-memcpy-stub.o (.text*)   /* add memcpy from the NewLib library here*/
 
    . = ALIGN(4);
    __code_end__ = .;        /* Define a global symbol at code end. */
    __code_ram_end__ = .;
  } > m_data

 

After building the project you can check the map file to confirm memcpy is indeed placed into .code section in RAM memory:

.code           0x1fff881c       0x18 load address 0x00000d90
                0x1fff881c                . = ALIGN (0x4)
                0x1fff881c                __CODE_RAM = .
                0x1fff881c                __code_start__ = .
                0x1fff881c                __code_ram_start__ = .
*(.code_ram)
*libc.a:lib_a-memcpy-stub.o(.text*)
.text.memcpy   0x1fff881c       0x16 C:/NXP/S32DS_ARM_v2018.R1/Cross_Tools/gcc-6.3-arm32-eabi/arm-none-eabi/newlib/lib/thumb/v7e-m\libc.a(lib_a-memcpy-stub.o)
                0x1fff881c                memcpy
                0x1fff8834                . = ALIGN (0x4)
*fill*         0x1fff8832        0x2
                0x1fff8834                __code_end__ = .
                0x1fff8834                __code_ram_end__ = .
                0x00000da8                __CODE_END = (__CODE_ROM + (__code_end__ - __code_start__))
                0x00000da8                __CUSTOM_ROM = __CODE_END

 

Note

If you are placing a function into RAM always consider to add sub-functions called by that function (typically located in a different object file).

Attachments

    Outcomes