ARM Technical Support Knowledge Articles

Why might the +FIRST and +LAST scatter-loading attributes not behave as you might expect?

Applies to: DS-5

Answer

Suppose you have the following scatter file:

LR_IROM1 0x00000000            ; load region
{
  ER_DATA 0x20000000           ; execution region
  {    
    *(MYSEC, +FIRST)           ; User-defined specific placement                         
                               ; for all sections named MYSEC
    .ANY(+RW, +ZI)
  }

The corresponding source file that declares the MYSEC section might contain variable declarations similar to the following code: 

unsigned char A;
unsigned int B = 0x12345678;
unsigned char Buffer[256] __attribute__((section("MYSEC"), zero_init));

To generate a map file at link time, run the following commands to build this example:

armcc -c --bss_threshold=0 main.c

armlink --scatter my_scatter_file.sct --symbols -–map --list demo.map main.o

Note: The --bss_threshold=0 option instructs the compiler not to place small global zero-initialized (ZI) data items in read-write (RW) data sections for optimization by default. The small global ZI data items are uninitialized variables that are 8 bytes or less in size.

For details about the --bss_threshold option, see the ARM Compiler armcc User Guide.

You might be expecting the Buffer variable in the MYSEC section to be located at the start address of the execution region ER_DATA (0x20000000), as specified by the +FIRST attribute. However, when checking the map file after compilation, you find that the Buffer variable is located after other RW and ZI variables, such as A and B.

The actual map file output (using ARM Compiler 5.06 update 2):    

----------------------------------8<----------------------------------
Symbol Name    Value     Ov Type        Size  Object(Section)

B              0x20000000   Data           4  main.o(.data)
Buffer         0x20000004   Data         256  main.o(MYSEC)
A              0x20000104   Data           1  main.o(.data)

:

Base Addr    Size         Type   Attr  Idx  E Section Name      Object

0x20000000   0x00000004   Data   RW    3    .data               main.o
0x20000004   0x00000100   Zero   RW    4    MYSEC               main.o
0x20000104   0x00000001   Zero   RW    2    .bss                main.o
---------------------------------->8----------------------------------

The expected map file output:

----------------------------------8<----------------------------------
Symbol Name    Value     Ov Type        Size  Object(Section)

Buffer         0x20000000   Data        256   main.o(MYSEC)
A              0x20000100   Data          1   main.o(.data)
B              0x20000104   Data          4   main.o(.data)

:

Base Addr    Size         Type   Attr  Idx  E Section Name      Object

0x20000000   0x00000100   Zero   RW    4    MYSEC               main.o
0x20000100   0x00000001   Zero   RW    2    R.bss               main.o
0x20000104   0x00000004   Data   RW    3    .data               main.o
---------------------------------->8----------------------------------

The reason for this behavior is that the precedence level of the +FIRST and +LAST attributes is not the highest according to the linker placement rules for each execution region. The +FIRST and +LAST attributes must not violate the basic attribute sorting order. For example, a RW section marked with the +FIRST execution region attribute is placed after any read-only (RO) code or RO data sections, but is placed before other RW sections. For details about the default section placement can be found in in the ARM Compiler armlink User Guide.

In the above example, variable B belongs to an RW data section named .data, and variable A belongs to a ZI section named .bss. In addition, the Buffer array is marked with the zero_init attribute, so the array is placed in a ZI section. The +FIRST attribute marks MYSEC as the first ZI section in the execution region ER_DATA, which explains the following ordering in memory:

B(RW), Buffer(ZI), A(ZI)

To ensure that the MYSEC section is placed at the beginning of the ER_DATA region, you can place MYSEC in a dedicated execution region for ZI data, for example:

LR_IROM1 0x00000000         ; load region
{  
  ER_DATA_ZI 0x20000000     ; dedicated ER for ZI data
  {
    * (MYSEC, +FIRST)
    .ANY(+ZI)
  }

  ER_DATA_RW +0             ; dedicated ER for RW data
  {
    .ANY(+RW)
  }
}

Related information:

Article last edited on: 2016-03-11 06:03:44

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential