一、链接配置(非必要)
1.符号变量的定义
STACK_SIZE = 0x200;
2.输出格式
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
3.入口地址
ENTRY(Reset_Handler)
即设置一个入口函数,启动后PC指针指向这个函数,然后首先运行这个函数。
二、内存布局
MEMORY
{
/* Define each memory region */
BOARD_FLASH (rx) : ORIGIN = 0x60000000, LENGTH = 0x800000 /* 8M bytes (alias Flash) */
SRAM_DTC (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000 /* 128K bytes (alias RAM) */
SRAM_ITC (rwx) : ORIGIN = 0x0, LENGTH = 0x20000 /* 128K bytes (alias RAM2) */
SRAM_OC (rwx) : ORIGIN = 0x20200000, LENGTH = 0xc0000 /* 768K bytes (alias RAM3) */
BOARD_SDRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x1e00000 /* 30M bytes (alias RAM4) */
NCACHE_REGION (rwx) : ORIGIN = 0x81e00000, LENGTH = 0x200000 /* 2M bytes (alias RAM5) */
}
脚本以MEMORY命令定义储存空间,其中ORIGIN定义空间的起始地址,LENGTH定义空间的长度。
LENGTH的作用在于如果超过了这个长度,IDE编译时有报错提示。
三、段链接定义
1.SECTIONS命令的基本语法
SECTIONS
{
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{
contents
} >region :phdr =fill
...
}
这是SECTIONS的基本语法,只有secname 和 contents 是必须的。其中secname可以自己任意命名。contents为各个段,系统有默认的段,常见有.text段,.rodata段,.data段,.bss段。
不同的开发环境段名不同,如keil中,表示这些段的名字不同,但基本功能都是相同的。
2.start AT的说明
start是执行的开始地址,AT是加载地址。
SECTIONS
{
.data 0x20000000 : AT 0x800
{
*(.data)
}
}
这个命令表示,所有文件的.data段从地址0x800加载,但是运行时从地址0x20000000取数据执行。
这个用法通常需要在启动文件中写一段将地址0x800的上的数据拷贝到0x20000000的代码,这样就把.data段从FLASH中拷贝到了RAM中。从而.data段的数据可以进行读写。需要注意的是这个地址是cpu统一编制的地址,即映射之后的地址。此例中,在cpu看来0x800对应FLASH的地址空间,0x20000000对于RAM的地址空间。
另外一种写法:
SECTIONS
{
. = ALIGN(4) ;
.data:
{
*(.data)
} > BOARD_FLASH AT>SRAM_OC
}
3.ALIGN
.=ALIGN(4)
表示从‘.’开始,后面的空间以4字节对齐。
四、定位符号‘.’
符号‘.’表示当前位置计数器的值,他表示的是一个相对于某空间区域的地址,他的绝对地址为某空间区域的地址加‘.’的值。可以用ABSOLUTE(.)表示绝对地址。它的初始值为0,每分配一段空间,它的值会加上这段空间的大小。
.boot_hdr : ALIGN(4)
{
FILL(0xff)
__boot_hdr_start__ = ABSOLUTE(.) ;
KEEP(*(.boot_hdr.conf))
. = 0x1000 ;
KEEP(*(.boot_hdr.ivt))
. = 0x1020 ;
KEEP(*(.boot_hdr.boot_data))
. = 0x1030 ;
KEEP(*(.boot_hdr.dcd_data))
__boot_hdr_end__ = ABSOLUTE(.) ;
. = 0x2000 ;
} >BOARD_FLASH