Gcc 裸机ARM链接器脚本:如何将初始化数据从ROM重新定位到RAM?

Gcc 裸机ARM链接器脚本:如何将初始化数据从ROM重新定位到RAM?,gcc,linker,arm,gnu,linker-scripts,Gcc,Linker,Arm,Gnu,Linker Scripts,我想把全局变量的初始值放在ROM部分,然后重新定位它们的地址并将它们的值复制到RAM中(这样程序就可以编辑) 我的链接器脚本部分: /* code */ .text : { __text_start = .; *(.text) __text_end = .; } > ROM /* Initialized global and static variables */ .data : AT ( __text_end ) { __data_start =

我想把全局变量的初始值放在ROM部分,然后重新定位它们的地址并将它们的值复制到RAM中(这样程序就可以编辑)

我的链接器脚本部分

/* code */
.text :
{
    __text_start = .;
    *(.text)
    __text_end = .;
} > ROM



/* Initialized global and static variables */
.data : AT ( __text_end )
{ 
    __data_start = . ; 
    *(.data); 
    __data_end = . ;  
} > RAM
int global_var = 0xAAA;

void main()
{
    global_var = 0xBBB;
}
我的启动ROM代码

/* code */
.text :
{
    __text_start = .;
    *(.text)
    __text_end = .;
} > ROM



/* Initialized global and static variables */
.data : AT ( __text_end )
{ 
    __data_start = . ; 
    *(.data); 
    __data_end = . ;  
} > RAM
int global_var = 0xAAA;

void main()
{
    global_var = 0xBBB;
}
问题:初始值
0xAAA
位于编译的bin文件中的
RAM
地址,而不是
ROM

如何在ROM中定义初始数据值,然后将其地址重新定位到RAM

感谢您的帮助

看看关于内存布局和链接的全面说明

您必须添加相关的启动代码,通过ROM中的RAM部分复制到RAM中的目的地,并初始化C运行时环境(zeroning.bss等)。网络中有大量的示例,通常由SDK提供,与同样提供的链接器脚本相匹配,因为这些文件必须匹配

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
在引导过程中进行双重检查

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

幸运或不幸的是,GNULD提供了不止一种方法来解决这个问题,正如您已经开始用链接器脚本演示的那样。同时,GNULD使它成为解决这个问题的一个PITA,它对放置某物的位置/方式非常敏感。;您将看到各种不同的示例,但它们似乎都有效

还请注意,这些名称也不重要:

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

嗨,我有一个从ROM到RAM复制数据的启动代码。。我的问题是,链接器脚本没有将初始数据放在ROM中(而是放在它应该重新定位到的RAM区域),我不明白为什么以及我在链接器脚本中写错了什么好。然后阅读链接的文章,它很好地解释了这一点,并提供了一些例子。
} > RAM AT > ROM