ARM Technical Support Knowledge Articles

Placement of small global ZI data (<= 8 bytes) in memory

Applies to: RealView Development Suite (RVDS)


A new optimization has been added to the RVCT 2.1 and later compilers, where small global ZI data items (<= 8 bytes) are now placed by default into an RW data section, not ZI as in earlier releases. For example:

   int global;  /* ZI (.bss) in RVCT 2.0.1 and earlier */
/* RW (.data) in RVCT 2.1 and later */

The benefit of this optimization is that it offers the compiler the opportunity to save on the number of base pointer registers needed to access global data, therefore freeing up valuable processor registers for other purposes, and consequently saving on ROM size (especially if RW data compression is active), as well as offering improved code performance.

However, this optimization may be incompatible with your build if you have made assumptions about the compiler's placement of data, for example:

   #pragma arm section zidata = ".bar"
int global; /* .bar in RVCT 2.0.1 and earlier, .data in RVCT 2.1 and later */
#pragma arm section

In RVCT 2.0.1 and earlier, a section called ".bar" is created, which you might place explicitly in the memory-map by specifying it in a scatter-file for the linker.

In RVCT 2.1 and later, the section ".bar" is not created, which may result in a warning at link time like:

   Warning: L6314W: No section matches pattern *(.bar)

or may silently fail if this region is not explicitly placed in a scatter-file.

To ensure that "global" is placed in a section called ".bar", the recommended approach (compatible with ADS 1.2, RVCT 1.2, RVCT 2.0 and RVCT 2.1) is to change the source code to:

   #pragma arm section zidata = ".bar", rwdata = ".bar"
int global;
#pragma arm section

Another workaround, for RVCT 2.1 and later only, is to use the new "--gnu" mode attribute:

   int global __attribute__ ((section (".bar")));

but beware that this will always create an RW section .bar (not a ZI section).

In RVCT 2.2, variable definitions with no initializer can be forced into ZI sections using __attribute__((zero_init)), for example:

  __attribute__((zero_init)) int x; /* in section ".bss" */
  __attribute__((section(".bar"),zero_init)) int y; /* in section ".bar" */

To revert to the behavior of RVCT 2.0.1 and earlier, use the (undocumented) RVCT 2.1 compiler switch "--bss_threshold=0", though beware that this might result in a slight increase in code size.

Be aware that this optimization may also affect placement of peripheral registers in the memory map, for example:

In timer.c:

   int timer;     /* ZI (.bss) in RVCT 2.0.1 and earlier */
/* RW (.data) in RVCT 2.1 and later */

...which is placed in the memory map using a scatter file like:

*.o (+RO) ; all code
timer.o (+ZI) ; timer peripheral
EXEC_RAM 0x400000
*.o (+RW, +ZI) ; all other data

In RVCT 2.0.1 and earlier, the timer peripheral register will be placed in the TIMER section. In RVCT 2.1 and later, the timer peripheral register will be placed in the EXEC_RAM section.

Note that it is NOT correct in this case to change:

      timer.o (+ZI)


      timer.o (+RW, +ZI)

because the UNINIT attribute only applies to ZI sections, not RW sections, so the RW section would be initialized on startup, which is not what was required.

The correct workaround in this case is to use "--bss_threshold=0" as described earlier.

Article last edited on: 2008-10-23 12:55:53

Rate this article

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