ARM Cortex-M Scatter Loading Working
Example
SITE HOME
Scatter-Loading Working Example.
In the Previous
Section, we learned the theory part of the scatter
loading and about XIP.
Let us now look at a very small practical self-contained example use
of scatter-loading.
The objective here is to place a user defined function called 'add'
at a specific location in the memory say at 0x3000_0000, using Scatter-loading
mechanism.
We will need the following:
- Bare Minimum 'startup.s'
: This will let us compile our C-code successfully
- 'datatypes.h'
: we will define some useful datatypes in this file.
- 'main.c'
: This will be our main c-code, which uses/calls a function
called 'add'.
- 'add.c'
: This will contain c-code for very simple 'add' function which
will just add 2 integers, and return the result of addition:
- 'scatter.sct'
: Scatter-Load file which will help us place the function 'add'
at a desired memory location, i.e. at 0x3000_0000
- Arm 'compiler/linker
commands' to successfully compile the source code.
You can
use any target processor to compile/link these files, we will
use cortex-m3 as the processor.
The 'main.c' will declare a 'extern' function called 'add'.
The full code for the 'add' function will be present in separate
file called 'add.c'.
We will compile the file 'main.c' and 'add.c'
separately to produce the respective object files 'c.o' and 'add.o'.
We will then compile the 'startup.s' file separately to
produce the object file 'a.o'
We will then write a simple 'scatter.sct' file, which will
instruct the linker to place the 'add.o' at a specific memory
location.
We will then 'link' the 3 above produced object files: 'c.o',
'add.o' and 'a.o' , using the 'scatter.sct'
scatter load file to produce a single binary executable called 'image.bin'.
We will then convert the binary file 'image.bin' into its
disassembly code, 'image.txt' to see how the function 'add'
has been placed.
We will then notice that the function 'add' has been placed at
0x3000_0000, as desired by the 'scatter.sct' file.
startup.s
Stack_Size EQU 0x00000401
AREA STACK,NOINIT,READWRITE,ALIGN=3
__stack_limit
Stack_Mem SPACE Stack_Size
__initial_sp
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD
Reset_Handler ; Reset Handler
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
Reset_Handler PROC
EXPORT Reset_Handler [Weak]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
EXPORT __stack_limit
EXPORT __initial_sp
END
datatypes.h
typedef unsigned int uint32_t;
#define CPU_SAU_REG_BASE ((uint32_t) 0xE000EDD0)
#define CPU_SCB_REG_BASE ((uint32_t) 0xE002ED08)
#define __IO
#define __RO
#define __RW
#define SCR *((uint32_t *) (0xE000ED10))
#define GPIO_1 *((uint32_t *) (0x20000ff0))
#define GPIO_2 *((uint32_t *) (0x20000df0))
#define GPIO_3 *((uint32_t *) (0x20000cf0))
#define GPIO_4 *((uint32_t *) (0x20000bf0))
#define GPIO_5 *((uint32_t *) (0x20000af0))
main.c
#include "datatypes.h"
extern int add(int a, int b);
void go_to_dsleep ()
{
SCR = 0x00000004; //bit 2 of SCR for deepsleep
__asm("WFE");
}
int main ()
{
int ii;
//write at location 0x40E0_0018, a value of
0x87654321
*((uint32_t *)0x40E00018) = 0x87654321;
asm("NOP");
GPIO_5 = 0x5a5a5a5a;
GPIO_4 = add(ii,ii);
go_to_dsleep();
while(1){}
}
add.c
#include "datatypes.h"
int add(int a, int b)
{
GPIO_4 = 0x44; This has no specific purpose
return a + b;
}
scatter.sct
LR_IROM1 0x10000000 0x00080000 {
RX_IRAM1 0x10000000 0x00010000 { ; load region
= execution region.
.ANY (+RW +RO)
}
RW_IRAM1 0x40000000 0x00010000 { ; RW data
.ANY (+RW +ZI)
}
RX_IRAM2 0x30000000 0x00010000 { ; Keep the add
function at 0x3000_0000
add.o
}
}
Compile commands:
Compile add.c to produce object
file add.o
/pkg/ARM/bin/armclang add.c -c --target=arm-arm-none-eabi
-mcpu=cortex-m3 -o add.o -O1
Compile main.c
to produce object file c.o
/pkg/ARM/bin/armclang main.c -c
--target=arm-arm-none-eabi -mcpu=cortex-m3 -o c.o -O1
Compile
startup.s to produce object file a.o
/pkg/ARM/bin/armasm startup.s --cpu=cortex-m3 -o a.o
Link 'a.o', 'c.o', 'add.o' to
produce '__image.axf'
/pkg/ARM/bin/armlink a.o c.o add.o --entry Reset_Handler
--scatter=scatter.sct --first __Vectors
Convert the
'__image.axf' file into disassembly text version
'image.txt'
/pkg/ARM/bin/fromelf --text -c -s -t -z --output image.txt
__image.axf
Produce
a 'hex' version of the file '__image.axf' called
'image.hex', just to see how the hex file looks like.
/pkg/ARM/bin/fromelf -cvf __image.axf --vhx --8x1 -o image.hex
Convert the '__image.axf' file to binary
executable file 'image.bin'.
/pkg/ARM/bin/fromelf --bin -o image.bin __image.axf
The above compile commands will produce binary executable called
'image.bin', and the disassembly file 'image.txt', full
disassembly file 'image.txt' can be seen here.
Note that the 'add' function has been placed at 0x3000_000, as
shown below:
add
0x30000000: f64032f0
@..2 MOVW r2,#0xbf0
0x30000004: f2c20200
.... MOVT r2,#0x2000
0x30000008:
2344
D# MOVS
r3,#0x44
0x3000000a:
6013
.` STR
r3,[r2,#0]
0x3000000c:
4408
.D ADD
r0,r0,r1
0x3000000e:
4770
pG
BX lr
You May also use Keil uVision to
compile this project. To use
scatter files with Keil uVision 5 Click Here.
For a
introductory Keil uVision 5 Tutorial, Click Here.
Click Here to Make Comments or
ask Questions
<=
PREV : Scatter Loading :
Next
=> No Next