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.

TM4C1294NCZAD: Changing sections link order in Linker command file.

Part Number: TM4C1294NCZAD

Our Setup:

Compiler:   TI ARM Compiler  v20.2.6.LTS.

CCS Version: 11.2

MCU:     TM4C1294NCZAD

Board:    EK-TM4C129-XL

The linker places sections in memory according to size (largest section first and so on) and not in the order as they are specified in the Linker Command file.

The linker command file looks as Follows:

MEMORY
{
    FLASH (RX) : origin = 0x00000000, length = 0x00100000
    SRAM (RWX) : origin = 0x20000000, length = 0x00040000
}

--heap_size=0x10000
--stack_size=0x800


/* Section allocation in memory */

SECTIONS
{
    .intvecs:   > 0x00000000
    .text     :   > FLASH
    .const  :   > FLASH
    .cinit    :   > FLASH
    .pinit    :   > FLASH
    .init_array : > FLASH

    .vtable :   > 0x20000000
    .data    :   > SRAM
    .bss     :   > SRAM
    .sysmem :   > SRAM
    .stack  :   > SRAM (HIGH)
}

/* define top of Stack will be used by initialization routine */
__STACK_TOP = __stack + __STACK_SIZE;

Output in Map file looks as Follows:

SEGMENT ALLOCATION MAP

run origin  load origin   length   init length attrs members
----------  ----------- ---------- ----------- ----- -------

20000000    20000000    00010678   00000000    rw-
  20000000    20000000    0000026c   00000000    rw- .vtable
  20000270    20000270    00010000   00000000    rw- .sysmem
  20010270    20010270    0000021f   00000000    rw- .data
  20010490    20010490    000001e8   00000000    rw- .bss
2003f800    2003f800    00000800   00000000    rw-
  2003f800    2003f800    00000800   00000000    rw- .stack

As we see the .sysmem which is the largest section is allocated ahead of .data and .bss sections.

We want sections to be allocated in the same order as defined an Linker Command file.

Regards

Lal

  • Lal,

    Our compiler expert is out until later this week.

    In this document there is a section "First Output Section in a Memory Range" that shows how you can ensure that a particular section comes first.

    https://software-dl.ti.com/ccs/esd/documents/sdto_cgt_Linker-Command-File-Primer.html

    However the rest of the sections can be allocated by the linker in any order.

    Instead you could try to use the "GROUP" directive.  Search the same document for "Group Output Sections Together".

    Regards,

    John

  • Dear John,

    Thanks for your prompt replay.

    Even If we group the .data and .bss section the .sysmem remains the largest section.

    The idea here is to define the memory layout such that the .sysmem occupies all the ram that remains after allocating all other sections and secondly put .stack at end of the Ram so that .stack and .sysmem grow towards each other.

    We previously used ARM-GCC and the sections were always placed as listed in Linker Command File, so the behaviour of TI-ARM compiler is a bit strange to us.

    Regards

    Lal

  • Even If we group the .data and .bss section the .sysmem remains the largest section.

    GROUP will not change the size of a section.  But it can help you with controlling the order.

    GROUP : > SRAM
        {
            .vtable
            .data
            .bss
            .sysmem
        }
    .stack  :   > SRAM (HIGH)

    Our compiler expert will be back tomorrow and can assist further.

    Regards,

    John

  • Hi Lal,

    By way of introduction, my name is Todd Snider. I am a member of the TI Arm Clang Compiler Tools team with experience working on the linker.

    As John suggested, a GROUP specification within the SECTIONS specification will allow you to order output sections within the area of memory that the GROUP is allocated to. The output sections specified within a GROUP will be allocated in order and contiguously.

    With regards to your request to have the linker allocate sections in the order in which they appear in the linker command file ... we have a pending enhancement request work item for this feature/behavior in the linker that we are strongly considering for the next major release (3.x.0.LTS, which is still in the planning stages). There are some complications that the linker needs to take into account if it were to implement the requested feature/behavior ...

    How to deal with different types of placement instructions that go to the same memory area?

    Some types of placement instructions are more constrained than others. For example, if a general allocation to SRAM is specified prior to an allocation to a specific address in the SRAM memory area, then the linker needs to honor the specific address placement before processing the general placement.

    SECTIONS {

       general_scn: { *(.data) } > SRAM

       speific_scn:   { a.o(.scn_a) } > 0x2000     /* where 0x2000 is within the SRAM memory range */

    }

    There are other types of placement instructions that may be less constrained, like "split" placement (e.g. "split_scn: { *(.scn) } >> SRAM" - allow "split_scn" to be allocated to SRAM in pieces (split on an input section boundary) to potentially fill available gaps between one allocated section and another) or "one-of" placement (e.g. "oneof_scn: { *(.scn) } > SRAM | EMEM" - allocates "oneof_scn" in entirety in either SRAM or EMEM).

    What we could end up implementing would honor differences in the priority of one type of placement instruction vs. another, but for those sections that have placement instructions of equivalent priority, such as:

    SECTIONS {

       a_scn: { *(.a_scn) } > SRAM

       b_scn: { *(.b_scn) } > SRAM

    }

    the linker can be made to allocate those in the order in which they appear in the linker command file, regardless of their relative size.

    Hope this helps.

    Regards,

    Todd Snider

  • Hi Todd,

    Thanks for taking time and answering in detail.

    I went through the compiler documentation and read about the options that you mentioned.

    Actually we also have a custom section "FAST_CODE" which Loads from Flash and runs from Ram (see blow), compiler don't allow to Group this with sections which load and run from Flash.

        .Fast_Code :
        {
            . = ALIGN(4);
            *(FAST_CODE)                /* FAST_CODE sections */
            . = ALIGN(4);
        }  LOAD = FLASH, RUN = SRAM,
           LOAD_START(__FastCode_LoadStart), LOAD_END(__FastCode_LoadEnd),
           RUN_START(__FastCode_RunStart)

    On the other hand if we Group all other section which run & load from Ram than this Group being the largest memory block gets allocated first and the FAST_CODE being very small gets allocated in the end.

    We want to define the memory layout such that:

    1. The .sysmem and .stack should occupy the upper memory range.
    2. The .sysmem and .stack should occupy all the ram that remains after allocating all other sections.
    3. Put .stack at end of the Ram so that .stack and .sysmem grow towards each other during program execution.

    So I think (for now) this can only be done, by manually splitting the RAM and putting the section as required.

    Regards

    Lal

  • The idea here is to define the memory layout such that the .sysmem occupies all the ram that remains after allocating all other sections and secondly put .stack at end of the Ram so that .stack and .sysmem grow towards each other.

    Not sure if it helps, but Compiler/DK-TM4C129X: any way to maximize the heap size? was an example using the TI ARM compiler where .sysmem was defined in such a way that used all remaining SRAM.

    The referenced example didn't allow the .stack and .sysmem to grow towards each other, but that could potentially cause a program failure if the heap overwrote what was being used for the stack.