MDK 分散加载文件分析


1.1 Realview MDK链接程序的两种方式


使用RealviewMDK时不可避免的要涉及到链接脚本文件,特别是编译链接那些大的工程文件时更是如此。在链接脚本中可以指定代码的存储布局,可以将代码段、只读数据段、可读写的数据段分别存放,甚至可以精确地指定代码放置的位置,这一点是很关键的,譬如说启动代码就必须放在可执行文件的开始位置。由于链接脚本重要性,开发者必须掌握其编写的方法。

Realview MDK链接程序使用了两种方式控制程序的链接

1.1.1链接控制命令选项


当使用链接控制命令选项时,链接器定义了12个段地址描述符, 这12个描述符可以直接在程序中引用.

Image$$ 执行区符号
符号说明
Image$$region_name$$Base 区的执行地址。
Image$$region_name$$Length 执行区长度(以字节为单位),不包括 ZI 长度。
Image$$region_name$$Limit 执行区中非 ZI 部分末尾后面的字节的地址。
Image$$region_name$$RO$$Base 此区中的 RO 输出节的执行地址。
Image$$region_name$$RO$$Length RO输出节的长度(以字节为单位)。
Image$$region_name$$RO$$Limit 执行区中 RO 输出节末尾后面的字节的地址。
Image$$region_name$$RW$$Base 此区中的 RW 输出节的执行地址。
Image$$region_name$$RW$$Length RW 输出节的长度(以字节为单位)。

Image$$region_name$$RW$$Limit 执行区中 RW 输出节末尾后面的字节的地址。

Image$$region_name$$ZI$$Base 此区中的 ZI 输出节的执行地址。
Image$$region_name$$ZI$$Length ZI 输出节的长度(以字节为单位)。
Image$$region_name$$ZI$$Limit 执行区中 ZI 输出节末尾后面的字节的地址。


它的RW长度计算:Length = (Image$$RW$$Limit-Image$$RW$$Base)

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0206ic/Chdcgbjd.html

1.1.1链接脚本文件*.sct


使用链接脚本文件后,上面提到的6个描述符号没有了,取而代之的是链接脚本文件中的段描述符.

在编译连接时如果指定了分散加载文件(.sct文件),在连接后会自动生成如下变量:

下面将结合3个具体的例子说明链接脚本文件的使用,下面三个例子中,载入区域和执行区域的名字是可以任意命名的,对这些段地址的引用可以使用如Image$$ LR_IROM1$$Base

Image$$ LR_IROM1$$Limit

Image$$ RW_RAM1 $$Base

Image$$ ZI_RAM1$$Limit

长度计算:Length = (Image$$段名$$Limit-Image$$段名$$Base)

代码段长度的计算方法为:Image$$ER_ROM1$$Limit-Image$$ER_ROM1$$Base

数据段长度的计算方法为:Image$$RW_RAM1$$Limit-Image$$RW_RAM1$$Base

引用链接脚本文件中的变量时,首先应该声明,下面是在汇编文件中和C/C++文件中的声明和引用方法:

A:汇编文件中的声明和引用方法:

声明:IMPORT ||Image$$region_name$$ZI$$Limit||

引用:LDR r0, =||Image$$region_name$$ZI$$Limit||

B: C/C++文件中的声明和应用方法:

声明:extern unsigned int Image$$region_name$$Limit

引用:config.heap_base = (unsigned int) &Image$$region_name$$Limit

例1 一个加载区域,多个连续的执行区域

;**************************************************************

; *** ******Scatter-Loading Description File***************

; **************************************************************

LR_IROM1 0x00000000 ; 定义载入区域LR_IROM1的起始地址为0x00000000

{

ER_IROM1 +0 ;执行区域ER_IROM1的起始地址紧接载于区域LR_IROM1的起始地址,即为

;0x00000000.

{

*(+R0) ;所有的只读代码段都连续地放在这个区域

}

RW_RAM1 +0 ;可读写数据段RW_RAM1紧接ER_IROM1段的尾地址存放,即0x00000000 +

;LR_IROM1的容量

{

* (+RW) ;所有的可读写的数据段(可读写的程序)都连续地放在这个区域

}

ZI_RAM1 +0 ;清零数据段ZI_RAM1(初始化为零的变量或者是未初始化的变量)紧接;

;RW_RAM1段的尾地址存放

{

*(+ZI) ;所有的清零数据段都连续地放在这个区域

}

}

