基于PxA255的U-B00t启动分析及移植
扫描二维码
随时随地手机看文章
摘要:Bootloader在嵌入式系统中是必不可少的重要组成部分,这里使用U-Boot 1.3.O在基于PXA255的嵌入式系统上,构建引导加载程序。在对目标板的硬件资源进行简要说明之后,详细分析了U-Boot的启动流程;接着从参考板的选择、目标板支持文件的建立和相关代码的修改,阐述移植的全过程;最后给出了编译和调试的方法。结果表明,U-Boot能稳定地运行。将U-Boot移植到自制的以PXA255为处理器的目标板上,并能成功引导Linux内核,该目标板已经应用于无线传感器网络的汇聚节点,取得了良好的效果。
关键词:U-Boot;PXA255;Bootloader;嵌入式系统;软件移植
0 引 言
Bootloader是操作系统运行之前执行的一小段程序,用来初始化硬件设备,建立一个系统空间映射图和一个适当的系统软硬件环境。最终Bootloader把操作系统内核映像加载到RAM中。并将系统控制权交给内核。
U-Boot被认为是功能最多,最具弹性以及开发最积极的开放源码Bootloader。U-Boot已经能够支持PowerPC,ARM,X86和MIPS体系结构的上百种开发板,U-Boot还具有通过TFTP,从IDE或SCSI磁盘以及DOc启动的能力,还提供了JFFS2的只读功能。正是由于U-Boot较高的可靠性和稳定性;高度灵活的功能设置;丰富的设备驱动程序和丰富的开发和调试文档,因此选择U-Boot作为目标板的Boot-loader。
对于嵌入式系统,Bootloader是基于特定的硬件来实现的,因此建立一个通用的。Bootloader是不可能的,要使Bootloader能在目标板上运行,必须做出相应的修改。
l 目标板
目标板采用Intel PXA255处理器,频率最高可达400 MHz,配置了32 MB的FLASH(Intel StrataFLASH)和64 MB的SDRAM(Samsung),网卡采用LAN91C96。板上有JTAG口、串口和网口,可分别完成程序的下载和调试工作。目标板的主要硬件资源如图1所示。
2 U-Boot启动过程分析
充分理解代码的启动流程,对于准确地判断出移植过程中出错的原因和出错的位置具有重要的作用。
2.1 U-Boot启动的入口点
一个可执行的Image必须有一个入口点,并且只能有一个全局入口。可执行Image的入口一般通过链接脚本文件来实现,链接脚本主要用于规定如何把文件内的section放入输出映像文件内,并控制输出文件内各个部分在程序地址空间内的分布。链接脚本文件位于board目录下的各个开发板目录。
以U-Boot支持的开发板1ubbock为例,查看链接脚本board/lubbock/u-boot.lds,就可以知道各个部分的链接顺序。这个连接脚本决定了U-Boot的第一阶段的代码是从0xO开始的,入口由_start符号指定(ENTRY(_start)),第一个链接的文件是cup/pxa/start.o,那么U-Boot的入口指令一定位于这个程序中。
2.2 U-Boot的启动步骤
U—Boot的启动一般分为stagel和stage2两个部分。依赖于CPU体系结构的代码,通常用汇编语言实现,放在stagel;而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
根据对链接脚本文件和源代码的分析,U-Boot的启动过程中函数调用的顺序如图2所示。
2.2.1 stagel部分
U-Boot的stagel代码从人口函数start.S开始,它用汇编语言写成,主要完成的工作为:设置异常向量;设置CPu的速度、时钟频率及中断控制寄存器;初始化内存控制器;将ROM中的程序复制到RAM中;初始化堆栈;转到RAM中执行。[!--empirenews.page--]
stage1代码执行完以后,就为stage2的运行建立起了基本的硬件环境,此时的U-Boot的存储器SDRAM映射图如图3所示。
2.2.2 stage2部分
接下来进入到U-Boot stage2,即C语言代码部分,入口是start_arml300t,位于lib_arm/board.c中。startarmboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个U-Boot的主函数,该函数主要完成的操作为:初始化本阶段要使用到的硬件设备;检测系统内存映射;将内核映像和根文件系统映像从FLASH拷贝到SDRAM中;为内核设置启动参数;调用内核。
在stage2部分,首先初始化全局数据表;然后顺序执行函数指针数组init_sequence中的初始化函数;接下来调用FLAsH_init()函数初始化CFI FLAsH(针对NOR FLASH);接着调用env_relocate()函数初始化环境变量;然后获取目标板的网络地址,包括IP地址和MAC地址;接着调用commend/console.c中定义的函数console_init_r()初始化串口控制台;最后进入main_loop循环,以接收用户命令。至此Bootloader的任务已经完成:初始化硬件,为内核传递参数,加载内核。
3 U-Boot的移植
3.1 移植的目标与主要工作
在移植之前,需要清楚移植的目标是什么。为了达到这个目标,需要做哪些工作。一般的开发板上U-Boot所需的最小功能,包括:串口、FLASH和网卡,由此可得移植目标是:
(1)将U-Boot移植到目标板FLASH上;
(2)U-Boot能够在目标板上运行起来;
(3)U-Boot能够读写目标板上FLAsH等存储设备;
(4)U-Boot能够使网卡正常工作,能通过网卡下载数据。
根据以上的移植目标,所做的主要工作应该包括:
移植U-Boot与目标CPU相应的代码;移植U-Boot的FLASH驱动;移植U-Boot,的网卡驱动。
3.2 参考板的选取
U-Boot本身已经支持多种开发板,所以在移植的过程中一般不需要从零开始,可以选择一个与自己目标板最接近的参考板,在参考板的基础上进行修改。所以选择适当的参考板是十分重要的,选择参考板的原则是参考板和目标板具有相同的处理器,至少类似的处理器;参考板和开发板具有相同的外围接口电路,至少基本接口相同。总之尽量重用已成熟的代码。
这里目标板的CPU为PXA255,在board目录里选择lubbock开发板作为参考板。对于相应的FLASH设备由于Intel FLAsH支持CFI(Common FLAsHInterface),选择drivers/cfi_FLAsH.c作为FLASH设备驱动。由于目标板使用LAN91C96网卡,所以选择drivers/lan91c96.c作为网卡驱动。
3.3 建立目标板支持文件
选择好参考板后,就可以依据参考板按照下面的步骤建立起目标板的支持文件:
在board目录下,通过“cp-rlubbock xsbase255”建立起目标板的支持目录,将lubbock.c改名为xsbase255.c,在Makefile里把lubbock.o改名为xsbase255.o。
在inclLlde/configs目录里.通过“cp 1ubbock.h xs-base255.h”命令建立起目标板的配置文件,这个文件需要经常修改。
在U-Boot根目录里的MakefiIe中加入如下的命令以创建目标板的编译环境:
xsbase2 5 5 config:unconfig
@$(MKCONFIG)$(@:_config=)arm pxa xsbase255
注意在@$(MKCONFIG)$(@:_config=)arm
pxa xsbase255前面的空白处是由Tab键生成的,千万不能以空格代替。至此,U-Boot已经为目标板配置好了支持文件。
3.4 修改相关代码
从移植U-Boot最小要求U-Boot能正常启动的角度出发,主要修改如下文件:
incIude/configs/xsbase255.h文件,大多数的寄存器参数都是在这一文件中设置完成的。通过宏定义,用于对平台无关的代码进行平台相关的定制,包括U-Boot命令、缺省的环境变量等。
board/xsbase255/xsbase255.c文件,只需进行基本的配置,包括设置math-type,启动参数首地址,获取系统的RAM信息等。
board/xsbase255/config.mk文件,设置TEXT-BASE,即设置U-Boot:自己启动时将自己复制到RAM中的起始地址。
驱动程序文件,主要包括网卡驱动和FLASH驱动程序。[!--empirenews.page--]
3.4.1 目标板配置文件的修改
目标板配置文件inclLlde/configs/xsbase255.h,是移植过程中最重要的文件。在这个文件中,包括两种类型的配置,一类是选项,前缀是CONFIG_,用来选择处理器、接口、命令、属性等;另一类是CFG_用来定义总线频率、串口波特率等。例如:
#define CONFIG_PXA255 1
#define CFG_SDRAMBASE O xa0000000
在这个头文件中,配置相当的重要,里面配置着主要硬件的参数,配置时必须结合相应的硬件手册才能正确的完成。主要的配置参数如表1所示。
除了上述表格列举的以外,还有一些其他的参数需要修改,例如控制台串口缺省的通信波特率,缺省的环境变量设置(包括本地IP地址、以太网接口的掩码和MAC地址、服务器IP地址、传递给内核的命令行参数等),启动参数列表配置等。头文件的修改需要对目标板的硬件资源有相当的了解,主要参考处理器和目标板的开发文档。
3.4.2 目标板支持文件的修改
目标板支持文件board/xsbase255/xsbase255.c也需要修改,此文件中的重点是board_init()函数,这个函数里包含与开发板密切相关的设备的初始化。bi_arch_number为系统启动时传递给内核的MACH号,如果这个参数与内核配置的不相同,则内核启动解压缩完成后将出现“Error:a”错误,提示用户这个是体系结构参数传递不正确。bi_boot_params为启动参数的地址,一般放在RAM起始的16 Kb处,在此设置为Oxa0000100。
3.4.3 驱动的移植
在这一部分主要包括闪存和网卡驱动程序的移植。
(1)FLASH驱动。这里所使用的目标板采用2片NOR型闪存,单片容量16 MB,数据线宽度为16 b,2片并作1个32 MB的数据宽度为32 b的。BANK。U-Boot本身支持CFI接口规范的闪存(CFI是针对NOR型FLASH提出的一种获取闪存和结构参数的操作规程和标准),涉及到的文件主要包括drivers/cfi-FLASH.c,comrhand/cmd_FLASH.c。要使U-Boot,支持CFI驱动,只需在include/configs/xsbase255.h中添加:
#define CFG_FLASH_CFI
#defineCFG_FLASH_CFl_DRIVER 1
(2)网卡驱动。这里使用的目标板上采用的网卡是LAN91C96,U-Boot自带的驱动程序drivers/lan91c96.c恰好支持这个网卡,因此只需在include/Configs/xsbase255.h中添加相应的配置即可:
#define CONFIG_DRIVER_IAN91C96
#define CONFIG_LAN91C96_BASE 0x0C000300
CONFIG_LAN91C96_BASE定义的值,应当由网卡的片选地址和I/O基址决定。如果U-Boot固有的驱动程序没有对目标板的支持,就需要自行在board/xsbase255目录下添加驱动程序,然后将其添加到本目录的Makefile中进行编译和链接。
4 U-Boot的编译和下载调试
在U-Boot根目录里输入命令:
make xsbase255_config
该命令通过./mkconfig脚本生成include/config.mk的配置文件,然后运行make命令,完成编译。如果在编译过程中出现错误,可根据错误的提示逐一排查。完成了错误的修改,在重新编译前,先运行make distclean命令,对先前编译生成的文件进行彻底的清除。
成功编译后,会生成3种不同的映像格式,分别是:u-boot:.bin(二进制格式),u-boot(ELF格式)和u-boot.srec(S—Record格式),根据加载器的不同,选择合适的格式烧写到FLASH中进行运行调试。在此选择u-boot.bin,直接按照二进制格式下载。
最有效的调试方法是下载映像到FLASH,使用硬件仿真器进行跟踪调试。但是由于硬件仿真器价格高等客观因素,采用软件跟踪的方法,利用目标板上的LED灯做出判断。一旦可以打印串口信息,就可以利用串口,将调试信息输出到屏幕上。
5 结 语
U-Boot是一个功能强大的:Bootloader开发软件,对多种开发板的支持使得它可以方便地移植到目标板上。首先详细分析U-Boot启动流程,然后详细介绍U-Boot在PXA255目标板上移植的全过程。目前U-Boot已经在目标板上稳定的运行,为Linux内核的移植打下了坚实的基础。