gcc ROM中的链接器脚本RAM初始化

yfwxisqw  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(108)

我目前正在编写我自己的链接器脚本来执行裸机RISC-V程序。我想把RAM中的全局变量的初始值放在ROM中(如果可能的话,准确地放在地址 _idata 处)(在 Boot 时,程序将负责把不同的值从ROM复制到RAM)。为此,我使用VMA/LMA机制。
下面是我的链接器脚本:

MEMORY
{
  ROM      (rx)  : ORIGIN = 0x00004000, LENGTH = 0x00004000
  RAM      (rwx) : ORIGIN = 0x00008000, LENGTH = 0x00004000
}

STACK_SIZE  = 0x3000;
BOOT_PC     = 0x1000;

/* Section Definitions */
SECTIONS
{  

  /* Code and constants */
  .text :
  {
    _stext = . ;
    *(.rodata*);
    *(.srodata*);
    *(.text*);
    _etext = . ;
    . = ALIGN(8);
    /* Initial data of RAM */
    _idata = . ;
  } > ROM

  /* Initialized data */
  /* Relocate in ROM */
  .data : AT (_idata)
  {
    . = ALIGN(8);
    _sdata = . ;
    *(.sdata .sdata.* .sdata2.*)
    *(.data .data.*)
    _edata = . ;
    . = ALIGN(8);
  } > RAM 

  /* Unitialized data */
  .bss (NOLOAD) :
  {
    . = ALIGN(8);
    _sbss = . ;
    *(.bss*);
    *(.sbss*);
    *(COMMON);
    _ebss = . ;
    . = ALIGN(8);
  } > RAM

  /* Stack */
  .stack (NOLOAD):
  {
    . = ALIGN(8);
    . = . + STACK_SIZE;
    . = ALIGN(8);
    _stack = . ;
  } > RAM
}

下面是我的基本C程序测试:

int d1 = 0x42;
const int d2 = 0x40;
int d3 = 0x35;

int main () {
  return 0;
}

然而,令我惊讶的是,初始值仍然放在RAM中(除了 d2 常量):

00004000 <d2>:
    4000:   0040                    .2byte  0x40
    ...

00004004 <main>:
    4004:   00000513            li  x10,0
    4008:   00008067            ret

0000400c <_etext>:
    400c:   0000                    .2byte  0x0
    ...

Disassembly of section .data:

00008000 <d3>:
    8000:   0035                    .2byte  0x35
    ...

00008004 <d1>:
    8004:   0042                    .2byte  0x42
    ...

有人能给我解释一下我做错了什么吗?我读了following information,我也测试了语法**〉RAM AT〉ROM**,但仍然没有成功...

1yjd4xko

1yjd4xko1#

您需要复制它作为启动。

_sidata = LOADADDR(.data);

/* ... */
  .data : 
  {
    . = ALIGN(8);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> ROM

最好是有一个单独的启动C代码,但作为一种解决方法,您可以使用gcc constructor

extern uint8_t _sdata[];
extern uint8_t _edata[];
extern uint8_t _sidata[];

static void __attribute__((constructor)) copyRAMfunctions(void)
{
    memcpy(_sdata, _sidata, _edata - sdata);
}

相关问题