一. uboot 启动流程
本文我们来详细的分析一下 uboot 的启动流程,理清 uboot 是如何启动的。通过对 uboot 启动流程的梳理。
我们就可以掌握一些外设是在哪里被初始化的,这样当我们需要修改这些外设驱动的时候就会心里有数。另外,通过分析 uboot 的启动流程可以了解 Linux 内核是如何被启动的。
注意: 分析 uboot启动流程的前提是,uboot源码需要经过编译。
二. 链接脚本 u-boot.lds
要分析 uboot 的启动流程,首先要找到“入口”,找到第一行程序在哪里。
程序的链接是由链接脚本来决定的,所以通过链接脚本可以找到程序的入口。连接脚本在uboot的根目录下u-boot.lds文件。
注意:如果没有编译过 uboot 的话链接脚本为 arch/arm/cpu/u-boot.lds。但这个不是最终使用的链接脚本,最终的链接脚本是在这个链接脚本的基础上生成的。编译一下 uboot,编译完成以后就会在 uboot 根目录下生成 u-boot.lds 文件。
只有编译
u-boot
以后才会在根目录下出现
u-boot.lds
文件!!!
打开
u-boot.lds
,内容如下:
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
2 OUTPUT_ARCH(arm)
3 ENTRY(_start)
4 SECTIONS
5 {
6 . = 0x00000000;
7 . = ALIGN(4);
8 .text :
9 {
10 *(.__image_copy_start)
11 *(.vectors)
12 arch/arm/cpu/armv7/start.o (.text*)
13 *(.text*)
14 }
15 . = ALIGN(4);
16 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
17 . = ALIGN(4);
18 .data : {
19 *(.data*)
20 }
21 . = ALIGN(4);
22 . = .;
23 . = ALIGN(4);
24 .u_boot_list : {
25 KEEP(*(SORT(.u_boot_list*)));
26 }
27 . = ALIGN(4);
28 .image_copy_end :
29 {
30 *(.__image_copy_end)
31 }
32 .rel_dyn_start :
33 {
34 *(.__rel_dyn_start)
35 }
36 .rel.dyn : {
37 *(.rel*)
38 }
39 .rel_dyn_end :
40 {
41 *(.__rel_dyn_end)
42 }
43 .end :
44 {
45 *(.__end)
46 }
47 _image_binary_end = .;
48 . = ALIGN(4096);
49 .mmutable : {
50 *(.mmutable)
51 }
52 .bss_start __rel_dyn_start (OVERLAY) : {
53 KEEP(*(.__bss_start));
54 __bss_base = .;
55 }
56 .bss __bss_base (OVERLAY) : {
57 *(.bss*)
58 . = ALIGN(4);
59 __bss_limit = .;
60 }
61 .bss_end __bss_limit (OVERLAY) : {
62 KEEP(*(.__bss_end));
63 }
......
73 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
74 }
第
3
行为代码当前入口点:
_start
,_start
在文件 arch/arm/lib/vectors.S 中有定义。vectors.S 如下所示:
从 vectors.S 中
可以看出,
_start
后面就是中断向量表,从图中的 “
.section ".vectors",
"ax
”可以得到,此代码存放在
.vectors
段里面。
u-boot.map
是
uboot
的内存映射文件,打开 u-boot.map:
从 u-boot.map 可以看到,某个文件或者函数链接到了哪个地址, 第 958
行可以看到
__image_copy_start
为
0X87800000
,而
.text
的起始地址也是
0X87800000
。
继续链接脚本
u-boot.lds,
第
11
行是
vectors
段,
vectors 段保存中断向量表,从vectors.S 中我们知道了 vectors.S
的代码是存在 vectors 段中的。 u-boot.map 文件可以看出:vectors 段的起始地址也是
0X87800000
,说明整个
uboot
的起始地址就是
0X87800000
,这也是为什么我们裸机
例程的链接起始地址选择
0X87800000
了,目的就是为了和
uboot
一致。