5.3. Memory Layout

Boards supported by CS3 can have multiple banks or regions of memory with different characteristics. This section describes how program sections are mapped onto memory regions, and how you can use these CS3 features to customize placement of your program's code or data in memory. CS3 also provides a uniform set of symbolic names for each region, allowing you to programmatically refer to each region's address range from C or assembly language as well as from the linker script.

5.3.1. Memory Regions and Program Sections

The regions that are available on a particular board are listed in the table for that board in Section 5.5, “Supported Boards for ARM EABI”, below. There are two kinds of regions: those documented as "Memory regions", which are general-purpose memory banks that can be used for program or data storage; and those documented as "Other regions", which typically correspond to memory-mapped control registers or other special-purpose storage.

CS3 supports boards that include both ram and rom memory regions. The ram region holds the .data and .bss sections, and the .text section in RAM profiles. In ROM profiles, the rom region holds the .text section and initialization values for the writable data sections.

In addition, all regions documented as "Memory regions" correspond to similarly-named program sections. For example, the linker script assigns the .ram section to the ram region.

More generally, for a memory region named R, CS3 linker scripts define a section named .R, which may contain initialized data or code. There is also a section named .bss.R for zero-initialized data (BSS), which is placed after the initialized data section for this region.

You can explicitly locate data or code in a section corresponding to a particular memory region using section attributes in your source C or C++ code. Section attributes are especially useful on code compiled for boards that include special memory banks, such as a fast on-chip cache memory, in addition to the default ram and/or rom regions. CS3's start-up code arranges for additional data-like sections to be initialized in the same way as the default .data section.

As an example to illustrate the attribute syntax, you can put a variable v in the .ram section using:

int v __attribute__ ((section (".ram")));

To declare a function f in this section, use:

int f (void) __attribute__ ((section (".ram"))) {...}

For more information about attribute syntax, see the GCC manual.

In addition to the .R and .bss.R sections, CS3 places a .cs3.region-head.R section at the beginning of each region R. Explicitly placing data in .cs3.region-head.R sections is discouraged, because CS3 itself may want to place items (like interrupt vector tables) at these locations. If there is a conflict, CS3 raises an error at link time.

Regions documented as "Other regions" in the tables in Section 5.5, “Supported Boards for ARM EABI” do not have corresponding program sections. Typically, these regions contain memory-mapped control and I/O registers and cannot be used for general data or program storage. If your program needs to manipulate data in these regions, you can use the CS3 memory map access interface declared in cs3.h, as described in Section 5.3.2, “Programmatic Access to the CS3 Memory Map”.

Memory maps for boards supported by Sourcery CodeBench Lite for ARM EABI are documented in XML files in the arm-none-eabi/lib/boards/ subdirectory of your Sourcery CodeBench installation directory.

5.3.2. Programmatic Access to the CS3 Memory Map

CS3 makes C declarations describing the memory regions on the target board available to your program via the header file cs3.h, which you can find in the arm-none-eabi/include directory within your install.

For each region named R, cs3.h declares a byte array variable __cs3_region_start_R at the region's start address, and a size_t variable __cs3_region_size_R to represent the total size of the region. These symbols are defined by the linker script and so may also be referenced from assembly language. Note that all regions are aligned on eight-byte boundaries and sizes are also multiples of eight bytes.

For memory regions that can correspond to program sections (as described in Section 5.3.1, “Memory Regions and Program Sections”), there are additional symbols __cs3_region_init_R and __cs3_region_init_size_R that describe constant data used to initialize the region. During the C initialization phase (Section 5.2, “Program Startup and Termination”), this data is copied into the lower part of the memory region. The symbol __cs3_region_zero_size_R represents the size of the zero-initialized .bss.R section following the initialized data. Any of these identifiers may actually be defined as a preprocessor macro that expands to an expression of the appropriate type and value.

To perform the memory region initializations during startup, CS3 internally uses the array variable __cs3_regions, which contains descriptors for all of the writable (RAM) memory regions. These descriptors are also exposed in cs3.h; refer to the header file for details.

5.3.3. Heap and Stack Placement

CS3 linker scripts provide default placement of the heap and stack in the RAM region. However, you can override the defaults by providing your own definitions of the associated CS3 variables. For example, you may put the heap and/or stack in some other memory region.

Heap placement is controlled by defining the symbol __cs3_heap_start at the beginning of the heap, and either the symbol __cs3_heap_end or the pointer variable __cs3_heap_limit to mark the end of the heap. For example, this fragment of C code places the heap in a region named extsram:

#define HEAPSIZE ...  /* However big you want to make it. */
unsigned char __cs3_heap_start[HEAPSIZE] 
    __attribute__ ((section (".bss.extsram"), aligned(8)));
unsigned char *__cs3_heap_limit = __cs3_heap_start + HEAPSIZE;

The default initial stack pointer for bare-metal profiles is given by the symbol __cs3_stack, and the stack grows downward from this address. Stack initialization is discussed in more detail in Section 5.2.2, “The Assembly Initialization Phase”.

You can find C declarations for the CS3 heap and stack symbols in the header file cs3.h.

The cs3.h header file also defines a macro for creating a custom stack. The custom stack is created as a block of RAM in the zero-initialized data section (BSS). The specified size must be a compile-time constant. To account for alignment, the final size of the stack may be a few bytes less than the requested size. The symbol __cs3_stack is initialized to point to the last extent of the stack block, and is 16-byte aligned. For example, the following fragment of C code creates a stack of 8192 bytes:

#include <cs3.h>

CS3_STACK(2 * 4096);

As indicated in Section 5.2.2, “The Assembly Initialization Phase”, there are cases where a boot monitor or simulator overrides a custom stack.