首页 > 代码库 > u-boot移植(二)---修改前工作:代码流程分析1
u-boot移植(二)---修改前工作:代码流程分析1
一、代码执行总体流程图
1.1 代码路径
-
U-boot.lds (arch\arm\cpu)
-
vectors.S (arch\arm\lib)
-
start.S (arch\arm\cpu\arm920t)
-
lowlevel_init.S (board\samsung\jz2440)
-
crt0.S (arch\arm\lib)
-
relocate.S (arch\arm\lib)
-
Board_init.c (common\init)
-
Board_f.c (common)
-
Jz2440.h (include\configs)
-
Generic-asm-offsets.h (include\generated)
1.2 启动代码流程图
分析完后补上。
二、链接文件
目录:u-boot-2017.03/arch/arm/cpu
文件:u-boot.lds
编写好的 .lds 文件,在用 arm-Linux-ld 连接命令时带 -Tfilename 来调用执行,如:arm-linux-ld-Tnand.lds x.o y.o -o xy.o
也用-Ttext参数直接指定连接地址,如 arm-linux-ld-Ttext 0x30000000 x.o y.o -oxy.o
既然程序有了两种地址,就涉及到一些跳转指令的区别。
ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。
??要特别注意这两条指令的意思:
1> b step:b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。
2> ldr pc, =board_init_r :该指令是一个伪指令编译后会生成以下代码:ldr pc, [pc, #8]
从内存中的某个位置读出数据并赋给PC,同样依赖当前PC的值,所以可以用它实现从Flash到RAM的程序跳转。
2种方式指明程序地址,这里分析下第二种方式,在根目录 Makefile文件有如下一行:
在文件 include/configs/jz2440.h
有定义:
我们在这里可以用下面的命令生成 u-boot.dis文件(注意交叉编译器的名字):
arm-2440-linux-gnueabi-objdump -D -m arm u-boot > u-boot.dis
在0 地址执行的是 _start.S文件,然后跳转到reset执行,接着定义异常向量表:
在u-boot.lds 脚本中并没有指定基地址, 根目录下的 u-boot 脚本是由 arch/arm/cpu/u-boot.lds
在编译的时候生成的,所以如果要修改u-boot.lds 需要找到正确的地方。
u-boot.lds 分析: 1 #include <config.h>
2 /* 指定输出可执行文件是elf格式,32位ARM指令,小端模式 */
3 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
4 OUTPUT_ARCH(arm) /* 指定输出文件的的平台体系为ARM */
5 ENTRY(_start) /* 指定可执行映像文件的起始段的段名是 _start,这里跳转到vector.S执行 */
6 SECTIONS
7 {
8 /DISCARD/ : { *(.rel._secure*) }
9 /* 指定可执行的 image 文件的全局入口点,通常这个地址都发给你法rom(flash)0x0位置。
10 * 必须使编译器知道这个地址,一般不修改此处,而是修改其它地方的宏定义*/
11 . = 0x00000000;
12 . = ALIGN(4);
13 .text :
14 {
15 /* 映像文件赋值起始地址,它在文件 arch/arm/lib/sections.c 中定义:
16 * char __image_copy_start[0] __attribute__((section(".__image_copy_start")));*/
17 *(.__image_copy_start)
18 /* arch/arm/lib/vectors.S 里有一句:.section ".vectors" */
19 /* 这里的 vectors 是让vector.S 链接的二进制文件的开头部分 */
20 *(.vectors)
21 CPUDIR/start.o (.text*) /* 执行 start.S */
22 *(.text*) /* 其他代码 */
23 }
24
25 . = ALIGN(4);
26 /* 只读数据段,所有的只读数据段都放在这个位置 */
27 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
28
29 . = ALIGN(4);
30 /* 可读写数据段,所有的可读写数据段都放在这个位置 */
31 .data : {
32 *(.data*)
33 }
34
35 . = ALIGN(4);
36
37 . = .;
38
39 . = ALIGN(4);
/* U-BOOT命令段 */
40 .u_boot_list : {
41 KEEP(*(SORT(.u_boot_list*)));
42 }
43
44 . = ALIGN(4);
45
46 .image_copy_end :
47 {
48 *(.__image_copy_end)
49 }
50
/* 相对动态信息段 */
51 .rel_dyn_start :
52 {
53 *(.__rel_dyn_start)
54 }
55
56 .rel.dyn : {
57 *(.rel*)
58 }
59
60 .rel_dyn_end :
61 {
62 *(.__rel_dyn_end)
63 }
64
65 .end :
66 {
67 *(.__end)
68 }
69
70 _image_binary_end = .;
71
72 /*
73 * Deprecated: this MMU section is used by pxa at present but
74 * should not be used by new boards/CPUs.
75 */
76 . = ALIGN(4096);
77 .mmutable : {
78 *(.mmutable)
79 }
80
81 /*
82 * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
83 * __bss_base and __bss_limit are for linker only (overlay ordering)
* bss段,里面放置的是初始值为0的全局变量和静态变量,这些变量不会保存在
* 二进制文件中
84 */
85
86 .bss_start __rel_dyn_start (OVERLAY) : {
87 KEEP(*(.__bss_start));
88 __bss_base = .;
89 }
90
91 .bss __bss_base (OVERLAY) : {
92 *(.bss*)
93 . = ALIGN(4);
94 __bss_limit = .;
95 }
96
97 .bss_end __bss_limit (OVERLAY) : {
98 KEEP(*(.__bss_end));
99 }
100
101 .dynsym _image_binary_end : { *(.dynsym) }
102 .dynbss : { *(.dynbss) }
103 .dynstr : { *(.dynstr*) }
104 .dynamic : { *(.dynamic*) }
105 .plt : { *(.plt*) }
106 .interp : { *(.interp*) }
107 .gnu.hash : { *(.gnu.hash) }
108 .gnu : { *(.gnu*) }
109 .ARM.exidx : { *(.ARM.exidx*) }
110 .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
111 }
链接执行,首先是进入到arch/arm/vector.S 中执行,在其中执行 _start.S ,_start.S 的首行就跳转到 start.S 中的 reset 中去执行了。
这里没有执行SPL,若要加上SPL,则还需要加上 nandflash
链接脚本暂时的流程为:
跳转A处,A代码在Vector.S中,执行_start.S代码,下一节看 _start.S的代码,并分析其过程。
备注:后续会更新此文档
u-boot移植(二)---修改前工作:代码流程分析1