Executable programs consist of a number of sections. Typically, there are program sections for code, initialized data, and zeroed data. There is often more than one code section and they must be placed at specific addresses in memory.

To describe how the program sections of your program are positioned in memory, the CrossWorks project system uses memory-map files and section-placement files. These XML-formatted files are described in Memory Map file format and Section Placement file format. They can be edited with the CrossWorks text editor. The memory-map file specifies the start address and size of target memory segments. The section-placement file specifies where to place program sections in the target's memory segments. Separating the memory map from the section-placement scheme enables a single hardware description to be shared across projects and also enables a project to be built for a variety of hardware descriptions.

For example, a memory-map file representing a device with two memory segments called FLASH and SRAM could look something like this in the memory-map editor.

<Root name="Device1">
  <MemorySegment name="FLASH" start="0x10000000" size="0x10000" />
  <MemorySegment name="SRAM" start="0x20000000" size="0x1000" />

A corresponding section-placement file will refer to the memory segments of the memory-map file and will list the sections to be placed in those segments. This is done by using a memory-segment name in the section-placement file that matches the corresponding memory-segment name in the memory-map file.

For example, a section-placement file that places a section called .stack in the SRAM segment and the .vectors and .text sections in the FLASH segment would look like this:

<Root name="Flash Section Placement">
  <MemorySegment name="FLASH" >
    <ProgramSection name=".vectors" load="Yes" />
    <ProgramSection name=".text" load="Yes" />
  </MemorySegment>
  <MemorySegment name="SRAM" >
   <ProgramSection name=".stack" load="No" />
  </MemorySegment>
</Root>

Note that the order of section placement within a segment is top down; in this example .vectors is placed at lower addresses than .text. The order memory segments are processed is bottom up; so in this example the sections in the SRAM segment will be placed prior to the sections in the FLASH segment.

Multiple memory segments can be specified by separating them with a semicolon. In the following example, the .stack section will be placed in the SRAM2 memory segment if it exists in the memory map, otherwise it will be placed in the SRAM memory segment. Sections can only be placed in one segment, they will not be placed in a second segment when the first is full.

<Root name="Flash Section Placement">
  <MemorySegment name="FLASH" >
    <ProgramSection name=".vectors" load="Yes" />
    <ProgramSection name=".text" load="Yes" />
  </MemorySegment>
  <MemorySegment name="SRAM2;SRAM" >
   <ProgramSection name=".stack" load="No" />
  </MemorySegment>
</Root>

The memory-map file and section-placement file to use for linkage can be included as a part of the project or, alternatively, they can be specified in the project's linker properties.

You can create a new program section using either the assembler or the compiler. For the C/C++ compiler, this can be achieved using __attribute__ on declarations. For example:

void foobar(void) __attribute__ ((section(".foo")));

This will allocate foobar in the section called .foo. Alternatively, you can specify the names for the code, constant, data, and zeroed-data sections of an entire compilation unit by using the Section Options properties.

You can now place the section into the section placement file using the editor so that it will be located after the vectors sections as follows:

<Root name="Flash Section Placement">
  <MemorySegment name="FLASH">
    <ProgramSection name=".vectors" load="Yes" />
    <ProgramSection name=".foo" load="Yes" />
    <ProgramSection name=".text" load="Yes" />
  </MemorySegment>
  <MemorySegment name="SRAM">
   <ProgramSection name=".stack" load="No" />
  </MemorySegment>
</Root>

If you are modifying a section-placement file that is supplied in the CrossWorks distribution, you will need to import it into your project using the Project Explorer.

Sections containing code and constant data should have their load property set to Yes. Some sections don't require any loading, such as stack sections and zeroed-data sections; such sections should have their load property set to No.

Some sections that are loaded then need to be copied to sections that aren't yet loaded. This is required for initialized data sections and to copy code from slow memory regions to faster ones. To do this, the runin attribute should contain the name of a section in the section-placement file to which the section will be copied.

For example, initialized data is loaded into the .data section and then is copied into the .data_run section using:

<Root name="Flash Section Placement">
  <MemorySegment name="FLASH">
    <ProgramSection name=".vectors" load="Yes" />
    <ProgramSection name=".text" load="Yes" />
    <ProgramSection name=".data" load="Yes" runin=".data_run" />
  </MemorySegment>
  <MemorySegment name="SRAM">
    <ProgramSection name=".data_run" load="No" />
    <ProgramSection name=".stack" load="No" />
  </MemorySegment>
</Root>

The startup code will copy the contents of the .data section to the .data_run section. To enable this, symbols named __section-name_start__, __section-name_end__, __section-name_load_start__ and __section-name_load_end__ are generated marking the section start, end, load start and load end addresses of each section. The startup code uses these symbols to copy the sections from their load positions to their run positions.

You can also create your own load and run section, for example the following placement file adds a .mydata section:

<Root name="Flash Section Placement">
  <MemorySegment name="FLASH">
    <ProgramSection name=".vectors" load="Yes" />
    <ProgramSection name=".text" load="Yes" />
    <ProgramSection name=".data" load="Yes" runin=".data_run" />
    <ProgramSection name=".mydata" load="Yes" runin=".mydata_run" />
  </MemorySegment>
  <MemorySegment name="SRAM">
    <ProgramSection name=".data_run" load="No" />
    <ProgramSection name=".mydata_run" load="No" />
    <ProgramSection name=".stack" load="No" />
  </MemorySegment>
</Root>

As the startup code doesn't know about this section, the following code will need to be added to the program to initialise the section:

/* Section image located in flash */
extern const unsigned char __mydata_load_start__[];
extern const unsigned char __mydata_load_end__[];

/* Where to locate the section image in RAM. */
extern unsigned char __mydata_start__[];
extern unsigned char __mydata_end__[];

...

/* Copy image from flash to RAM. */
memcpy(__mydata_start__, 
       __mydata_load_start__,
       __mydata_end__ - __mydata_start__);