2.6.2. Placing the stack and heap in the scatter-loading description file

In many cases, it is preferable to specify the location of the stack and heap in the description file. This has two main advantages:

This section describes methods for implementing this:

Placing symbols explicitly

Stack pointer initialization refers to the symbols stack_base and heap_base as reference symbols that can be placed in a description file. To do this, create symbols labeled stack_base and heap_base in an assembler module called stackheap.s. The same can be done for the stack and heap limits in a two-region memory model.

You can locate each of the symbols within their own execution region in the description file, as shown in Example 2.15.

Example 2.15. Placing symbols explicitly in stackheap.s

        AREA   stacks, DATA, NOINIT
        EXPORT stack_base

stack_base        SPACE   1

        AREA   heap, DATA, NOINIT
        EXPORT heap_base
 
heap_base         SPACE   1
	    END

Figure 2.14 and Example 2.16 show how you can place the heap base at 0x20000 and the stack base at 0x40000. The stack and heap base locations can be altered by editing the addresses of the respective execution regions.

The disadvantage of this approach is that one word of SPACE (stack_base) is occupied above the stack region.

Figure 2.14. Placing symbols explicitly

Example 2.16. Placing symbols explicitly in a scatter file

LOAD_FLASH 0x24000000 0x04000000
{
    ; ...
    HEAP 0x20000 UNINIT
    {
        stackheap.o (heap)
    }

    STACKS 0x40000 UNINIT
    {
        stackheap.o (stacks)
    }
    ; ...
}

Utilizing linker generated symbols

This method requires that the stack and heap sizes are specified in an object file.

First, define areas of an appropriate size for the stack and heap in an assembler source file, for example, stackheap.s, as shown in Example 2.17.

Use the SPACE directive to reserve a zeroed block of memory. Set the NOINIT area attribute to prevent this zeroing.

During development, you might choose to zero-initialize the stack so that the maximum stack usage can be seen. Labels are not required in this source file.

Example 2.17. Placing sections for stack and heap

        AREA stack, DATA, NOINIT
    SPACE   0x3000 ; Reserve stack space

        AREA heap, DATA, NOINIT
    SPACE   0x3000 ; Reserve heap space

        END

You can then place these sections in their own execution region in the scatter-loading description file, as shown in Example 2.18.

Example 2.18. Placing sections for stack and heap

LOAD_FLASH 0x24000000 0x04000000
{
    :
    STACKS 0x1000 UNINIT     ; length = 0x3000
    {
        stackheap.o (stack)  ; stack = 0x4000 to 0x1000
    }

    HEAP 0x15000 UNINIT      ; length = 0x3000
    {
        stackheap.o (heap)   ; heap = 0x15000 to 0x18000
    }
}

The linker generates symbols that point to the base and limit of each execution region, that can be imported into the retargeting code to be used by __user_initial_stackheap():


Image$$STACKS$$ZI$$Limit = 0x4000
Image$$STACKS$$ZI$$Base  = 0x1000
Image$$HEAP$$ZI$$Base   = 0x15000
Image$$HEAP$$ZI$$Limit  = 0x18000

You can make this code more readable by using the DCD directive to give these values more meaningful names, as shown in Example 2.19.

Example 2.19. Using the DCD directive

        IMPORT          ||Image$$STACKS$$ZI$$Base||
        IMPORT          ||Image$$STACKS$$ZI$$Limit||
        IMPORT          ||Image$$HEAP$$ZI$$Base||
        IMPORT          ||Image$$HEAP$$ZI$$Limit||

    stack_base  DCD     ||Image$$STACKS$$ZI$$Limit||      ; = 0x4000
    stack_limit DCD     ||Image$$STACKS$$ZI$$Base||       ; = 0x1000

    heap_base   DCD     ||Image$$HEAP$$ZI$$Base||         ; = 0x15000
    heap_limit  DCD     ||Image$$HEAP$$ZI$$Limit||        ; = 0x18000

You can use these examples to place the heap base at 0x15000 and the stack base at 0x1000. You can then change the stack and heap base locations easily by editing the addresses of the respective execution regions.

Using the scatter file EMPTY attribute

This method uses the scatter file EMPTY attribute of the linker. This enables regions to be defined that contain no object code or data. This is a convenient method of defining a stack or heap. The length of the region is specified after the EMPTY attribute. In the case of a heap, that grows upwards in memory, the region length is positive. In the case of a stack, the region length is marked as negative, to indicate that it grows downwards in memory. Example 2.20 shows how to use the EMPTY attribute.

The benefit of this approach is that the size and position of the stack and heap is defined in one place, that is, in the scatter-loading description file. You do not have to create a stackheap.s file.

Example 2.20. Placing stack and heap regions using EMPTY

ROM_LOAD 0x24000000 0x04000000
{
    ...
    HEAP 0x30000 EMPTY 0x3000
    {
    }

    STACKS 0x40000 EMPTY -0x3000
    {
    }
    ...
}

At link time, the linker generates symbols to represent these EMPTY regions:


Image$$HEAP$$ZI$$Base      = 0x30000
Image$$HEAP$$ZI$$Limit     = 0x33000
Image$$STACKS$$ZI$$Base    = 0x3D000
Image$$STACKS$$ZI$$Limit   = 0x40000

Your application code can then process these symbols as shown in Example 2.21.

Example 2.21. Linker generated symbols representing EMPTY regions

                IMPORT      ||Image$$HEAP$$ZI$$Base||
                IMPORT      ||Image$$HEAP$$ZI$$Limit||

heap_base       DCD         ||Image$$HEAP$$ZI$$Base||
heap_limit      DCD         ||Image$$HEAP$$ZI$$Limit||

                IMPORT      ||Image$$STACKS$$ZI$$Base||
                IMPORT      ||Image$$STACKS$$ZI$$Limit||

stack_base      DCD         ||Image$$STACKS$$ZI$$Limit||
stack_limit     DCD         ||Image$$STACKS$$ZI$$Base||
Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203G
Non-Confidential