|
U-boot移植心得《一》
好久没有更新博客了,老是没有时间。其实写写这些技术文章是很有好处的,一是可以增加自己的印象,二是可以和好多志同道合的人一起分享和讨论。最近在学习u-boot,那就从这里开始写吧,下面我将会把我所理解的u-boot全部记录下来,和大家分享。
关于U-boot的功能和传说在这里就不提了,直接进入正题,我是用的2440的开发板,从U-boot的三个核心文件开始说起:
u-boot.lds , config.mk(board目录对应开发板下) , start.S
先看最简单的config.mk,打开它里面只有一句:TEXT_BASE = 0x33F80000,这句话的意思是告诉编译器,u-boot的映像文件处于外部RAM的地址位于0x33F80000处,为什么是在这里?那就要了解你自己的开发板的硬件结构,我自己的开发板的外部RAM是2片32M构成的,总共64M。这64M的物理地址范围是0x30000000~0x33ffffff,这64M的外部RAM是这样来组织的,我们想把编译好的U-boot映像文件放到顶部的512K处,因此规定TEXT_BASE = 0x33F80000,TEXT_BASE是u-boot在外部RAM的运行起始地址。
再看u-boot.lds:
OUTPUT_FORMAT("elf32-littlearm",
"elf32-littlearm", "elf32-littlearm") ①编译器编译u-boot的输出格式
/*OUTPUT_FORMAT("elf32-arm",
"elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
②u-boot入口地址,上面的TEXT_BASE不也是入口地址吗?是的,_start是在内部RAM中运行的地址,2440的启动方式有2种,一种是NOR flash中启动,一种是NAND flash中启动,从NOR中启动,程序可以直接在NOR中运行,运行地址是0x00000000,如果是在NAND flash中启动,arm处理器首先将NAND中的前4K代码自动复制到内部ram中运行,运行地址也是0x00000000.那TEXT_BASE是怎么回事呢?是这样的,u-boot不管是从NOR还是NAND中启动,它们最终是要将代码复制到外部的64M的ram中运行的,因此一开始,代码是先从0x00000000地址处开始运行,这段代码有一个重要的任务是将U-boot的代码复制到外部64M的RAM中去,当复制完成后,程序就会跳到外部RAM中去运行。TEXT_BASE就是u-boot在外部RAM中的运行起始地址。
SECTIONS
{
.
= 0x00000000; ③代码运行的起始地址
.
= ALIGN(4);
.text : ④代码段的存放顺序
{
cpu/arm920t/start.o (.text) ⑤从这里可以看出start.o是u-boot运行的第一段代码。由start.S编译生成。
board/100ask24x0/boot_init.o
(.text)⑥接着存放第二段代码,boot_init.c是U-boot1.1.6源码中没有的文件,是后来移植添加进去的,里面存放了时钟初始化,从NOR或NAND中复制代码到RAM的相关程序。为什么添加到这里呢?如果不指定添加到这里,编译器会主动将程序放到⑦中,这样可能将boot_init.c的代码编译到前4K范围之外,这样如果u-boot在NAND启动的时候,前4K代码被自动复制到内部RAM中运行,这样前4K代码完不成将u-boot的代码复制到外部RAM中去的任务,启动就会失败。
*(.text)
⑦其他所有代码段的代码
}
.
= ALIGN(4);
.rodata
: { *(.rodata) } ⑧直读数据段
.
= ALIGN(4);
.data
: { *(.data) } ⑨可读可写数据段
.
= ALIGN(4);
.got
: { *(.got) } 10、got段,u-boot自定义,可不用管
.
= .;
__u_boot_cmd_start
= .; 11、u-boot命令段,u-boot的各种命令都存在此处。
.u_boot_cmd
: { *(.u_boot_cmd) }
__u_boot_cmd_end
= .;
.
= ALIGN(4);
__bss_start
= .; 12、最后代码存放用户堆区数据段
.bss
: { *(.bss) }
_end
= .;
}
从下节开始我们进入u-boot的启动代码start.S来分析u-boot的第一阶段的启动过程。