我有以下链接器脚本,它应该链接代码以在基于闪存的微控制器上运行。 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
感谢。
答案 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);