您的位置:首页 > 其它

Uboot学习总结(续一)

2015-08-05 10:49 183 查看
文章是一年前做项目时候写的,现在有时间将其贴出来,其中大部分引用http://www.ibm.com/developerworks/cn/linux/l-btloader/上描述,这里特作说明。

2.1、基本架构

Uboot的基本结构和定义在不同的版本之间会有一些修改,但不管怎么修改其大体的目录架构都不会有太大的变化,如下截取2014.04版本基本架构。

.

|--Licenses

|-- api

|-- arch

|-- board

|-- common

|-- disk

|-- doc

|-- drivers

|-- dts

|-- examples

|-- fs

|-- include

|-- lib

|-- nand_spl

|-- net

|-- post

|-- scripts

|-- spl

|-- test

`-- tools

1、Licenses这个目录没什么东西,只是uboot的一些声明介绍;

2、Api这个目录下是,为外部的应用提供的一些接口程序;

3、Arch这个目录与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录;
4、board:其中包含SDRAM 初始化代码、Flash 底层驱动、板级初始化文件。
5、common:与处理器体系结构无关的通用代码,实现uboot命令行下支持的命令,以及环境变量的处理函数。
6、disk:磁盘驱动的分区处理代码。
7、doc:文档目录。Uboot有非常完善的文档,推荐大家参考阅读。
8、drivers:Uboot支持的外围设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
9、dts:支持平坦设备树(flatteneddevice trees)的文件;
10、examples:API接口实例;
11、fs: 支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。
12、include:头文件,包括各CPU 的寄存器定义,文件系统、网络等等configs 子目录下的文件是与目标板相关的配置头文件
13、lib: 最新版本中的lib文件中是,CRC校验,压缩以及解压缩、以及加密处理的文件;
14、nand_spl:一些特殊构架需要的启动代码;
15、net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
16、post:Power-On-Self-Test,即开机自测试功能软件代码;
17、scripts: 目录下的文件是用于配置系统构建的程序源文件。
18、spl:统一所有现有实现二级程序加载程序(SPL);
19、test:最新发布的版本中有这个test文件;
20、tools:生成Uboot的工具,如:mkimage, crc等等。

2.2、uboot的启动流程

1、分析启动过程

Uboot的启动过程大致可以分为Stage1和Stage2两个过程。对于依赖CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且代码会具有更好的可读性和可移植性。

Stage1阶段:

1> 对硬件设备进行初始化操作

1屏蔽所有的中断。为中断提供服务通常是OS 设备驱动程序的责任,为避免在启动过程中OS响应中断,导致启动失败,所以在Boot Loader 的执行全过程中屏蔽何中断。中断屏蔽可以通过写CPU 的中断屏蔽寄存器或状态寄存器来完成。

2设置CPU 的速度和时钟频率。

3RAM初始化。包括正确地设置系统的内存控制器的功能寄存器以及各内存库控制寄存器等。

4初始化UART。通过初始化UART 向串口输出打印来说明uboot第一阶段初始化已成功(还可以通过点亮LED来判断)。

5关闭CPU 内部指令/数据cache。

2> 为加载uboot而准备RAM空间

为了获得更快的执行速度,通常把 stage2 加载到 RAM 空间中来执行,因此必须为加载 uboot的stage2 准备好一段可用的RAM 空间范围。

由于stage2 通常是有C 语言编写的代码,因此在考虑空间大小时,除了stage2 可执行映象的大小外,还必须把堆栈空间也考虑进来。此外,空间大小最好是memory page (通常是4KB)的倍数。一般1M的RAM 空间已经足够了。具体的地址范围可以任意安排。

另外,还必须确保所安排的地址范围的的确确是可读写的RAM 空间,因此,必须对所安排的地址范围进行测试。具体的测试方法可以采用以memory page 为被测试单位,测试每个memory page 开始的两个字是否是可读写的。其具体步骤如下:

1先保存memory page 开始两个字的内容。

2向这两个字中写入任意的数字。比如:向第一个字写入0x55,第2 个字写入0xaa。

3然后,立即将这两个字的内容读回。显然,我们读到的内容应该分别是0x55 和0xaa。如果不是,则说明这个memory page 所占据的地址范围不是一段有效的RAM 空间。

4再向这两个字中写入任意的数字。比如:向第一个字写入0xaa,第2 个字中写入0x55。

5然后,立即将这两个字的内容立即读回。读到的内容应该分别是0xaa 和0x55。如果不是,则说明这个memory page 所占据的地址范围不是一段有效的RAM 空间。

6恢复这两个字的原始内容。测试完毕。

为了得到一段干净的 RAM 空间范围,可以将所安排的 RAM 空间范围进行清零操作。

3> 将uboot拷贝到RAM中

拷贝时要确定两点:1stage2 的可执行映象在固态存储设备的存放起始地址和终止地址;2RAM 空间的起始地址。

4>设置好堆栈

堆栈指针的设置是为了执行C语言代码作好准备。通常我们可以把 sp的值设置为(stage2_end-4),上述安排的那个 1MB 的 RAM 空间的最顶端(堆栈向下生长)。经过上述这些执行步骤后,系统的物理内存布局应该如下图2.2.1所示。

5>最后调到C语言接口

在上述一切都就绪后,就可以跳转到 uboot的stage2 去执行了。

图2 uboot 的 stage2 可执行映象刚被拷贝到 RAM 空间时的系统内存布局:



图2.2.1
Stage2阶段:

正如前面所说,stage2 的代码通常用 C 语言来实现,以便于实现更复杂的功能和取得更好的代码可读性和可移植性。但是与普通C 语言应用程序不同的是,在编译和链接uboot 这样的程序时,不能使用glibc 库中的任何支持函数。为处理启动函数接口同时具有处理返回值和传递参数的功能,uboot采用了Boot Loader一贯的设计方式:采用汇编语言写一段trampoline小程序,并将这段 trampoline小程序来作为stage2可执行映象的执行入口点。然后我们可以在 trampoline汇编小程序中用CPU跳转指令跳入入口函数中去执行;而当入口
函数返回时,CPU执行路径再次回到trampoline程序。这种方法的思想就是:用这段trampoline小程序来作为入口函数的外部包裹(externalwrapper),来处理启动函数接口同时具有处理返回值和传递参数的功能。

1>初始化本阶段要使用到的硬件设备

1初始化至少一个串口,以便和终端用户进行 I/O 输出信息;

2初始化计时器等。设备初始化完成后,可以输出一些打印信息,程序名字字符串、版本号等。

2>检测系统内存映射(memory map)

将存储在 flash 上的内核映像读到 RAM中之前检测整个系统的内存映射情况,以明确哪些RAM是处于空闲状态的。

3>将 kernel 映像和根文件系统映像从 flash 读到 RAM 中

1规划内存占用的布局

这里包括两个方面:a、内核映像所占用的内存范围;b、根文件系统所占用的内存范围。在规划内存占用的布局时,主要考虑基地址和映像的大小两个方面。对于内核映像,一般将其拷贝到从(MEM_START+0x8000) 这个基地址开始的大约1MB大小的内存范围内(嵌入式 Linux 的内核一般都不操过 1MB)。为什么要把从 MEM_START 到 MEM_START+0x8000 这段 32KB 大小的内存空出来呢?这是因为 Linux 内核要在这段内存中放置一些全局数据结构,如:启动参数和内核页表等信息。而对于根文件系统映像,则一般将其拷贝到MEM_START+0x0010,0000
开始的地方。如果用Ramdisk 作为根文件系统映像,则其解压后的大小一般是1MB。

2从 Flash 上拷贝

由于嵌入式 CPU 通常都是在统一的内存地址空间中寻址 Flash 等固态存储设备的,因此从 Flash 上读取数据与从 RAM 单元中读取数据并没有什么不同。用一个简单的循环就可以完成从Flash 设备上拷贝映像的工作。

4>为内核设置启动参数,

将内核映像和根文件系统映像拷贝到 RAM 空间中后,就可以准备启动 Linux 内核了。但是在调用内核之前,应该作一步准备工作,即:设置Linux 内核的启动参数。

5>调用内核

BootLoader 调用Linux 内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到MEM_START+0x8000地址处。在跳转时,满足内核启动的条件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: