Placing data at a specific memory address with Segger Embedded Studio

This blog is to introduce a method how to place data at the specific memory address with Segger Embedded Studio.

The only solution to place a symbol at a given address, is to place it into a separate section.

If you create one section per “fixed address” symbol, it is guaranteed that the symbol is at the start of that section. You can supply a start address (and optionally even the size) to a section.

To place an unitialized symbol in RAM use:

  <MemorySegment name="$(RAM_NAME:RAM);SRAM">
    [...]
    <ProgramSection alignment="4" load="No" name=".MyVar" start="0x20010000" />
    [...]
  </MemorySegment>

To place a constant symbol in Flash use:

  <MemorySegment name="$(FLASH_NAME:FLASH)">
[...]
    <ProgramSection alignment="4" load="Yes" name=".MyVar" start="0x00010000" />
[...]
  </MemorySegment>

To place a symbol in RAM that should be initialized by startup, use:

  <MemorySegment name="$(FLASH_NAME:FLASH)">
[...]
    <ProgramSection alignment="4" load="Yes" runin=".MyVar_run" name=".MyVar" />
[...]
  </MemorySegment>
  <MemorySegment name="$(RAM_NAME:RAM);SRAM">
[...]
    <ProgramSection alignment="4" load="No" name=".MyVar_run" start="0x20010000" />
[...]
  </MemorySegment>
  ldr r0, =__MyVar_load_start__
  ldr r1, =__MyVar_start__
  ldr r2, =__MyVar_end__
  bl memory_copy

and copy from .MyVar to .MyVar_run in crt0 (thumb_crt0.s, before /* zero the bss. */)

You can then use attribute((section(“.MyVar”))) to place a symbol into that section at the address given by the start attribute.

Reference from Segger Embedded Studio (Documentation)

https://studio.segger.com/index.htm?https://studio.segger.com/ide_section_placement.htm

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 SEGGER Embedded Studio for ARM 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 SEGGER Embedded Studio for ARM 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 options.

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 options.

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 SEGGER Embedded Studio for ARM distribution, you will need to import it into your project using the Project Explorer.

Sections containing code and constant data should have their load project option set to Yes. Some sections don’t require any loading, such as stack sections and zeroed-data sections; such sections should have their load project option 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__);

One thought on “Placing data at a specific memory address with Segger Embedded Studio

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.