裸板驱动总结(makefile+lds链接脚本+裸板调试)

 在裸板2440中,当我们使用nand启动时,2440会自动将前4k字节复制到内部sram中,如下图所示:

然而此时的SDRAM、nandflash的控制时序等都还没初始化,所以我们就只能使用前0~4095地址,在前4k地址里来初始化SDRAM,nandflash,初始化完成后,才能将nandflash的4096至后面的地址内容存放到SDRAM里去.

而裸板驱动的步骤如下所示:

  • 1.makefile
  • 2.lds链接脚本 (供makefile调用)
  • 3.写真正要执行的文件代码,比如初始化nand,sdram,串口等

为什么要写lds链接脚本?

首先lds链接脚本的作用就是将多个*.o文件的各个段链接在一起,告诉链接器这些各个段存放的地址先后顺序,它的好处就是,确保裸板2440的前4k地址里存放的是初始化SDRAM,nandflash的内容


 

1.写makefile

(参考makefile初步制作:

objs := head.o init.o nand.o main.o    //定义objs变量,表示obj文件,包含生成boot.bin目标文件需要的依赖文件, 使用$(objs)就可以使用这个变量了 //‘:=’:有关位置的等于(比如:”x:=a  y:=$(x)  x:=b”,那么y的值取决于当时位置的a,而不是b)  //‘=’:无关位置的等于(比如:”x=a  y=$(x)  x=b”,那么y的值永远等于最后的b ,而不是a)                                                         nand.bin : $(objs)   //冒号前面的是表示目标文件, 冒号后面的是依赖文件,这里是将所有*.o文件编译出nand.bin可执行文件arm-linux-ld -Tnand.lds    -o nand_elf $^   //将*.o文件生成nand_elf链接文件 //-T:指向链接脚本, $^:指向所有依赖文件, arm-linux-objcopy -O binary -S nand_elf $@ //将nand_elf链接文件生成nand.bin文件 //$@:指向目标文件:nand.bin //-O :选项,其中binary就是表示生成的文件为.bin文件 arm-linux-objdump -D -m arm  nand_elf > nand.dis //将nand.bin文件反汇编出nand.dis文件 //-D :反汇编nand.bin里面所有的段, -m arm:指定反汇编文件的架构体系,这里arm架构 %.o:%.c            //冒号前面的是目标文件,冒号后面的是依赖文件,%.o表示所有.o文件, arm-linux-gcc -Wall -c -O2 -o $@ $<         //将*.c文件生成*.o文件 //$<:指向第一个依赖文件, 也就是.c文件 //$@:指向目标文件,也就是.o文件 //-Wall:编译若有错,便打印警告信息     -O2:编译优化程度为2级 %.o:%.S                            arm-linux-gcc -Wall -c -O2 -o $@ $<    //将*.S文件生成*.o文件    clean:                           //输入make clean,即进入该项,来删除所有生成的文件     rm -f  nand.dis nand.bin nand_elf *.o   //通过rm命令来删除
复制代码

2.写lds链接脚本

(参考lds脚本解析: http://www.cnblogs.com/lifexy/p/7089873.html)

复制代码
 SECTIONS {     . = 0x30000000;             //指定当前的链接地址=0x30000000 .text          :   { head.o(.text)    //添加第一个目标文件,里面会调用这些函数 init.o(.text)      //添加第二个目标文件,里面存放关看门狗,初始化SDRAM等函数 nand.o(.text)   //添加第三个目标文件,里面存放初始化nand函数*(.text)    // *(.text) 表示添加剩下的全部文件的.text代码段 }  .rodata ALIGN(4) : {*(.rodata)}       //指定只读数据段 .data ALIGN(4) : { *(.data) }     //指定读写数据段,     *(data):添加所有文件的数据段 __bss_start = .;     //把__bss_start赋值为当前地址位置,即bss段的开始位置 .bss ALIGN(4)  : { *(.bss)  *(COMMON) }     //指定bss段,里面存放未被使用的变量 __bss_end = .;        //把_end赋值为当前地址位置,即bss段的结束位置 }
复制代码

上面的链接地址=0x30000000,表示程序运行的地方应该位于0x30000000处,0x30000000就是我们的SDRAM基地址,而一上电后,nand的前4k地址会被2440自动装载到内部ram中,所以我们初始化了sdram和nand后,就需要把程序所有内容都复制到链接地址0x30000000上才行

2.1为什么要在bss段的前后设置两个符号__bss_start, __bss_end?

定义__bss_start__bss_end符号,是用来程序开始之前将这些未定义的变量清0,节省内存
__bss_start -0x30000000就等于该bin文件的字节大小,实现动态复制

2.3为什么链接地址在0x30000000处,为什么在初始化sdram和nand之前,还能运行前4k地址的内容?

我们先来看看head.S第一个目标文件,就知道了:

复制代码
.text                                           
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信