u-boot 1.3.4源码分析详细教程

每款MCU上电之后,并不是立即执行到主程序的,而是最先初始化整个系统资源,俗称“Boot loader”。所以,u-boot是一种普遍用于嵌入式系统中的Boot loader,Boot loader是在操作系统运行之前执行的一小段程序,通过它,可以初始化硬件设备、建立内存空间的映射表,从而建立适当的软硬件环境,为最终调用操作系统内核做好准备。Boot loader的主要运行任务就是将内核映象从硬盘上读到RAM中,然后跳转到内核的入口点去运行,即开始启动操作系统。系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的Boot Loader程序;所以了解了u-boot的启动流程,就可以清楚知道linux启动时打印的信息是什么意思。

那么在介绍u-boot之前,先来认识一款软件Source insight;由于从u-boot官网下载的u-boot1.3.4安装包,它支持各大硬件平台,而且程序数据极多,在学习时,需要挑重点,找出符合字节硬件的程序;所以source insight是一款相当不错的软件,当然像Slick edit也是一款很好的编辑器。

1 . Source Insight 使用

1.1 Source Insight工程创建

u-boot 1.3.4源码分析详细教程

新建工程菜单

u-boot 1.3.4源码分析详细教程

工程设置界面

u-boot 1.3.4源码分析详细教程

工程设置完成

u-boot 1.3.4源码分析详细教程

工程文件保存路径设置界面(默认)

u-boot 1.3.4源码分析详细教程

源码添加界面

u-boot 1.3.4源码分析详细教程

配置为添加子目录文件

u-boot 1.3.4源码分析详细教程

添加文件完成界面

u-boot 1.3.4源码分析详细教程

关闭源码添加界面

u-boot 1.3.4源码分析详细教程

文件同步菜单

u-boot 1.3.4源码分析详细教程

同步配置

u-boot 1.3.4源码分析详细教程

同步进行中

u-boot 1.3.4源码分析详细教程

同步完成后界面

1.2常用操作介绍:

u-boot 1.3.4源码分析详细教程

过滤文件(输入要查看的文件名)

u-boot 1.3.4源码分析详细教程

查看目标文件

查看文件中函数,变量,宏定义:

对于整个工程中只一个一份代码的函数或变量或宏,导航窗口会直接列出其定义,如下所示

u-boot 1.3.4源码分析详细教程

对于有多个同名目标,则会以列表形式出现,让用户选择:

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

搜索功能:

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

给工程添加非默认类型文件:

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

删除文件:

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

反向删除:

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

同样方法删除CPU目录下无关文件。

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

u-boot 1.3.4源码分析详细教程

2.  u-boot目录结构

u-boot 1.3.4源码分析详细教程

board:存放文件夹的是具体开发板相关文件夹,有的目录是公司名,里面存放具体开发板的文件夹。有的直接开发板文件夹。其中存放的是板级相关文件。

common:通用文件,存放的是所有CPU共用的文件,大部分是u-boot命令支持文件。

像bootm, go,tftpboot ,help 等命令就是在这些文件中实现。

CPU:存放芯片构架相关的文件,一个文件夹代表一个类型的CPU核心。其中的文件夹存放整个核心通用的代码文件以及具体的SOC文件夹。

u-boot 1.3.4源码分析详细教程

Disk              :硬件相关的支持代码。不用修改。

Doc        :u-boot的使用说明书。不用修改。

Drivers  :u-boot设备驱动代码。

Fs          :文件系统代码,不用修改。

include:u-boot头文件,包含有公用头文件,设备驱动相关头文件,以及分体系构架相关的头文件。

u-boot 1.3.4源码分析详细教程

其中有一个文件夹是configs,比较重要,存放开发板配置头文件,每个开发板对应一个头文件,头文件的名字就是开发板的名字。

u-boot 1.3.4源码分析详细教程

lib_generic:通用库文件代码,整个u-boot共用文件。不用修改。

lib*:    其他以lib开头的是具体体系架构相关的库文件,整个个芯片构架共用的文件。不用修改。

nand_spl:nand 驱动。

net:网络协议代码,一般不用修改。

post:一些开发板上电检测代码,一般不用修改。

tool:编译u-boot需要的一些工具代码,不用修改。

