Keil Logo

ARMLINK: Using Linker Scatter File for Buffer Management


To use ExecutionRegions in your scatter file to reserve memory for buffers which are referenced in your code, linker-defined symbols can be used. For a more advanced usage, the scatter file can be pre-processed with the ARMCC which allows using #define and importing header files for configuration. This technique is explained in this article.

Using a custom scatter file

µVision creates a scatter file using the information from the dialog Options for Target -> Target. The automatic creation of the scatter file can be enabled or disabled in the dialog Options for Target -> Linker with the option Use Memory Layout from Target dialog. When disabled, you can define a custom scatter file in the field Scatter File. By default, µVision suggests the scatter file that was generated in a previous build. Open the scatter file directly in µVision with the button Edit...

The scatter file

First, we take a look to the default scatter file created by µVision:

LR_IROM1 0x08000000 0x00080000  {
  ER_IROM1 0x08000000 0x00080000  {
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00010000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

Add a new ExecutionRegion to define an empty buffer (refer to Syntax of an execution region description). For example:

LR_IROM1 0x08000000 0x00080000  {
  ...
  Buffer1 [start_adr]  EMPTY [size] {}
}

The above line creates a buffer starting at [start_adr] with size of [size]. The attribute EMPTY reserves an empty memory block of a given size in the execution region. No section can be placed in a region with the attribute EMPTY. This is not a limitation, but protects this region from assignments.

The attribute EMPTY also force the section to be uninitialized.

Importing linker-defined symbols in your code

You can access the ExecutionRegion Buffer1 with the following code, which refers to the linker-defined symbol for this region:

extern unsigned int Image$$Buffer1$$Base;
extern unsigned int Image$$Buffer1$$ZI$$Length;

The first line extern unsigned int Image$$Buffer1$$Base; imports the linker-defined symbol which refers the Base address of the ExecutionRegion. The second line, extern unsigned int Image$$Buffer1$$ZI$$Length; refers the to the length of the ExecutionRegion.

Because Image$$Buffer1$$Base and Image$$Buffer1$$ZI$$Length are symbols with an address, you need to use the "address (&)-operator" to get the value. For example:

unsigned int Buffer1_adr = (unsigned int)&Image$$Buffer1$$Base;
unsigned int Buffer1_length = (unsigned int)&Image$$Buffer1$$ZI$$Length;

Now, this symbol can be used with other commands. For example, with a memset command to initialize the buffer with a value:

memset((void *)Buffer1_adr, 0xAA, (size_t)Buffer1_length);

Linker-defined symbols can be used directly without creating an object

memset((void *)&Image$$Buffer1$$Base, 0xAA, (size_t)&Image$$Buffer1$$ZI$$Length);

Pre-process scatter files

The linker can invoke the ARMCC for pre-processing the scatter file. For this, add the following code to the first line of the scatter file:

#! armcc -E

The linker calls the ARMCC with the give parameter. The parameter -E intruct the compiler to execute only the pre-processor step.

When pre-processing the scatter file with ARMCC, you can use the directive #define as shown in the example below:

#! armcc -E

#define BUFFER1_START 0x20000000
#define BUFFER1_SIZE 0x1000

LR_IROM1 0x08000000 0x00080000  {
  ...
  Buffer1 BUFFER1_START EMPTY BUFFER1_SIZE {}
  ...
}

The #define statements can be put into a header (for example, config.h). If you are using #include statements in the scatter file to include header files, then you need to add -I and an include path. Otherwise ARMCC will not find the include file. Example of a header file config.h:

#ifndef __CONFIG_H
#define __CONFIG_H

#define BUFFER1_START 0x20000000
#define BUFFER1_SIZE 0x1000

#endif

Now, the header file can be included in the scatter file

#! armcc -E -I .\cfg

#include "config.h"

LR_IROM1 0x08000000 0x00080000  {
  ...
  Buffer1 BUFFER1_START EMPTY BUFFER1_SIZE {}
  ...
}

As you can see, in the first line, -I .\cfg has been added to the ARMCC command line. This is required because the config.h is placed in the .\cfg. Therefore, an include file path needs being set.

See Also

FORUM THREADS

The following Discussion Forum threads may provide information related to this topic.

Last Reviewed: Tuesday, April 4, 2017


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.