`
yidongkaifa
  • 浏览: 4052775 次
文章分类
社区版块
存档分类
最新评论

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排除。


分享到:
评论

相关推荐

    mdk sct 分散加载文件 周立功

    mdk sct 分散加载文件 周立功

    关于S3C2410的分散加载文件

    Scatter file(分散加载描述文件)用于LARM链接器的输入参数,它指定...在利用MDK进行实际应用程序开发时,常常需要使用道分散加载文件,例如以下情况: 存在复杂的地址映射:例如代码和数据需要分开放在在多个区域。

    MDK应用文章:4.2410的分散加载文件.pdf

    MDK应用文章:4.2410的分散加载文件.pdf

    MDK map 文件介绍

    MDK map以及分散加载文件构成文件介绍

    分散加载文件浅释.pdf 周立功 keil mdk sct文件

    关于keil mdk 开发环境,sct文件的编写方法,相对比较专业的文档,周立功

    STM32-KEIL分散加载范例

    以前看到IAR可以做 linux内核也可以做,一直以为是一个未解之谜,比如一个数组ARR[10]注意的话,你以后在每个模块.C.H用的时候用ARR[1...分散加载就是这个技术!附件是我KEIL成功的!非常顺利,因为我从RTT源码里学习的

    MDK程序分散加载实例(基于GD32)

    以GD32F3X0固件库程序为例,分享KEIL如何将函数及.c文件分散加载到指定区域。

    keil for arm汇编程序分散加载文件(L6236E 错误 )出错的解决方法

    Cortex-M3在MDK下汇编程序分散加载文件出错的解决方法 解决一个用KEIL FOR ARM 写ARM纯汇编的常见问题

    Keil MDK下如何设置非零初始化变量1

    1. 修改分散加载文件,增加一个名为MYRAM的执行节,该执行节起始地址为0x1000A000, 2. 分散加载文家同方法 1,如果还是定义一个数组,可以用下面

    MDK应用文章

    4.2410的分散加载文件 5.Realveiw MDK中图形化界面配置详解 6.Realview MDK中编译器对中断处理的过程详解 7.Realview MDK中链接脚本的详细解析 8.Realview MDK中调试脚本的详细解析 9.在MDK中添加自己的FLASH编程...

    在 KEIL 环境下通过批处理命令追加应用代码的 CRC Checksum

    在 MDK V5.31 环境下,通过构建后的批处理命令调用外部工具 srecord-1.64-win32(srec_cat.exe)来完成代码移植性校验值 CRC Checksum 的追加。 资源内有一个示例工程,呈现了如何生成 CRC Checksum,如果通过 CRC32...

    keil中文帮助完整版

    包括keil编译器的大多帮助文件中文版,关于库,分散加载文件的语法,命令等,很不错的资料!

    使用c++编写stm32并调用lib函数

    里面有两个工程,一个是生成库文件工程,一个是主调用工程。可为想使用c++编译和想使用软件lib封装驱动的朋友提供参考。里面内容为本人原创,如有转载请注明。...软件平台为keil mdk for arm平台。

    STM32F303VCT6_CCM使用说明+源码.zip

    分别是在KEIL_MDK和IAR中的设置分散加载文件的,和测试的源码。都是本人测试通过的。 结论:CCM这个区域真的是好东西,可以提高速度,我用的是求平方根的算法,求十次平方根的时间差别在2us,代码量越多执行的时间差...

    GD32F1开发例程和开发工具.rar

    Introduction:GD32F1x0 分散加载例程 ,支持 GD32F130 / GD32F150 / GD32F170 / GD32F190 例程演示了如何将代码分配到Flash指定区域,参考这个例程,客户可将非关键代码分配到Flash高地址空间。 Introduction:...

Global site tag (gtag.js) - Google Analytics