I would like to put initial values of global variables in ROM section, and then, relocate their addresses and copy their values to RAM (so it can be edited by the program).
My linker script SECTIONS:
/* code */
.text :
{
__text_start = .;
*(.text)
__text_end = .;
} > ROM
/* Initialized global and static variables */
.data : AT ( __text_end )
{
__data_start = . ;
*(.data);
__data_end = . ;
} > RAM
My Boot ROM code:
int global_var = 0xAAA;
void main()
{
global_var = 0xBBB;
}
The problem: The initial value 0xAAA
is located at RAM
address in the compiled bin file instead of ROM
How can I define initial .data values in ROM, and then relocate their address to RAM?
Thank you for your help
int global_var = 0xAAA;
int global_too;
void main()
{
global_var = 0xBBB;
}
MEMORY
{
bob : ORIGIN = 0x08000000, LENGTH = 0x100
ted : ORIGIN = 0x20000000, LENGTH = 0x100
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
.data : { *(.data*) } > ted AT > bob
.bss : { *(.bss*) } > ted AT > bob
}
Disassembly of section .text:
08000000 <reset-0x8>:
8000000: 20000400
8000004: 08000009
08000008 <reset>:
8000008: f000 f802 bl 8000010 <main>
800000c: e7fe b.n 800000c <reset+0x4>
...
08000010 <main>:
8000010: 4b01 ldr r3, [pc, #4] ; (8000018 <main+0x8>)
8000012: 4a02 ldr r2, [pc, #8] ; (800001c <main+0xc>)
8000014: 601a str r2, [r3, #0]
8000016: 4770 bx lr
8000018: 20000000
800001c: 00000bbb
Disassembly of section .data:
20000000 <global_var>:
20000000: 00000aaa
Disassembly of section .bss:
20000004 <global_too>:
20000004: 00000000
and if you really want/need .data or .bss then continue and add something like this
MEMORY
{
bob : ORIGIN = 0x08000000, LENGTH = 0x100
ted : ORIGIN = 0x20000000, LENGTH = 0x100
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
__data_rom_start__ = .;
.data :
{
__data_start__ = .;
*(.data*)
__data_end__ = .;
} > ted AT > bob
.bss :
{
__bss_start__ = .;
*(.bss*)
__bss_end__ = .;
} > ted AT > bob
}
In bootstrap to double check
.align
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __bss_start__
.word __bss_end__
Disassembly of section .text:
08000000 <reset-0x8>:
8000000: 20000400
8000004: 08000009
08000008 <reset>:
8000008: f000 f80c bl 8000024 <main>
800000c: e7fe b.n 800000c <reset+0x4>
800000e: 46c0 nop ; (mov r8, r8)
8000010: 08000034
8000014: 20000000
8000018: 20000004
800001c: 20000004
8000020: 20000008
08000024 <main>:
8000024: 4b01 ldr r3, [pc, #4] ; (800002c <main+0x8>)
8000026: 4a02 ldr r2, [pc, #8] ; (8000030 <main+0xc>)
8000028: 601a str r2, [r3, #0]
800002a: 4770 bx lr
800002c: 20000000
8000030: 00000bbb
Disassembly of section .data:
20000000 <global_var>:
20000000: 00000aaa
Disassembly of section .bss:
20000004 <global_too>:
20000004: 00000000
8000010: 08000034
8000014: 20000000
8000018: 20000004
800001c: 20000004
8000020: 20000008
arm-none-eabi-nm so.elf
20000008 B __bss_end__
20000004 B __bss_start__
20000004 D __data_end__
08000034 T __data_rom_start__
20000000 D __data_start__
20000004 B global_too
20000000 D global_var
08000024 T main
08000008 t reset
hexdump -C so.bin
00000000 00 04 00 20 09 00 00 08 00 f0 0c f8 fe e7 c0 46 |... ...........F|
00000010 34 00 00 08 00 00 00 20 04 00 00 20 04 00 00 20 |4...... ... ... |
00000020 08 00 00 20 01 4b 02 4a 1a 60 70 47 00 00 00 20 |... .K.J.`pG... |
00000030 bb 0b 00 00 aa 0a 00 00 |........|
00000038
And you can see the 0x00000aaa at offset 0x34 in the file.
Then fill in the bootstrap to copy .data from flash to ram and to zero .bss using these tool generated addresses.
I have no use for .data and make no assumptions about .bss so mine looks like this
reset:
bl main
b .
MEMORY
{
bob : ORIGIN = 0x08000000, LENGTH = 0x100
ted : ORIGIN = 0x20000000, LENGTH = 0x100
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
.bss : { *(.bss*) } > ted
}
YMMV
Fortunately or unfortunately gnu ld provides more than one way to solve this problem as you have started to demonstrate with your linker script. At the same time gnu ld makes it a PITA to figure this out, very sensitive to where/how to place the something = .; You will see various different examples yet they all seem work.
And also note these names do not matter either:
MEMORY
{
bob : ORIGIN = 0x08000000, LENGTH = 0x100
ted : ORIGIN = 0x20000000, LENGTH = 0x100
}
SECTIONS
{
.hello : { *(.text*) } > bob
.world : { *(.data*) } > ted AT > bob
}
Disassembly of section .hello:
08000000 <reset-0x8>:
8000000: 20000400
8000004: 08000009
08000008 <reset>:
8000008: f000 f802 bl 8000010 <main>
800000c: e7fe b.n 800000c <reset+0x4>
...
08000010 <main>:
8000010: 4b01 ldr r3, [pc, #4] ; (8000018 <main+0x8>)
8000012: 4a02 ldr r2, [pc, #8] ; (800001c <main+0xc>)
8000014: 601a str r2, [r3, #0]
8000016: 4770 bx lr
8000018: 20000000
800001c: 00000bbb
Disassembly of section .world:
20000000 <global_var>:
20000000: 00000aaa
hexdump -C so.bin
00000000 00 04 00 20 09 00 00 08 00 f0 02 f8 fe e7 00 00 |... ............|
00000010 01 4b 02 4a 1a 60 70 47 00 00 00 20 bb 0b 00 00 |.K.J.`pG... ....|
00000020 aa 0a 00 00 |....|
00000024
Still produces the desired binary.
short answer:
Try this
} > RAM AT > ROM