引言
bootloader通常称为“系统的引导加载程序”,是系统加电或复位后执行的第一段程序代码[1]。这段程序的主要任务是,实现硬件设备初 始化并建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核或用户应用程序准备好正确的环境。通 常,bootloader包含两种不同的加载和启动引导方式,即启动加载方式和下载方式。
① 启动加载(boot loading)方式。这种引导方式也称为“自主(autonomous)引导方式”,也即bootloader从目标机的某个固态存储设备上将操作系统 加载到ram中并引导运行,整个过程并没有用户的介入。这种引导方式是bootloader的正常工作模式下普遍采用的一种引导方式。因此在嵌入式产品发 布的时候,bootloader一般以这种引导方式对内核代码进行启动引导。
② 下载(down loading)方式。在这种引导方式下目标机上的bootloader将通过串口连接或网络连接等通信手段从主机下载文件,如下载应用程序、数据文件、 内核映像等。从主机下载的文件通常首先被bootloader保存到目标机的ram中,然后再被bootloader写到目标机上的固态存储设备中,其后 完成内核的引导运行。bootloader的这种引导方式通常在系统研发和更新时使用。
在嵌入式系统研发阶段,现有的bootloader下载引导方式又可根据加载途径的不同细分为以下几种:
① 通过ethernet网口从宿主机下载内核到目标板,从而实现软件系统启动;
② 通过串口从宿主机下载内核到目标板从而实现软件系统启动;
③ 直接从flash中提取已存储的内核,从而实现软件系统的启动。
总结以上几种引导方式会发现,它们有些共同的弊端;在系统调试时需要进行宿主机与目标板间的硬件线路的实际连接,使用起来不够方便,且烧片的速 度比较缓慢,调试的效率不高;硬件方面需要大容量的flash的支持,增加了研发成本;进行内核更新时显得不够灵活。为此,采用可移动的存储介质对系统内 核进行存储(如sd卡、cf卡等),从而实现对系统内核的灵活调试和引导。这种引导方式的好处是,在调试时无需把宿主机和目标板进行硬件连接,提高了调试 的效率,使用起来更便捷、更灵活;进行内核更新时显得更为灵活,只需把更新内核转存到指定目录,此外它的实现也比较简单。进行这方面的改进时只需做以下工 作:在硬件方面,增加针对特定移动存储介质的硬件电路,而在中大型系统中,有关移动存储介质的硬件电路(如sd卡、cf卡等相关的电路)是现成的,所以硬 件部分也可忽略;在bootloader程序内部,只需添加对移动存储介质(如cf卡、sd卡等)基于文件系统进行存储访问的指令。按此思路,在已有硬件 平台的基础上针对移动设备sd卡对原有bootloader进行了改进。下面介绍实现过程。
1 硬件平台
本次改进测试的硬件平台是由英蓓特公司开发的基于lpc2294 arm控制器的lpc22eb06i实验平台。其上的主要功能模块有:
① 2 mb的flash、1 mb的sram(可扩展到4 mb)、256b具有i2c接口的e2prom等存储器;
② 2个rs232(其中一路可接modem)、rs485、can等通信总线接口;
③ 2个调试接口:lpt和jtag调试接口;
④ 支持cf卡、sd/mmc等移动存储介质;
⑤ 支持128×128真彩显示。
图1是其硬件功能框图。
图1 lpc22eb06i开发平台功能框图
2 bootloader的改进设计
2.1 原有bootloader功能
原来的bootloader具有如下功能:
① 串口下载功能,通过串口下载内核到指定ram区;
② flash烧写功能,从ram区烧写数据到flash中;
③ 数据区内块搬移功能;
④ 其他功能。其指令封装结构如下:
struct _cmd_tbl {
char *cmd;//命令字
bool(*run)(struct _cmd_tbl*cptr,int argc,char**argv);//指向具体的功能处理函数
char*usage;//命令使用方法信息
char*help;//帮助信息
char*helpmore;
};
例如,flash烧写命令封装如下:
cmd_tbl_flash
{"flash",dowritetoflashblocks,
"flash {loader/kernel/root} {block1/.../block16}/n"
" copy to flash from sdram of area./n"
"flash [dest] [src] [len]/n" /
" copy to flash from src to dest./n",
"flash {loader/kernel/root} {block1/.../block16}/n"
" copy to flash from sdram./n",
"flash {loader/kernel/root} {block1/.../block16}/n"
" copy to flash from sdram of area./n"
"flash [dest] [src] [len]/n"
" copy to flash from src to dest./n"
}
其中,flash是其命令字;dowritetoflashblocks为其处理方法的方法名;flash {loader/kernel/root} {block1/.../block16}和flash [dest] [src] [len]为其命令的使用格式(其中“{}”内为可选项,“[]”内为必选项)。
2.2 bootloader改进实验
此次改进就是在原有bootloader的基础上,增加对移动存储介质sd卡以fat格式进行读取数据的指令来实现的。命令封装如下:
cmd_tbl_sd_read
{"readsd", doreadfromsdblocks,
"readsd [filename] [addr] read data from sd to sdram for startup./n",
"readsd [filename] [addr] read data from sd to sdram for startup./n",
"readsd [filename] [addr] read data from sd to sdram for startup./n"
}
其功能是,在sd卡中把指定目录下的内核文件提取到sdram区域中,从而完成内核的加载。
另增加3条辅助指令,一条完成sd卡的格式化,另一条完成对系统内核的保存,最后一条完成对系统内核的启动加载。命令封装如下:
cmd_tbl_sd_format{
"formatsd",doformatsdcard,
"formatsdformat sd card with fat/n",
"formatsdformat sd card with fat/n",
"formatsdformat sd card with fat/n"
}
cmd_tbl_sd_store{
"sdstore", dostoretosdblocks,
"sdstore /[addr] {kernel/rootfs}/n"
"store kernel/rootfs fromsdramto sd card./n",
"sdstore [addr] {kernel/rootfs}/n"
"store kernel/rootfs fromsdram to sd card./n",
"sdstore [addr] {kernel/rootfs}/n"
"store kernel/rootfs fromsdram to sd card./n"
}
cmd_tbl_sd_load{
"sdload", doloadfromsdblocks,
"sdload [addr] {kernel/rootfs}/n"
"load kernel/rootfs from sd card tosdram./n",
"sdstore [addr] {kernel/rootfs}/n"
"load kernel/rootfs from sd card tosdram./n",
"sdstore [addr] {kernel/rootfs}/n"
"load kernel/rootfs from sd card tosdram./n"
}
其中,cmd_tbl_sd_format的功能是完成对sd卡的格式化,cmd_tbl_sd_store的功能是把sdram区域中的内核 代码备份到sd卡的固定存储区,cmd_tbl_sd_load的功能是把sd卡的固定存储区中的内核代码加载到指定的sdram区域中。
下面分析一下其基于fat文件系统的具体读取和备份方法。首先看一下fat文件系统的基本结构。fat文件系统的整体结构大体由4大部分组 成:mbr区(主引导记录区)、dbr区(dos引导记录区)、fat区(文件分配表区,fat1为主文件分配表区,fat2为备份文件分配表区)和 data区(数据区,包含fdt区——文件目录表区)。fat文件系统结构如下:
其各个区域基扇区地址(把mbr区的基扇区地址作为0)计算如下:
dbr区的基扇区地址=mbr基扇区地址 63
fat表的基扇区地址=dbr的基扇区地址 保留扇区数
fdt区基扇区地址=每fat表扇区数×fat表个数 (fdt区的开始簇号2)×每簇扇区数 fat表基扇区地址。(簇是系统进行文件管理的单位,fat表中的每一项对应一个簇,文件的存取按簇进行,一簇包含若干个扇区。)
从fat文件系统的组织结构可以看出,从sd卡中读取系统内核代码数据到指定的ram区比较容易,就是根据系统内核文件名在文件系统中进行查找 定位,随后完成读取。对于内核代码的备份和加载,需要在深入分析fat文件系统的组织结构的基础上对sd卡格式化作一些处理。在格式化时,通过设置mbr 区和dbr区的数据实现不对sd卡存储区的最末8 mb区域(根据实际需要可增减)作格式化处理的目的,即把它置为raw区。所以系统内核备份的实现,就是把系统内核代码通过sd卡的写入指令填充到raw 区。系统内核的加载是从raw区直接读取备份的内核代码。
3 总结
本文所述的内核加载启动引导方式已经过实践验证。它实现了目标板与宿主机间硬件线路连接的完全脱离,为系统调试者提供了便利,有效地提高了系统 调试的效率;与此同时,它还能方便地实现系统的在线更新。可以说要进行系统启动引导设计,此方法是一个不错的选择。最后说明一点,本文介绍的 bootloader改进方法是在lcp2294芯片开发的lpc22eb06i实验平台上完成的。由于bootloader与处理器的体系结构和具体嵌 入式板级设备的配置密切相关,若要在其他的处理器芯片或平台上采用上述方法,还需对bootloader中与处理器体系结构相关的代码作适当的修改。这部 分不是本文探讨的主要内容,所以在此不再详述,若有读者还想详细了解相关内容,请查阅相关论文或书籍。
『本文转载自网络,64体育的版权归原作者所有,如有侵权请联系删除』