i.MX6ULL终结者C 语言实现LED例程修改Makefile

在上一小节我们已经写好了Makefile文件,在里面链接的时候我们使用的“arm-linux-gnueabihf-ld -Ttext 0X87800000 -o ledc.elf $^”命令,在这条命令里面我们通过“-Ttext”来指定链接地址0x87800000,这样所有的文件都会连接到以0x87800000为起始地址的区域。有时候我们工程中很多文件需要链接到指定的区域(段),比如Linux里面初始化函数会放到init的段里面,所以我们需要能够自定义一些段,这些段的起始地址可以自由指定,同样我们也可以指定一个文件或者一个函数应该存放到哪个段里面。要完成这个功能我们需要使用链接脚本。链接脚本是用于描述文件如何被连接在一起生成最终的可执行文件。主要目的是描述输入文件中的段如何被映射到输出文件中,并且控制输出文件的内存排列,一般我们编译生成的文件都包括text段,data段等等。

链接脚本实际上是通过一系列的指令组成的,每个命令是带有参数的关键字或者是对符号的赋值,可以使用分号分隔命令。像文件名之类的字符串可以直接输入,也可以使用“*”通配符,我们可以使用“SECTIONS”来定义一个段,在里面描述文件的内存分配。我们的代码编译出来,一般都会包括在test、data、bss和rodata这四个段里面,比如我们的代码要连接到0x80000000这个地址,数据连接到0x81000000这个地址,我们可以编写连接脚本,如下:

1 SECTIONS{
    
    
2  . = 0X80000000;
3  .text : {
    
    *(.text)}
4  . = 0X81000000;
5  .data ALIGN(4) : {
    
     *(.data) } 
6  .bss ALIGN(4)  : {
    
     *(.bss) } 
7 }

第1行通过“SECTIONS”,后面加一个大括号,这个大括号和第7行大括号的是一对。有点类似C语言中的函数。
第2行对“.”的特殊符号赋值,“.” 在链接脚本里面叫做定位计数器,默认定位计数器是0。我们要求代码连接到以0x80000000开始的地址,因此这一行给“.”赋值0x80000000,表示以0x80000000地址开始,后面的文件或者段都会以0x80000000位起始地址开始连接。
第3行的“.text”是段名,后面的冒号是语法要求。冒号后面的大括号里面可以填上要链接到“.text”这个段里面的所有文件,“(.text)”中的“”是通配符,表示所有输入文件的.text段都放到“.text”中。
第4行,我们的要求是数据放到 0X81000000 开始的地方,所以我们需要重新设置定位计数器“.”,将其改为 0X81000000。如果不重新设置的话会怎么样?假设“.text”段大小为 0X100,那么接下来的.data 段开始地址就是 0X80000000+0X100=0X80000100,所以我们必须调整定位计数器为 0X81000000。
第5行跟第3行一样,定义了一个名为“.data”的段,然后所有文件的“.data”段都放到这里面。这一行多了一个“ALIGN(4)”,这是什么意思呢?这是用来对“.data”这个段的起始地址做字节对齐的,ALIGN(4)表示 4 字节对齐。也就是说段“.data”的起始地址要能被4整除,一般常见的都是 ALIGN(4)或者ALIGN(8),也就是4字节或者8字节对齐。
第6行定义了一个“.bss”段,所有文件中的“.bss”数据都会被放到这个里面,“.bss”数据就是那些定义了但是没有被初始化的变量。

上面这些就是连接脚本的基本语法格式,我们按照这个语法来编写我们本实验的链接脚本,我们要求链接起始地址为0x87800000,start.o要被链接到最开始的位置(0x87800000),根据要求我们在工程目录下建立文件“imx6ull.lds”文件,然后在里面输入下面的脚本:

  1 SECTIONS{
    
    
  2         . = 0X87800000;
  3         .text :
  4         {
    
    
  5                 start.o
  6                 main.o
  7                 *(.text)
  8         }
  9         .rodata ALIGN(4) : {
    
    *(.rodata*)}
 10         .data ALIGN(4)   : {
    
     *(.data) }
 11         __bss_start = .;
 12         .bss ALIGN(4)  : {
    
     *(.bss)  *(COMMON) }
 13         __bss_end = .;
 14 }

上面链接脚本首先第1行通过“SECTIONS”定义一个关键字。然后第2行设置定位计数器为0x87800000(我们链接的起始地址),第3行是定义text段,第5行是指定开始链接的第一个文件“start.o”(首先要执行改文件,所以连接在最开始处)。第6行是链接的main.o,其实main.o链接的位置无所谓,所以可以不用写出来,由编译器自行决定链接位置。第9行,第10行设置rodata、data按照4字节对齐。第 11、13 行有“__bss_start”和“__bss_end”两个符号,分别对两个符号进行赋值,其值为定位符“.”,这两个符号用来保存.bss段的起始地址和结束地址。前面说了.bss段是定义了但是没有被初始化的变量,我们需要手动对.bss 段的变量清零的,因此我们需要知道.bss段的起始和结束地址,这样我们直接对这段内存赋 0 即可完成清零。通过第11、13行代码,.bss段的起始地址和结束地址就保存在了“__bss_start”和“__bss_end”中,我们就可以直接在汇编或者C文件里面使用这两个符号。

然后我们保存并退出imx6ul.lds文件,如果使用这个链接文件,我们需要修改Makefile文件,打开当前工程的Makefile文件,将里面的“arm-linux-gnueabihf-ld -Ttext 0X87800000 -o led.elf $^”内容改成“arm-linux-gnueabihf-ld -Timx6ul.lds -o led.elf $^”。实际就是将-T后面的0x87800000改成imx6ul.lds,表示使用imx6ul.lds这个链接脚本,修改完成以后保存并退出Makefile文件。在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46635880/article/details/108593541