0 引 言
Bootloader是操作系统运行之前执行的一小段程序,用来初始化硬件设备,建立一个系统空间映射图和一个适当的系统软硬件环境。终Bootloader把操作系统内核映像加载到RAM中。并将系统控制权交给内核。BootLoader就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。比如在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。
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)和64MB的SDRAM(Samsung),网卡采用LAN91C96。SDRAM:Synchronous Dynamic Random Access Memory,同步动态随机存储器,RAM(随机存取存储器)RAM -random access memory 随机存储器。存储单元的内容可按需随意取出或存入,且存取的速度与存储单元的位置无关的存储器。这种存储器在断电时将丢失其存储内容,故主要用于存储短时间使用的程序。 按照存储信息的不同,随机存储器又分为静态随机存储器(Static RAM,SRAM)和动态随机存储器(Dynamic RAM,DRAM)。所谓“随机存取”,指的是当存储器中的数据被读取或写入时,所需要的时间与这段信息所在的位置无关。相对的,读取或写入顺序访问(Sequential Access)存储设备中的信息时,其所需要的时间与位置就会有关系(如磁带)。同步是指 Memory工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是自由指定地址进行数据读写。SDRAM从发展到现在已经经历了四代,分别是:代SDR SDRAM,第二代DDR SDRAM,第三代DDR2 SDRAM,第四代DDR3 SDRAM.(显卡上的DDR已经发展到DDR5) 板上有JTAG口、串口和网口,可分别完成程序的和调试工作。目标板的主要硬件资源如图1所示。
2 U-Boot启动过程分析
充分理解代码的启动流程,对于准确地判断出移植过程中出错的原因和出错的位置具有重要的作用。
2.1 U-Boot启动的入口点
一个可执行的Image必须有一个入口点,并且只能有一个全局入口。可执行Image的入口一般通过链接脚本文件来实现,脚本简单地说就是一条条的文字命令,这些文字命令是可以看到的(如可以用记事本打开查看、编辑),脚本程序在执行时,是由系统的一个解释器,将其一条条的翻译成机器可识别的指令,并按程序顺序执行。因为脚本在执行时多了一道翻译的过程,所以它比二进制程序执行效率要稍低一些。本通常可以由应用程序临时调用并执行。各类脚本被广泛地应用于网页设计中,因为脚本不仅可以减小网页的规模和提高网页浏览速度,而且可以丰富网页的表现,如动画、声音等。链接脚本主要用于规定如何把文件内的section放入输出映像文件内,并控制输出文件内各个部分在程序地址空间内的分布。
以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中执行。RAM(随机存取存储器)RAM -random access memory 随机存储器。存储单元的内容可按需随意取出或存入,且存取的速度与存储单元的位置无关的存储器。这种存储器在断电时将丢失其存储内容,故主要用于存储短时间使用的程序。 按照存储信息的不同,随机存储器又分为静态随机存储器(Static RAM,SRAM)和动态随机存储器(Dynamic RAM,DRAM)。
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循环,以接收用户命令。
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键生成的,千万不能以空格代替。
3.4 修改相关代码
从移植U-Boot要求U-Boot能正常启动的角度出发,主要修改如下文件:
incIude/configs/xsbase255.h文件,大多数的寄存器参数都是在这一文件中设置完成的。
board/xsbase255/xsbase255.c文件,只需进行基本的配置,包括设置math-type,启动参数首地址,获取系统的RAM信息等。
board/xsbase255/config.mk文件,设置TEXT-BASE,即设置U-Boot:自己启动时将自己复制到RAM中的起始地址。
驱动程序文件,主要包括网卡驱动和FLASH驱动程序。
3.4.1 目标板配置文件的修改
目标板配置文件inclLlde/configs/xsbase255.h,是移植过程中重要的文件。
#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型闪存,闪存(Flash Memory)是一种长寿命的非易失性(在断电情况下仍能保持所存储的数据信息)的存储器,数据删除不是以单个的字节为单位而是以固定的区块为单位(注意:NOR Flash 为字节存储。),区块大小一般为256KB到20MB。闪存是电子可擦除只读存储器(EEPROM)的变种,EEPROM与闪存不同的是,它能在字节水平上进行删除和重写而不是整个芯片擦写,这样闪存就比EEPROM的更新速度快。由于其断电时仍能保存数据,闪存通常被用来保存设置信息,如在电脑的BIOS(基本输入输出程序)、PDA(个人数字助理)、数码相机中保存资料等。单片容量16 MB,数据线宽度为16 b,2片并作1个32 MB的数据宽度为32b的。BANK。U-Boot本身支持CFI接口规范的闪存,涉及到的文件主要包括drivers/cfi-FLASH.c,comrhand/cmd_FLASH.c。
#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中进行编译和链接。Makefile文件 Makefile 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
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内核的移植打下了坚实的基础。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。