例2 一个加载区域,多个非连续的执行区域

; **************************************************************

; *** ******Scatter-Loading Description File***************

; **************************************************************

LR_IROM1 0x00010000 ;定义载入区域LR_IROM1的起始地址为0x00010000

{

ER_IROM1 +0 ;执行区域ER_IROM1的起始地址紧接载于区域LR_IROM1的起始

;地址,即为0x010000.

{

*(+R0) ;所有的只读代码段都连续地放在这个区域

}

RW_RAM1 0x00040000 ;可读写数据段RW_RAM1的起始地址0x00040000

{

*(+RW) ;所有的可读写的数据段(可读写的程序)都连续地放在这个区域

}

ZI_RAM1 +0 ;清零数据段ZI_RAM1(初始化为零的变量或者是未初始化的变量)

;紧接RW_RAM1段尾地址存放,即为0x040000 +RW_RAM1的容量

{

*(+ZI) ; 所有的清零数据段都连续地放在这个区域

}

}

例3 两个加载区域,多个非连续的执行区域

; *************************************************************

; *** ******Scatter-Loading Description File***************

; *************************************************************

LR_IROM10x00010000 ;定义载入区域LR_IROM1的起始地址为0x00010000

{

ER_IROM1 +0 ;执行区域ER_IROM1的起始地址紧接载于区域LR_IROM1的起始地址

;即为0x010000.

{

*(+R0) ;所有的只读代码段都连续地放在这个区域

}

}

LR_IROM20x00040000 ;定义载入区域LR_IROM2的起始地址为0x00040000

{

RW_RAM1 +0 ;可读写数据段RW_RAM1的起始地址0x00040000

{

*(+RW) ;所有的可读写的数据段(可读写的程序)都连续地放在这个区域

}

ZI_RAM1 +0 ;清零数据段ZI_RAM1(初始化为零的变量或者是未初始化的变量)

;紧接RW_RAM1段的尾地址存放,即为0x040000 +RW_RAM1的容量

{

*(+ZI) ;所有的清零数据段都连续地放在这个区域

}

}

实际代码中应用说明:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
; Run in flash


LR_ROM1 0x00000000
{
ER_ROM1 0x00000000 0x00200000
{
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_RAM1 0x30000000 0x04000000
{
.ANY (+RW +ZI)
}
RW_IRAM1 0x40000000 0x00001000 {
.ANY (+RW +ZI)
}
}

-------------------------------------------------------------------------------------------------

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
; Run in RAM


LR_ROM1 0x30000000 { ; load region
ER_ROM1 0x30000000 0x0040000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_RAM1 +0 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM1 0x40000000 0x00001000 {
.ANY (+RW +ZI)
}
}

----------------------------------------------------------------------------------------

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
; Two Section


LR_ROM1 0x00000000
{
ER_ROM1 0x00000000 0x00200000
{
S3C2440A.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_RAM1 0x30050000 0x03000000
{
.ANY (+RW +ZI)
}
RW_IRAM1 0x40000000 0x00001000 {
.ANY (+RW +ZI)
}
}


LR_ROM2 0x00001000
{
ER_ROM2 0x30000100 0x00004000
{
keyled.o (+RO)
}
}

使用上述两段分散加载的,必须先把0x1000的代码copy到0x30000100处,程序才能正常运行。

------------------------------------------------------------------

Notes:

* (InRoot$$Sections)

起始地址与加载域重合的执行域成为root region,有许多 ARM库节必须放置在根区(rootregion),例如 __main.o、__scatter*.o、__dc*.o 和*Region$$Table。 此列表在不同版本中可能有差异。 链接器可以使用InRoot$$Sections 自动放置所有这些节,而不会影响将来的使用。

*(+RO)包含了* (InRoot$$Sections),所以如果在rootregion中用到了*(+RO)可以不再指定* (InRoot$$Sections)

.ANY (+RO)

.ANY(+RO) 是指其下面的执行域对于指定的模块,RO数据指定了存放地址,用.ANY就可以把已经指定的具有RO属性的Code/data排除。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值