README:文本文档,u-boot的编译,配置说明。

Makefile: 管理u-boot的Makefile文件—移植u-boot时候要在这个文件 添加一个自己的开发板配置选项。

u-boot 1.3.4源码分析详细教程

3. u-boot 的启动过程

3.1  u-boot 启动阶段

      分两部分:

1)汇编部分—启动代码;入口: cpu/构架文件夹/start.S

2) C语言代码部分。u-boot复杂功能都是这个阶段实现。

入口:lib_*/board.c 中void start_armboot (void)函数。

任何一个开发板的u-boot都是从cpu/构架文件夹/start.S 文件开始执行。

start.S:启动代码,负责异常向量表定义,初始化CPU时钟,存储器配置,堆栈配置,复制代码到内存中,跳到到C代码阶段。

3.2 start.S分析

以xyd2440为例子分析

入口文件:start.S (cpu\arm920t)  。

工作内容:

1.        异常向量表定义

2.        关看门狗

3.        关中断

4.        配置时钟

5.        配置存储器控制器

6.        配置栈

7.        复制代码到内存

8.        清BSS段

9.        跳转到C代码执行。

3.2.1 补充:GNU 汇编知识

1)可以使用C的方法包含C语言头文件,例如:

u-boot 1.3.4源码分析详细教程

2).globl 关键字:声明一个全局的标号,全局标号,其他可见,可以使用这个标志。
.globl _start  :把_start标号声明为全局的,其他的文件 ,C,链接文件,其他汇编文件都可见。
 
3)标号定义: “标号:” ,如: _start: ,定义一个_start标号。一个标号代表一个地址。

4).balignl关键字:在当前位置以指定对齐方式存放数字。
  .balignl 16,0xdeadbeef  在当前代码所在的地址开始找到第一个16的整数倍地址存放0xdeadbeef
5).word关键字:在当前位置存放一个数值。如:
_TEXT_BASE:
 .word TEXT_BASE
代表在当前地址存放 TEXT_BASE 所代表的数值。
6)可以使用C语言的预处理功能。
#if defined(CONFIG_xyd2440_LED_DEBUG)
…..
#endif
上面代码意思是如果定义了CONFIG_xyd2440_LED_DEBUG宏,就编译其中包含的代码段。

#define S_FRAME_SIZE 72
#define S_OLD_R0 68
上面使用C语言的宏定义功能定义数值。
7)  注释:和C语言一样。同时支持使用@注释。  可用:// ,  /*  */,  @
8)汇编代码专用宏定义:以 .macro 开头 后接宏名,中间宏代码,最后是 .endm 做为结束。
 .macro bad_save_user_regs
 sub sp, sp, #S_FRAME_SIZE
 stmia sp, {r0 - r12}   @ Calling r0-r12
 ldr r2, _armboot_start
 sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
 sub r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
 ldmia r2, {r2 - r3}   @ get pc, cpsr
 add r0, sp, #S_FRAME_SIZE  @ restore sp_SVC

 add r5, sp, #S_SP
 mov r1, lr
 stmia r5, {r0 - r3}   @ save sp_SVC, lr_SVC, pc, cpsr
 mov r0, sp
 .endm
9) .align关键字: 控制代码对齐方式
ARM的.align 5就是2的5次方对齐,也就是4字节对齐,

3.3 分析 :
//异常向量表定义
.globl _start  //把 _start 声明为全局标号               
_start: b  start_code            //第1条指令,复位异常
 ldr pc, _undefined_instruction //未定义异常
 ldr pc, _software_interrupt    //软中断异常
 ldr pc, _prefetch_abort        //预取指中止异常
 ldr pc, _data_abort            //数据中止异常
 ldr pc, _not_used
 ldr pc, _irq                  //IRQ中断异常
 ldr pc, _fiq                  //FIQ中断异常

_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort:  .word data_abort
_not_used:  .word not_used
_irq:   .word irq
_fiq:   .word fiq

当整个u-boot流程走完之后,就真正进入linux的启动系统了。

所以,如果对u-boot整理流程通过软件来认识一边的话,就完全知道linux在启动时,干了哪些事。就像window启动时,会出现一些信息,告诉你当前执行到哪里,执行了什么事,一目了然。

相关推荐