链接器脚本加载与虚拟地址

时间:2011-10-20 04:54:22

标签: ld linker-scripts

我有以下链接器脚本,它应该链接代码以在基于闪存的微控制器上运行。 uC的地址为0x0,RAM为0x40000000。我想将数据部分放入flash中,但链接程序以便在RAM中完成对数据部分的访问。关键是,当控制器启动时,我会手动将它从闪存中复制到适当的RAM位置。

MEMORY 
{
    flash   : ORIGIN = 0x00000000, LENGTH = 512K
    ram : ORIGIN = 0x40000000, LENGTH = 32K
    usbram   : ORIGIN = 0x7FD00000, LENGTH = 8K
    ethram   : ORIGIN = 0x7FE00000, LENGTH = 16K
}

SECTIONS
{
    .text : { *(.text) } >flash
    __end_of_text__ = .;
    .data : 
    {
        __data_beg__ = .;
        __data_beg_src__ = __end_of_text__;
        *(.data)
        __data_end__ = .;
    } >ram AT>flash
    .bss : 
    {
        __bss_beg__ = .;
        *(.bss)
    } >ram
}

如上所示的代码生成以下输出:

40000000 <__data_beg__>:
40000000:   00000001    andeq   r0, r0, r1
40000004:   00000002    andeq   r0, r0, r2
40000008:   00000003    andeq   r0, r0, r3
4000000c:   00000004    andeq   r0, r0, r4
40000010:   00000005    andeq   r0, r0, r5
40000014:   00000006    andeq   r0, r0, r6

表示形式的数组

int foo[] = {1,2,3,4,5,6};

问题是它链接到0x40000000,而不是我想要的闪存区域。我期望链接器脚本的AT&gt; flash部分指定链接到flash,如LD手册中所述。

http://sourceware.org/binutils/docs/ld/Output-Section-Attributes.html#Output-Section-Attributes

这是我的ld调用:

arm-elf-ld  -T ./lpc2368.ld entry.o main.o -o binary.elf

感谢。

2 个答案:

答案 0 :(得分:1)

你的链接器脚本LINKS .data到RAM和LOADS .data到FLASH。这是由于AT命令。

为什么要将易失性数据链接到闪存?数据和Bss必须始终链接到RAM。您的链接描述文件非常正确。您只需将text和constand数据链接到flash中。

请查看您的地图文件。它必然会为数据变量分配一个RAM地址。

程序加载程序代码然后将data_beg_src中的副本(data_end - data_beg)字节复制到data_beg。

因此,作为数组的第一个数据被复制到SRAM的开头。

如果您需要将数据链接到Flash:

 Data :
  {
   *(.data);
  } > flash

Linker现在将LINK和LOAD .data链接到flash中。但如果我是你,我就不会这样做。

答案 1 :(得分:0)

您的.data虚拟地址= 0x40000000

您的.data逻辑地址= 0x00000000

这可以通过命令看到 Sections: Idx Name Size VMA LMA File off Algn 8 .data 00000014 40000000 00000000 00001000 2**2 CONTENTS, ALLOC, LOAD, DATA

int n;
Console.WriteLine("How many town names would you like to enter:");
n = int.Parse(Console.ReadLine());
string[] TownNames = new string[n];
Console.Clear();

int totalLength = 0; // holds total length of names
Console.WriteLine("Enter {0} town names:", n);
for (int i = 0; i < n; i++)
{
    Console.Write("Enter number {0}: ", i + 1);
    TownNames[i] = Convert.ToString(Console.ReadLine());

    totalLength += TownNames[i].Length; // add the name length to total
}

int average = totalLength/n; // calculate average

Console.Clear();
Console.WriteLine("town names lower than average length:");

for (int i = 0; i < n; i++)
{
    if (TownNames[i].Length < average) // print values when the length name is less than average.
    {
        Console.WriteLine("Town {0} : {1}", i + 1, TownNames[i]);
    }
}


Console.ReadKey(true);