Now that we know, how to write linker scripts, we will attempt to
write a program, and place the .data section in RAM.
The add program is modified to load two values from RAM, add them and
store the result back to RAM. The two values and the space for result
is placed in the .data section.
Listing 9. Add Data in RAM
.data
val1: .4byte 10 @ First number
val2: .4byte 30 @ Second number
result: .4byte 0 @ 4 byte space for result
.text
.align
start:
ldr r0, =val1 @ r0 = &val1
ldr r1, =val2 @ r1 = &val2
ldr r2, [r0] @ r2 = *r0
ldr r3, [r1] @ r3 = *r1
add r4, r2, r3 @ r4 = r2 + r3
ldr r0, =result @ r0 = &result
str r4, [r0] @ *r0 = r4
stop: b stopWhen the program is linked, the linker script shown below is used.
SECTIONS {
. = 0x00000000;
.text : { * (.text); }
. = 0xA0000000;
.data : { * (.data); }
}The dump of the symbol table of .elf is shown below.
$ arm-none-eabi-nm -n add-mem.elf
00000000 t start
0000001c t stop
a0000000 d val1
a0000001 d val2
a0000002 d resultThe linker script seems to have solved the problem of placing the
.data section in RAM. But wait, the solution is not complete yet!
RAM is volatile memory, and hence it is not possible to directly make the data available in RAM, on power up.
All code and data should be stored in Flash before power-up. On
power-up, a startup code is supposed to copy the data from Flash to
RAM, and then proceed with the execution of the program. So the
program’s .data section has two addresses, a load address in Flash
and a run-time address in RAM.
![]() | Tip |
|---|---|
In |
The following two modifications have to be done, to make the program work correctly.
.data section.
.data section from Flash
(load address) to RAM (run-time address).
The run-time address is what that should be used for determining the
address of labels. In the previous linker script, we have specified
the run-time address for the .data section. The load address is not
explicitly specified, and defaults to the run-time address. This is
OK, with the previous examples, since the programs were executed
directly from Flash. But, if data is to be placed in RAM during
execution, the load address should correspond to Flash and the
run-time address should correspond to RAM.
A load address different from the run-time address can be specified
using the AT keyword. The modified linker script is shown below.
SECTIONS {
. = 0x00000000;
.text : { * (.text); }
etext = .; ❶
. = 0xA0000000;
.data : AT (etext) { * (.data); } ❷
}
Symbols can be created on the fly within the SECTIONS command by
assigning values to them. Here etext is assigned the value of the
location counter at that position. etext contains the address of the
next free location in Flash right after all the code. This will be
used later on to specify where the .data section is to be placed in
Flash. Note that etext itself will not be allocated any memory, it
is just an entry in the symbol table.
| |
The AT keyword specifies the load address of the .data
section. An address or symbol (whose value is a valid address) could
be passed as argument to AT. Here the load address of .data is
specified as the location right after all the code in Flash.
|
To copy the data from Flash to RAM, the following information is required.
flash_sdata)
ram_sdata)
.data section. (data_size)
With this information the data can be copied from Flash to RAM using the following code snippet.
ldr r0, =flash_sdata
ldr r1, =ram_sdata
ldr r2, =data_size
copy:
ldrb r4, [r0], #1
strb r4, [r1], #1
subs r2, r2, #1
bne copyThe linker script can be slightly modified to provide these information.
| Start of data in Flash is right after all the code in Flash. | |
| Start of data in RAM is at the base address of RAM. | |
| Obtaining the size of data is not straight forward. The data size is calculated from the difference in the start of data in RAM and the end of data in RAM. Yes, simple expressions are allowed within the linker script. |
The add program with data copied to RAM from Flash is listed below.
Listing 11. Add Data in RAM (with copy)
.data
val1: .4byte 10 @ First number
val2: .4byte 30 @ Second number
result: .space 4 @ 1 byte space for result
.text
;; Copy data to RAM.
start:
ldr r0, =flash_sdata
ldr r1, =ram_sdata
ldr r2, =data_size
copy:
ldrb r4, [r0], #1
strb r4, [r1], #1
subs r2, r2, #1
bne copy
;; Add and store result.
ldr r0, =val1 @ r0 = &val1
ldr r1, =val2 @ r1 = &val2
ldr r2, [r0] @ r2 = *r0
ldr r3, [r1] @ r3 = *r1
add r4, r2, r3 @ r4 = r2 + r3
ldr r0, =result @ r0 = &result
str r4, [r0] @ *r0 = r4
stop: b stopThe program is assembled and linked using the linker script listed in Listing 10, “Linker Script with Section Copy Symbols”. The program is executed and tested within Qemu.
qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null
(qemu) xp /4dw 0xA0000000
a0000000: 10 30 40 0![]() | Note |
|---|---|
In a real system with an SDRAM, the memory should not be accessed right-away. The memory controller will have to be initialised before performing a memory access. Our code works because the simulated memory does not require the memory controller to be initialised. |