arm-A7中断
有时候我们很多文件需要链接到指定的区域,或者叫做段里面,比如在 Linux 里面初始化函数就会放到 init 段里面。因此我们需要能够自定义一些段,这些段的起始地址我们可以自由指定,同样的我们也可以指定一个文件或者函数应该存放到哪个段里面去。
要完成这个功能我们就需要使用到链接脚本,看名字就知道链接脚本主要用于链接的,用于描述文件应该如何被链接在一起形成最终的可执行文件。其主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件中的内存排布。比如我们编译生成的文件一般都包含 text 段、 data 段等等。
链接脚本的语法很简单,就是编写一系列的命令,这些命令组成了链接脚本,每个命令是一个带有参数的关键字或者一个对符号的赋值,可以使用分号分隔命令。像文件名之类的字符串可以直接键入,也可以使用通配符“*”。最简单的链接脚本可以只包含一个命令“SECTIONS”,我们可以在这一个“SECTIONS”里面来描述输出文件的内存布局。我们一般编译出来的代码都包含在 text、 data、 bss 和 rodata 这四个段内,假设现在的代码要被链接到 0X10000000 这个地址,数据要被链接到 0X30000000 这个地方,下面就是完成此功能的最简单的链接脚本:
例子:
1 | SECTIONS{ |
第 1 行我们先写了一个关键字“SECTIONS”,后面跟了一个大括号,这个大括号和第 7 行的大括号是一对,这是必须的。看起来就跟 C 语言里面的函数一样。
第 2 行对一个特殊符号“.”进行赋值,“.”在链接脚本里面叫做定位计数器,默认的定位计数器为 0。我们要求代码链接到以 0X10000000 为起始地址的地方,因此这一行给“.”赋值0X10000000,表示以 0X10000000 开始,后面的文件或者段都会以 0X10000000 为起始地址开始链接。
第 3 行的“.text”是段名(代码段),后面的冒号是语法要求,冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件,“(.text)”中的“”是通配符,表示所有输入文件的.text段都放到“.text”中。
第 4 行,我们的要求是数据放到 0X30000000 开始的地方,所以我们需要重新设置定位计数器“.”,将其改为 0X30000000。如果不重新设置的话会怎么样?假设“.text”段大小为 0X10000,那么接下来的.data 段开始地址就是 0X10000000+0X10000=0X10010000,这明显不符合我们的要求。所以我们必须调整定位计数器为 0X30000000。
第 5 行跟第 3 行一样,定义了一个名为“.data”的段(数据段),然后所有文件的“.data”段都放到这里面。但是这一行多了一个“ALIGN(4)”,这是什么意思呢?这是用来对“.data”这个段的起始地址做字节对齐的, ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被 4 整除,一般常见的都是 ALIGN(4)或者 ALIGN(8),也就是 4 字节或者 8 字节对齐。
第 6 行定义了一个“.bss”段(bss数据段x,表示定义了但是还没有初始化的数据段),所有文件中的“.bss”数据都会被放到这个里面,“.bss”数据就是那些定义了但是没有被初始化的变量。
“__bss_start”和“__bss_end”是符号,这两其实就是对这两个符号进行赋值,其值为定位符“.”,这两个符号用来保存.bss 段的起始地址和结束地址。
那个最先被执行,就把他链接到最前。
内存按存储的类型分以下几种;
1, .BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。【包括未初始化的全局变量和局部静态变量,我们知道未初始化的全局变量和局部静态变量默认值都为0, 本来它们也可以被放在.data 段的, 但是因为它们都是 0, 所以为它们在.data 段分配空间并且存放数据 0 是没有必要的。 程序运行的时候它们的确是要占内存空间的, 并且可执行文件必须记录所冇未初始化的全局变量和局部静态变量的大小总和, 记为.Bss段。 所以.bss 段只是为未初始化的全局变量和局部静态变量预留位置而已, 它并没有内容, 所以它在文件中也不占据空间。】
2, .data段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。 【全局变量和局部变量数据经常放在数据段】
3, .text段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。【程序源代码编译后的机器指令经常放在代码段】
而在.bin文件中,包括Vectors段,ramcode段,SysApp段以及相对独立的功能段FeatureX
Vectors段即对应启动文件Cstartup.S,必须放置在bin文件0地址处。
ramcode段紧接着vectors段,对应程序中被标记为ramcode的函数。
SysApp段在Vectors段之后,其对应main.c以及一些程序逻辑代码等,包含对应的code,rodata,data(含retention和非retention)段。【retention内容为:在RAM中具有一段被保护的内存空间,此空间具有掉电保护机制,不会因为MCU掉电而擦除。】
FeatureX段为一个独立的功能段,包含对应的code,rodata,data等。
1 | __image_copy_start uboot 拷贝的首地址 |
修改了代码。会导致上面的值发生变化,除了首地址。