(1) "-pie"选项
原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)"段(在链接脚本u-boot.lds中可见),其中(.rel*)", "*(.dynsym)"存放变量、函数的地址
使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)
把程序的链接地址固定好,启动时把u-boot从nand flash拷贝到SDRAM 里面来,然后清除bss段。
运行地址<--->链接地址:他们两个是等价的,只是两种不同的说法。
加载地址<--->存储地址:他们两个是等价的,也是两种不同的说法。
查找pie选项
去掉 "-pie"选项
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
(2)把从零写u-boot中的init.c拷贝到u-boot/board/samsung/smdk2440中
有多个同名函数时,改函数名字或设置为static,也就是仅限于本文件使用
参考"毕业班第1课"的start.S, init.c来修改代码
把init.c放入board/samsung/smdk2440目录, 修改Makefile
修改CONFIG_SYS_TEXT_BASE为0x33f80000(起始地址)
修改start.S
上面取0x33f80000这个值是因为,内存大小是64M ,起始地址是0x3000,0000,而结束地址是0x3400,0000,0x3400,0000减去0x33f80000刚好是512K,一般的u-boot不会超过512K.
(3)nand flash相关操作(start.S)
(3.1)先设置栈,然后进入nand flash的初始化函数
(3.2)设置参数,拷贝程序,重定位。其中指令ldr r1, =start和指令ldr r1 _TEXT_BASE作用是一样的,如果用ldr r1, =start这条伪汇编指令的话,假若start这个值很复杂的时候会把它存在一个地址,存在哪里根本无法掌握,是由编译器决定的,有可能存在4K之外去了,我们用ldr r1= _TEXT_BASE这条指令,存在哪里都已经定死了。CONFIG_SYS_TEXT_BASE为0x33f80000,是程序的链接地址。r0是源地址,而r1是目的地址;这里_bss_start-_start是二进制文件u-boot.bin的大小,也就是说r2是需要拷贝的文件的大小。然后把代码拷贝到SDRAM里面去。
(4)清除bss段
在链接脚本中有
这里只需吧_bss_end修改为_bss_end_
(5)跳到SDRAM里面执行
bl是相对跳转指令,想让它在SDRAM里面执行,可以用ldr pc , =call_board_init_f这条指令,call_board_init_f是链接地址,这样做可以从片内内存跳到SDRAM上面来,最后调用函数board_init_f,修改board_init_f, 把relocate_code去掉(因为重定位之前已经做了)
2、调用board_init_f函数后开始进入第二阶段board_init_r函数
(1)board_init_r函数
下面第一个参数是gd_t结构体,,这个参数的值不大好确定,由于board_init_f函数已经把这个参数定下来了,直接把这个参数值返回就可以了
第二个参数是目的地址
,看内存图,可知目的地址是程序的链接地址
修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
board/samsung/smdk2440/libsmdk2440.o
在u-boot中搜索链接脚本
里面的./arch/arm/cpu/u-boot.lds:,其中CPUDIR是当前目录的意思,由于start.S, init.c, lowlevel.S等文件都编译进库libsmdk2440.o里面,
然后进行编译make
3、查看反汇编
(1)生成反汇编文件
(2)看start.S, init.c, lowlevel.S等文件放是否放在最前面
nand_init_ll函数时在init.c文件里面的,因为目标地址是33f80000,在偏移值为588的地方,16进制的588换算成10进制是1416,大概1K左右,没有超过4K
4、查看生成的链接脚本
(1)下面是编写的链接脚本
(2)下面是编译后自动生成的链接脚本
CPUDIR是arch/arm/cpu/arm920t
5、地址修改
(1)目标地址强制定为0x33f80000,程序不能超过512k,因为SDRAM 的最高地址是0x34000000.以前地址从最上面一路往下减,减去程序本身大小才算出来的。现在把它定死,最后面两句话要去掉,改成addr=0x33f80000.
(2)代码修改
(3)目标地址强制定为0x33f80000,程序不能超过512k.
看看程序本身的大小,只有400多K。但400多K不包含bss段,看链接脚本bss_end_这个值减去程序开始的地方才是程序本身的大小。在start.S中可知只要知道bss_end_ofs的大小就知道程序最终的大小(大于u-boot.bin),在汇编里搜索bss_end_ofs这里000acbd0是程序运行时最终总的大小,这里包括bss段。000acbd0转换成10进制有700多K,超过了我们预留的512K .因而0x33f80000显然是不够的,把目的地址改成0x33f00000,有1M的空间。
6、烧写、启动
(1)退出菜单查看mtd分区
这里分配给u-boot的空间只有256K ,我们的有400多K
(2)用命令自行下载烧写
接上usb_device那条线,打开dnw,
用usb 1 30000000命令下载,usb是指usb命令,1是指一直等待直到下载完,30000000是指下载到SDRAM的地址。然后用dnw下载
从0地址开始擦除,结束地址是80000,共擦除512K,这里nand表明是异于nor flash操作的nand flash操作
nand write 30000000 0 80000是指从SDRAM的地址写内容到nand flash的0地址,这里需要写的大小是80000(nand flash的0地址)