桂林电子科技大学毕业设计(论文)报告用纸 第 16 页 共 56 页
post examples tools doc
通用 存放上电自检程序 应用例程 一些独立运行的应用程序的例子,如helloworld 工具 文档 存放一些制作映像的工具,如mkimage 开发使用文档 U-Boot的源代码包含对几十种处理器、几百种开发板的支持,对于特定的开发板,配置编译只需要改动其中平台依赖的部分程序即可。 3.1.1 LPC2468OEM_Board中几个重要的文件
① cpu/arm720t/start.S:在flash中执行的引导代码,负责初始化硬件环境,把U-Boot从flash加载到RAM中去,然后跳到lib_arm/board.c中的start_armboot中去执行。
② lib_arm/board.c:U-Boot的初始化流程,尤其是U-Boot用到的全局数据结构gd、bd的初始化,以及设备和控制台的初始化。
③ board/LPC2468OEM_Board/lowlevelsys_init.c、nand.c、eth.c等:在board目录下的代码都是严重依赖于目标板的。对于不同的CPU、SOC、ARCH来说,U-Boot都可以有相对通用的代码。但是板子的构成却是非常多样的,主要的差别是内存地址、flash型号、外围芯片如网络等等。以上几个文件分别用于LPC2468OEM_Board板的低级初始化、nand flash驱动、网络驱动等。如果要给开发板修改驱动程序或添加新的设备驱动程序,即添加在此处。
④ include/configs/ LPC2468OEM_Board.h:这个头文件中主要定义了两类变量。一类是选项,前缀是CONFIG_,用来选择处理器、设备接口、命令、属性等,主要用来决定是否编译某些文件或者函数。另一类是参数,前缀是CFG_,用来定义总线频率、串口波特率、Flash地址等参数。这些常数参量主要用来支持通用目录中的代码,定义板子资源参数。
这两类宏定义对U-Boot的移植性非常关键,开发板上的相关硬件设备的启用与否,是通过编译条件判断#ifdef或#ifndef来选择配置编译的。U-Boot的命令也要通过这个配置头文件来进行配置:比如要添加ping命令,就必须添加CFG_CMD_NET和CFG_CMD_PING,不然common/cmd_net.c就不会被编译了。
⑤ board/LPC2468OEM_Board/config.mk和board/LPC2468OEM_Board/u-boot.lds:这两个文件跟U-Boot的内存分配有关。config.mk中的TEXT_BASE项定义了U-Boot的起始地址。u-boot.lds是编译的链接脚本文件,定义了链接生成U-Boot映像时各程序段的起始地址、内存分配、对齐方式等。
16
桂林电子科技大学毕业设计(论文)报告用纸 第 17 页 共 56 页
⑥ board/LPC2468OEM_Board /Makefile:板级的编译配置文件。使用该文件可以配置board目录中的哪些文件被编译进映像中。 3.1.2 U-Boot的启动流程
对于LPC2468平台来说,U-Boot启动流程主要是在两个文件中:cpu/arm720t/start.S和lib_arm/board.c。
start.S是U-Boot的引导代码,相当于常说的bootloader中的stage1,负责初始化硬件环境,把u-boot加载到RAM中去,然后跳到相关入口中去执行。
start.S完成的主要工作有: ① 定义程序入口;
一个可执行的Image 必须有一个并且只能有一个唯一的全局入口点。通常这个入口放在Rom(flash)的0x0 地址。start.S 中是依靠一个.globl _start标号来定义的。 ② 设置异常向量(Exception Vector);
异常向量表,也可称为中断向量表,必须是从地址0开始连续的存放。如ARM体系结构中包括复位(reset)、未定义处理(undef)、软件中断(SWI)、预取指令错误(Pabort)、数据错误(Dabort)、保留、以及IRQ、FIQ等异常模式。 ③ 初始化硬件环境;
代码中依次顺序为:进入SVC模式,擦除I/D Cache,关闭MMU部件,关闭中断,设置PLL(phase lock loop)时钟和存储器。相关代码见源代码中的cpu_init_crit过程。 ④ 内存重定位;
⑤ 转到C语言函数入口执行;
board.c里的start_armboot()函数是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。这里只简要列出其主要执行的函数流程:
void start_armboot (void) {
/* 给全局数据变量gd安排空间*/
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); memset ((void*)gd, 0, sizeof (gd_t)); /* 给开发板数据变量gd->bd安排空间*/ gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t));
monitor_flash_len = _bss_start - _armboot_start;//取u-boot的长度。 /* 顺序执行init_sequence数组中的初始化函数 */
17
桂林电子科技大学毕业设计(论文)报告用纸 第 18 页 共 56 页
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }
/*配置可用的Flash */ size = flash_init (); ??
/* 初始化堆空间 */
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); /* 重新定位环境变量, */ env_relocate ();
/* 从环境变量中获取IP地址和以太网接口MAC 地址*/ gd->bd->bi_ip_addr = getenv_IPaddr (\ ……
/* 设备初始化 */ devices_init ();
/* 跳转表初始化 */ jumptable_init ();
/* 完整地初始化控制台设备 */ console_init_r ();
/* 使能中断处理 */ enable_interrupts ();
/* 通过环境变量初始化 */
if ((s = getenv (\
load_addr = simple_strtoul (s, NULL, 16); }
/* main_loop()循环不断执行 */ for (;;) {
main_loop (); /* 主循环函数处理执行用户命令 -- common/main.c */
} }
18
桂林电子科技大学毕业设计(论文)报告用纸 第 19 页 共 56 页
3.2 U-Boot的配置和编译
U-Boot工程的可配置性和移植性可以分为两层:一是由目录顶层的Makefile来实现,配置工程要包含的文件和文件夹,用什么编译器等等。二是由目标板的配置头文件来实现源码级的可配置性,通用性。主要使用的是#ifdef #else #endif 之类来实现的。 U-Boot的源码是通过GCC和Makefile来组织编译的。运行make命令以后,所有子目录的编译连接都由顶层目录的Makefile文件来确定,首先由顶层目录下的Makefile设置开发板定义,然后递归的调用各级子目录下的Makefile,最后把编译过的程序链接成U-Boot映像。
在执行make之前,先要执行make $(board)_config对工程进行配置,以确定特定于目标板的各个子目录和头文件。
$(board)_config:是Makefile 中的一个伪目标,它传入指定的CPU,ARCH,BOARD,SOC参数去执行mkconfig脚本。这个脚本的主要功能在于连接目标板平台相关的头文件夹,生成config.h文件包含板子的配置头文件。使得Makefile能根据目标板的这些参数去编译正确的平台相关的子目录。
执行make LPC2468OEM_Board_config,即可完成目标板的配置,并写入顶层Makefile中。
Makefile文件中的相关代码为:
LPC2468OEM_Board_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm720t LPC2468OEM_Board NULL lpc2468
顶层的Makefile还要定义交叉编译器、U-Boot所依赖的目标文件、映像编译的依赖关系等。缺省的编译目标为all,包括u-boot(U-Boot映像的ELF格式)、u-boot.bin(U-Boot映像的原始二进制格式)、u-boot.srec(U-Boot映像的S-Record格式)、System.map(U-Boot映像的符号表)一共四个文件。U-Boot通过ld命令按照System.map地址表把目标文件组装成u-boot。u-boot.bin和u-boot.srec依赖于u-boot,3种映像格式都可以烧写到Flash中,但需要看加载器能否识别这些格式。一般u-boot.bin最为常用,直接按照二进制格式下载,并且按照绝对地址烧写到Flash中就可以了。u-boot和u-boot.srec都自带地址定位信息。
3.3 U-Boot的移植
U-Boot能够支持多种体系结构的处理器,而且它能够支持的开发板也已经越来越多。由于Bootloader程序是完全依赖于底层硬件平台的,所以在一块新电路板上使用
19
桂林电子科技大学毕业设计(论文)报告用纸 第 20 页 共 56 页
U-Boot程序时,需要做一定的移植工作。
开始移植U-Boot之前,先要熟悉硬件电路板和处理器。确认U-Boot是否已经支持新电路板的处理器和I/O设备。假如U-Boot已经支持一块非常相似的电路板,那么移植的过程将会非常简单。
移植U-Boot工作主要是:添加开发板硬件相关的文件、配置选项,然后配置编译。 开始移植之前,需要先分析一下U-Boot已经支持的开发板,比较出硬件配置最接近的开发板。选择的原则是,首先处理器相同,其次处理器体系结构相同,然后是以太网接口等外围接口。还要验证一下这个参考开发板的U-Boot,至少能够配置编译通过。
我们是用EA公司提供的uboot 1.1.6源码进行移植,主要的工作包括norflash驱动,nandflsh驱动,网卡驱动的移植以及一些相关文件的修改。 [piaozhiye@localhost ~]$ tar -xzvf u-boot-1.1.6.tar.gz [piaozhiye@localhost ~]$ cd u-boot-1.1.6
[piaozhiye@localhost u-boot-1.1.6]$ make LPC2468OEM_Board_config [piaozhiye@localhost u-boot-1.1.6]$make
将/u-boot-1.1.6/common/cmd_bootm.c:167行注释掉否则会出现以下错误,它只是打印一些信息 无关紧要。
//printf(\%x %x\\r\\n\ADDRESS_PAGE_0, CACHE_PAGE_CTRL, CACHE_SETTINGS);
cmd_bootm.c: In function `do_bootm':
cmd_bootm.c:167: error: `ADDRESS_PAGE_0' undeclared (first use in this function) cmd_bootm.c:167: error: (Each undeclared identifier is reported only once cmd_bootm.c:167: error: for each function it appears in.)
cmd_bootm.c:167: error: `CACHE_PAGE_CTRL' undeclared (first use in this function)
cmd_bootm.c:167: error: `CACHE_SETTINGS' undeclared (first use in this function) make[1]: *** [cmd_bootm.o] 错误 1
将/u-boot-1.1.6/lib_arm/board.c:397和398行注释掉,USB 相关的。我们没有用到USB将其注释掉。 //usbhw_init(); //usbstatus_check();
/home/piaozhiye/u-boot-1.1.6/lib_arm/board.c:397: `usbhw_init'
/home/piaozhiye/u-boot-1.1.6/lib_arm/board.c:398: `usbstatus_check'
到此即可编译通过,uboot也可以在串口打印出启动信息。
20
undefined undefined
reference reference
to to