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 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_load 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" 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 need to copy the contents of the .data_load section to the .data_run section. To enable this, symbols are generated marking the start and end addresses of each section. For each section, a start symbol called __section-name_start__ and an end symbol called __section-name_end__ are generated. These symbols can be used to copy the sections from their load positions to their run positions.
For example, the .data_load section can be copied to the .data_run section using the following call to memcpy.
/* Section image located in flash */ extern const unsigned char __data_load_start__; extern const unsigned char __data_load_end__; /* Where to locate the section image in RAM. */ extern unsigned char __data_run_start__; extern unsigned char __data_run_end__; /* Copy image from flash to RAM. */ memcpy(__data_run_start__, __data_load_start__, __data_load_end__ - __data_load_start__);