7.2.4 Placing functions and data in a named section

You can place functions and data by separating them into their own objects without having to use toolchain-specific pragmas or attributes. Alternatively, you can specify a name of a section using the function or variable attribute, __attribute__((section("name"))).

You can use __attribute__((section("name"))) to place a function or variable in a separate ELF section, where name is a name of your choice. You can then use a scatter file to place the named sections at specific locations.

You can place ZI data in a named section with __attribute__((section(".bss.name"))).

Use the following procedure to modify your source code to place functions and data in a specific section using a scatter file.

Procedure

  1. Create a C source file file.c to specify a section name foo for a variable and a section name .bss.mybss for a zero-initialized variable z, for example:
    #include "stdio.h"
    
    int variable __attribute__((section("foo"))) = 10;
    __attribute__((section(".bss.mybss"))) int z;
    
    int main(void)
    {
        int x = 4;
        int y = 7;
        z = x + y;
        printf("%d\n",variable);
        printf("%d\n",z);
        return 0;
    }
  2. Create a scatter file to place the named section, scatter.scat, for example:
    LR_1 0x0
    {
        ER_RO 0x0 0x4000
        {
            *(+RO)
        }
        ER_RW 0x4000 0x2000
        {
            *(+RW)
        }
        ER_ZI 0x6000 0x2000
        {
            *(+ZI)
        }
        ER_MYBSS 0x8000 0x2000
        {
            *(.bss.mybss)
        }
    
        ARM_LIB_STACK 0x40000 EMPTY -0x20000  ; Stack region growing down
        { }
        ARM_LIB_HEAP 0x28000000 EMPTY 0x80000 ; Heap region growing up
        { }
    }
    
    FLASH 0x24000000 0x4000000
    {
        ; rest of code
    
        ADDER 0x08000000
        {
            file.o (foo)                  ; select section foo from file.o
        }
    
    }

    The ARM_LIB_STACK and ARM_LIB_HEAP regions are required because the program is being linked with the semihosting libraries.

    Note:

    If you omit file.o (foo) from the scatter file, the linker places the section in the region of the same type. That is, ER_RW in this example.
  3. Compile and link the C source:
    armclang --target=arm-arm-eabi-none  -march=armv8-a file.c -g -c -O1 -o file.o
    armlink --cpu=8-A.32 --scatter=scatter.scat --map file.o --output=file.axf

    The --map option displays the memory map of the image.

    Example:

    In this example:

    • __attribute__((section("foo"))) specifies that the linker is to place the global variable variable in a section called foo.
    • __attribute__((section(".bss.mybss"))) specifies that the linker is to place the global variable z in a section called .bss.mybss.
    • The scatter file specifies that the linker is to place the section foo in the ADDER execution region of the FLASH execution region.

    The following example shows the output from --map:

    …
        Execution Region ER_MYBSS (Base: 0x00008000, Size: 0x00000004, Max: 0x00002000, ABSOLUTE)
    
        Base Addr    Size         Type   Attr      Idx    E Section Name        Object
    
        0x00008000   0x00000004   Zero   RW            7    .bss.mybss          file.o
    …
      Load Region FLASH (Base: 0x24000000, Size: 0x00000004, Max: 0x04000000, ABSOLUTE)
    
        Execution Region ADDER (Base: 0x08000000, Size: 0x00000004, Max: 0xffffffff, ABSOLUTE)
    
        Base Addr    Size         Type   Attr      Idx    E Section Name        Object
    
        0x08000000   0x00000004   Data   RW            5    foo                 file.o
    …

    Note:

    • If scatter-loading is not used, the linker places the section foo in the default ER_RW execution region of the LR_1 load region. It also places the section .bss.mybss in the default execution region ER_ZI.
    • If you have a scatter file that does not include the foo selector, then the linker places the section in the defined RW execution region.

    You can also place a function at a specific address using .ARM.__at_address as the section name. For example, to place the function sqr at 0x20000, specify:

    int sqr(int n1) __attribute__((section(".ARM.__at_0x20000")));
    
    int sqr(int n1)
    {
        return n1*n1;
    }

    For more information, see 7.2.5 Placing __at sections at a specific address.

Non-ConfidentialPDF file icon PDF versionDUI0803J
Copyright © 2014–2017, 2019 Arm Limited or its affiliates. All rights reserved.