uboot的介绍
1.1
uboot的介绍
Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序,
UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS,
LynxOS嵌入式操作系统。UBoot除了支持PowerPC系列的处理器外,还能支持MIPS、
x86、ARM、NIOS、XScale等诸多常用系列的处理器。
1.2
uboot的体系结构
目录树
|--board
|--common
|--cpu
|--disk
|--doc
|--drivers
|--dtt
|--examples
|--fs
|--include
|--lib_arm
|--lib_generic
|--net
|--post
|--rtc
|--tools
1.
board:和一些已有开发板有关的文件. 每一个开发板都以一个子目录出现在当前目录中,比如说:
leopard2a子目录中存放与我们开发板相关的配置文件.
2.
common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。例如bootm命令对应就是cmd_bootm.c。
3.
cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm926ejs就是我们开发板上使用的cpu架构目录。
4.
disk:对磁盘的支持。
5.
doc:文档目录。Uboot有非常完善的文档,推荐大家参考阅读。
6.
drivers:Uboot支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
7. fs:
支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。
8.
include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。该目录下configs目录有与开
发板相关的配置头文件,如leopard2a.h。该目录下的asm目录有与CPU体系结构相关的头文件,asm对应的是asmarm.
9.
lib_xxxx: 与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。
10.
net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
11.
tools:生成Uboot
的工具,如:mkimage,
crc等等。
2、uboot的运行过程分析
2.1
启动模式介绍
大多数 Boot Loader
都包含两种不同的操作模式:"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader
的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
启 动加载(Boot
loading)模式:这种模式也称为"自主"(Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM
中运行,整个过程并没有用户的介入。这种模式是 BootLoader 的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader
显然必须工作在这种模式下。
下载(Downloading)模 式:在这种模式下,目标机上的 Boot Loader
将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 BootLoader
保存到目标机的 RAM 中,然后再被 BootLoader 写到目标机上的FLASH 类固态存储设备中。BootLoader
的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 BootLoader 的这种工作模式。工作于这种模式下的 Boot
Loader 通常都会向它的终端用户提供一个简单的命令行接口。
UBoot这样功能强大的 Boot Loader
同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。
2.2
运行过程
大
多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot也不例外。依赖于CPU体系结构的代码(如CPU初
始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
U
- Boot 编译后的代码定义一般不超过100kB ,并且这100 kB 又分成两个阶段来执行. 第一阶段的代码在start . s 中定义,大小不超过10
kB ,它包括从系统上电后在0x00000000 地址开始执行的部分. 这部分代码运行在Flash 中,它包括对arm926ejs的一些寄存器的初始化和将U -
Boot 的第二阶段代码从Flash 拷贝到SDRAM 中. 除去第一阶段的代码,剩下的部分都是第二阶段的代码.
第二阶段的起始地址是在第一阶段代码中指定的,被复制到SDRAM后,就从第一阶段跳到这个入口地址开始执行剩余部分代码. 第二阶段主要是进行一些BSS
段设置,堆栈的初始化等工作,最后会跳转到main -loop 函数中,接受命令并进行命令处理. 图1 给出了U - Boot
的详细的运行过程包括对内核的设置、装载及调用过程。
2.3
本开发板的地址分布(leopard2a)
本目标板是RAM 16M, Flash
8M,具体空间如图所示:
1F12FFFF
Uboot
Uboot_env
Kernel
Rootfs
1F000000
1F020000
1F01FFFF
1F02FFFF
1F030000
1F130000
1F7EFFFF
Kernel
Rootfs
FLASH
SDRAM
0x00030000
0x00130000
0x00430000
可以根据变换后的分区结构,设置
uboot_addr,uboot_addr_end,kernel_addr,kernel_addr_end,rootfs_addr,rootfs_addr_end,
config_addr,
config_addr_end等环境变量,调整bootloader。
SDRAM的调整修改linux-2.4.20_mvl31/drivers/mtd/maps/physmap.c
2.4
运行代码分析
2.4.1 stage
1
uboot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码包括定义入口,设置异常向量,设置cpu的模式和频率,配置内存区控制寄存器,安装uboot的栈空间,关闭看门狗等。由于本人对ram的汇编不太熟悉,所以这一部分不作具体分析。
2.4.2
stage 2
lib_arm/board.c中的start
armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个uboot(armboot)的主函数,该函数主要完成如下操作:
2.4.2.1
调用一系列初始化函数
1. 指定初始函数表:
init_fnc_t
*init_sequence[] = {
cpu_init, /* cpu的基本设置
*/
board_init, /* 开发板的基本初始化 */
interrupt_init,
/* 初始化中断 */
env_init, /* 初始化环境变量
*/
init_baudrate, /* 初始化波特率 */
serial_init, /*
串口通讯初始化 */
console_init_f, /* 控制台初始化第一阶段
*/
display_banner, /* 通知代码已经运行到该处 */
dram_init,
/* 配制可用的内存区 */
display_dram_config,
#if
defined(CONFIG_VCMA9) || defined
(CONFIG_CMC_PU2)
checkboard,
#endif
NULL,
};
执行初始化函数的代码如下:
for
(init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
{
if ((*init_fnc_ptr)() != 0)
{
hang
();
}
}
2.
配置可用的Flash区
flash_init ()
3.
初始化内存分配函数
mem_malloc_init()
4. nand
flash初始化
#if (CONFIG_COMMANDS &
CFG_CMD_NAND)
puts ("NAND:");
nand_init();
/* go init the NAND
*/
#endif
5.
初始化环境变量
env_relocate ();
6.
外围设备初始化
devices_init()
7.
I2C总线初始化
i2c_init();
8.
LCD初始化
drv_lcd_init();
9.
VIDEO初始化
drv_video_init();
10.
键盘初始化
drv_keyboard_init();
11.
系统初始化
drv_system_init();
2.4.2.2
初始化网络设备
初始化相关网络设备,填写IP、MAC地址等。
1.
设置IP地址
gd->bd->bi_ip_addr = getenv_IPaddr
("ipaddr");
2.
设置mac地址
{
int i;
ulong
reg;
char *s,
*e;
uchar
tmp[64];
i = getenv_r
((uchar*)("ethaddr"), tmp, sizeof (tmp));
s = (i > 0) ? (char*)tmp :
NULL;
for (reg = 0; reg <
6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) :
0;
if
(s)
s = (*e)
? e + 1 : e;
}
}
2.4.2.3 进入主UBOOT
命令行
进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
for
(;;) {
main_loop
();
}}
3、uboot的移植和测试
3.1
移植的过程
① 在宿主机上建立交叉编译开发环境
②
修改cpu/arm926ejst目录中的文件内容,
主要包含cpu.C,start.S,interrupts.C以及seria1.C,speed.C等文件
③
在board目录下创建自己的目标板(开发板)目录leopard2a
在目录下创建leopard2a.C,flash.C,memsetup.S
以及Makefile,u-bot.1ds,config.mk文件
④
在include/configs目录下创建leopard2a.h
⑤
打开u-bot目录下Makefile文件,加入如下两行:
leopard2a_config :
unconfig
@./mkconfig $(@:_config=) arm arm926ejs
leopard2a
⑥ 编译。运行命令:
1. make
leopard2a_config
2.
make
编译成功.生成基本的u—b00t.
⑦
烧写.把编译成的u-bot.bin
至此移植u-bot过程结束.
3.2
移植主要修改的文件
移植u—boot到开发板上只需要修改和硬件相关的代码即可。这首先就联想到cpu目录下的启动代码,另外参考u—boot/readme文件可知其他还需要修改的主要文件有:
Makefile文件,和include目录下的目标板.h头文件(leopard2a.h),board目录下的目标板.C文件(leopard2a.c),flash.C文件,u-boot.1ds链接文件,以及cpu目录下的串口驱动文件。
具体修改如下:
①
cpu/arm926ejst目录下
② board/leopard2a
③
include/configs目录下leopard2a.h文件.此文件是leopard2a目标板头文件,大多数寄存器参数是在这一文件中设置完成的.
3.3
uboot网络下载功能的添加和RAM调试
在commom/main.c
中的main_loop函数中添加tftp下载的函数,可以通过按钮触发下载rimage,kimage。
在烧录u-boot.bin之前,需要进行ram调试,保证uboot可以在EVB上正常运行。
先下載U-boot
到SDRAM上, 然後執行SDRAM 上的U-boot 程序, 以確認U-boot可以正常執行, Command 如下:
1.
“tftp a00000 u-boot.bin” <= 下載程序到SDRAM
2. “go a00000” <=
從SDRAM 執行程序
如果U-boot 可以相容於目前的硬件, 5VT EVB
會重新正常啟動,要是不能正常啟動,表示U-boot 不相容於目前的硬件, 請更換新的u-boot。再重新測試,
直到被測試的U-boot可以正常啟動!
原文地址:http://www.cnblogs.com/tanshupeng/p/3776214.html