LD文件详解

周末不卷了,讲个知识点很散的LD文件,这东西难度完全看原来的LD文件怎么写,我们顶多就是改改,要是从零开始写的话,人都要到异世界生活了。

说在前面

它不像代码一样都是要定义的,大部分都是标号,没定义过的标号第一次出现就是给他定义。

它的注释一般是C语言那种/**/,其他的不知道能不能用

它有几个大块,花括号{}外面部分、MEMORY部分、SECTIONS部分、其他带花括号的部分。

花括号{}外面部分

这些比较简单,就是一些宏定义。

ENTRY入口地址

ENTRY(Reset_Handler)

以Reset_Handler作为进程执行的第一条用户空间的指令在进程地址空间的地址,简单来说就是代码从这里开始执行,Reset_Handler一般在startup之类的汇编文件里面写着。

DEFINED检查定义

HEAP_SIZE  = DEFINED(__heap_size__)  ? __heap_size__  : 0x00000400;

DEFINED(__heap_size__) 检查__heap_size__是否已经被定义,如果有定义就返回1,没定义就返回0。但是这里后面跟着? __heap_size__  : 0x00000400;意义就变了,变成了像C语言一样“DEFINED(__heap_size__)  ? __heap_size__  : 0x00000400”成了一个整体。

如果__heap_size__有定义就返回__heap_size__的值,没定义就返回0x00000400。

MEMORY部分

就是MEMORY然后用花括号括住的部分,像刻光盘一样,给你的芯片分个区,这里仅仅只是分区,不会塞东西进去。这里具体要分多少个区域,得根据芯片来,而且每个芯片的ROM和RAM区域都不一样。

MEMORY
 {
   iROM_0         : ORIGIN = 0x00000000,  LENGTH = 1206k
   iRAM_0         : ORIGIN = 0x04000000,  LENGTH = 32k
 }

有像上面这样写的最简单的,分个iROM_0区域,0x00000000开始,长度为1206k。

MEMORY
{
  /* Flash */
  m_interrupts          (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00000400
  m_text                (RX)  : ORIGIN = 0x00000410, LENGTH = 0x000EBBF0

  /* SRAM */
  m_data_2              (RW)  : ORIGIN = 0x1FFF4800, LENGTH = 0x0001A000
  MagicFlag             (RW)  : ORIGIN = 0x2000EB00, LENGTH = 0x00000500
}

有像这样写得详细一点的,分开flash和RAM区域,还标注清楚权限。

SECTIONS部分

SECTIONS是最重要的,中文翻译叫段。不仅细化了MEMORY的分区,还能嵌套别的{},SECTIONS里面的{}也叫SECTIONS,中文翻译叫做节。

无嵌套例子

先举个没有嵌套的例子

SECTIONS
 {
/* Start of internal ROM area (iROM_0) */
  .intvect  align (512)                 :>iROM_0  /* start of interrupt vector */
  .intvect_end  0x00200                 :>.       /* end   of interrupt vector */
  EIINTTBL  align (4)                   :>.
  .text     align(4)                    :>.      /* program code area */

  .romdata  ROM(.data)                  :>.      /* constant data to initialize variables (copied to RAM at startup)*/
  .romzdata ROM(.zdata)                 :>.      /* constant data to initialize variables in ZDA area (copied to RAM at startup)*/

  __top_of_iROM_0 = MEMENDADDR(iROM_0);
}

这里只提取了iROM_0的部分,我们逐句解析。

  .intvect  align (512)                 :>iROM_0
  .intvect_end  0x00200                 :>. 
  EIINTTBL  align (4)                   :>.
  .text     align(4)                    :>.      /* program code area */

先分了个叫".intvect"的中断向量表的区域出来,这里的SECTIONS名前面都要加点号。align是个对齐的命令,要开512字节的空间并且将里面中断向量表的内容对齐。:>就是放入的意思。把这512字节放到iROM_0里面,也就是上面的MEMORY里面的首地址0x00000000。

.就是当前地址的意思,由于上面已经占用了512字节,也就是0x200,那么下面的.会自动向后移动512字节。那就是把intvect_end放到0x200的位置。

后面的就不赘述了

  .romdata  ROM(.data)                  :>.      /* constant data to initialize variables (copied to RAM at startup)*/
  .romzdata ROM(.zdata)                 :>.      /* constant data to initialize variables in ZDA area (copied to RAM at startup)*/

.romdata和.romzdata都是标号SECTIONS名,将iROM_0里面的.data区域分配给.romdata,.zdata区域分配给.romzdata,并且表明是ROM性质的。

  __top_of_iROM_0 = MEMENDADDR(iROM_0);

将iROM_0最后的地址给到__top_of_iROM_0标号

MEMADDR(iROM_0)就是iROM_0开头地址

带嵌套例子

另一种格式也比较基础,也就是分了.sram和.heap 两个节。

    .sram :
    {
        . = ALIGN(4);/*4字节对齐*/
        *(.text.startup) /*取出.text.startup的所有的内容放在.sram里面*/
        KEEP(*(.init))/*KEEP确保.init中的内容在链接过程中不会被垃圾处理法则丢弃。*/
        __sram_bss_end = .;
    } > int_sram /*放入上面MEMORY定义的int_sram分区当中*/

    .heap (NOLOAD):
    {
    	. += ALIGN(4);
	    _end = .;
	    end = .;
        _heap_start = .;
        . += HEAP_SIZE;/*将定位器.后移HEAP_SIZE长度*/
        _heap_end = .;
    } > int_sram

节地址

    {
        ……
    } > int_flash

    . = ALIGN(4);
    __text_end = .;
    __sram_data_rom = __text_end;
    
    .sram_data : AT(__sram_data_rom)
    {
        ……
    }

AT(__sram_data_rom)代表.sram_data节从__sram_data_rom的地址开始。

	  .DummySection : ALIGN(4)
	  {
        ……
	  } > Dummy

代表DummySection在前面地址对齐之后的地址开始

虚拟地址和加载地址

节里面的地址分为两种

VMA(virtual memory address虚拟内存地址)

LMA(load memory address加载内存地址)

VMA是执行输出文件时section所在的地址,而LMA是加载输出文件时section所在的地址。

通常VMA和LMA是相同的,也有不同的情况。

    .sram_bss:
    {
        ……
    } > int_sram AT>int_sram

前面一个int_sram是VMA,后一个int_sram是LMA。

    .sram_bss (NOLOAD) :
    {
        ……
    } > int_sram

这种就是int_sram是VMA,没有LMA。

其他带花括号的部分

这种就比较简单了,而且少见,就是最常用CONSTANTS。

CONSTANTS
{
    const_data_section 0x08000000 :
    {
        *(.const_data)  // 将程序中的只读数据放置到Flash存储器的起始地址0x08000000处
    } > FLASH
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃鱼的羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值