SD卡引导Linux内核在ARM11中的实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Jishu Tantao ◆技术探讨
1引言
传统的ARM嵌入式系统大多采用Nor Flash或Nand Flash这2种非易失闪存来存储程序和数据并且引导和启动系统的。

而本文采用的是已经普遍应用于数字产品的SD存储卡。

SD卡较传统的Flash具有明显的优势:
首先,价格便宜,随着SD卡技术的发展和SD卡生产厂商的不断增加,SD卡的价格不断下降,已经和Flash的价格相差无几。

其次,存储容量大,尤其是SDHC卡的出现,目前已经能够达到32GB,并且增大趋势日益明显。

再次,读写方便,我们可以通过读卡器读写SD卡,比起仿真价格便宜,读写速度快。

最后,易插拔、更换和携带方便。

从上述分析可知,SD卡在今后ARM嵌入式的应用会逐渐增加,且很多厂家的芯片已经外扩了SD卡接口。

2系统组成及启动方式
ARM-Linux嵌入式系统包括硬件平台和软件平台2大部分。

我个人在学习和研究ARM-Linux嵌入式系统时使用的平台如下:硬件平台采用Samsung公司的S3C6410处理器、128M的mobile SDRAM、2G的SD卡及其他外部接口设备。

软件平台系统包括引导程序(u-boot)、嵌入式操作系统内核(Kernel)、文件系统(File System)。

由于Linux的开源和使用的广泛性,我选择了Linux内核。

S3C6410是一种兼容性比较好的ARM11处理器。

S3C6410的SD/MMC接口模块可以兼容MMC卡4.2协议和SD卡2.0协议。

这样目前市场上流行的SD/MMC卡和SDHC卡基本就都可以兼容使用了。

S3C6410启动模式有多种方式,分别由XSELNAND,OM[4: 0],GNP[15:13]管脚控制。

图1是系统引导的框图。

系统引导的整个过程是先通过OM管脚确定系统通过什么器件启动。

当把OM[4:1]设置为1111时,表明系统从iROM启动。

iROM启动后要把外围设备的代码拷贝到Stepping Stone中运行。

此时GPN[15:13]用于识别设备的类型。

当GPN[15:13]设置为111时,即从SD/MMC(CH1)设备中拷贝代码。

Stepping Stone执行结束后要把BL2中代码拷贝到SDRAM中,继续执行BL2中的程序。

3SD卡引导Linux内核过程
3.1BL1的引导
整个系统上电或复位后,PC指针指向iROM的起始地址,即0x08000000位置,此段程序称为BL0,大小为32kB。

这段代码是Samsung公司在做芯片的时候固化到芯片中去的。

BL0执行最后的
SD卡引导Linux内核在ARM11中的实现
孙伟忠吴庆洪
(辽宁科技大学,辽宁鞍山114044)
摘要:对目前非常流行的ARM-Linux嵌入式系统的组成进行了介绍,并针对Samsung公司的S3C6410处理器分析了ARM-Linux嵌入式系统从SD卡启动系统的过程,突出该系统从SD卡引导的技术难点,同时针对当下流行的Linux内核进行引导并取得成功。

关键词:ARM;Linux;S3C6410;SD卡
41
机电信息2010年第24期总第270期
技术探讨◆Jishu Tantao
工作就是从SD卡中读取8kB代码到I-RAM(Stepping Stone)中,然后PC指针指向I-RAM的起始地址。

I-RAM的起始地址为0x0C000000,此段程序称为BL1,是用户自己写的代码并且存储到SD卡中的。

对于SD/MMC卡,S3C6410是从SD卡所有扇区的最后18个扇区(每个扇区512Bytes)开始读取8kB的程序。

而对于SDHC卡是从SDHC卡所有扇区的最后1042个扇区开始读取8kB的程序。

这是由S3C6410芯片中iROM的代码决定的。

因此我们要将程序根据使用卡的种类放到指定的位置上。

以下都以SD/MMC为例进行研究,代码分布结构如表1所示。

其中MBR为SD卡分区后的主引导纪录,Kernel是Linux操作系统的内核,User File System是用户的文件系统,BL2是系统第二阶段引导的代码,ENV是Linux系统内核引导时需要的环境变量,BL1是系统第一阶段引导的代码,最后的1kB 字节为保留使用。

往往研究Linux的时候都会借用很多源代码来进行,因此我选用u-boot来进行说明。

先来分析u-boot生成二进制代码的空间结构,然后再分析具体内容。

一般而言u-boot生成二进制代码是大于8kB小于256kB的u-boot.bin文件。

由于BL1只有8kB,所以需要把u-boot.bin转换为8kB的BL1和BL2代码。

具体实现可以把u-boot.bin的前8kB的代码放到SD卡的BL1位置上,然后把整个u-boot.bin文件写入到SD 卡的BL2位置上。

到目前为止我们只知道BL1的位置,其他的位置并不知道,这是因为其他段的写入位置和u-boot有很大关系。

3.2BL2的引导
下面分析一下u-boot程序是如何从SD卡中把BL2和ENV引导出来的。

系统在BL1中首先执行的是cpu目录下对应平台的目录中有一个启动文件start.S,当执行到blmovi_bl2_copy时,这时PC指针要跳转到当前目录下的movi.c文件中执行movi-bl2-copy程序。

movi-bl2-copy中执行CopyMovitoMem(HSMMC_CHANNEL,MOVI_BL2_POS,MOVI_BL2_BLKCNT,(uint*)BL2_BASE,MOVI_ INIT_REQUIRED)指令。

而CopyMovitoMem是iROM启动后提供给用户的一个函数,函数的指针在0×0C004008地址中,包含5个参数。

还提供了一个SD/MMC卡总扇区的参数,存放在0×0C003FFC 地址中。

参数MOVI_BL2_POS是要从SD/MMC中拷贝的第几个扇区开始,参数MOVI_BL2_BLKCNT为拷贝扇区的数目,BL2_BASE 为拷贝到什么位置上。

从movi.h中可以看出,MOVI_BL2_POS是SD/MMC中的总扇区数减去562个扇区,如果是SDHC卡则为SDHC的总扇区数减去1586个扇区。

MOVI_BL2_BLKCNT是512个扇区也就是前面说到的256kB。

BL2_BASE是0×C7E00000,为内存中代码存储的地址,这个地址是通过MMU把0×57E00000影射到0×C7E00000中的。

这样u-boot中就实现了BL2段代码的拷贝。

并且也知道了应该把BL2放到SD卡的什么位置上。

同样的道理,我们可以得到ENV段中的环境变量放在哪里,只不过这次没有用到iROM中提供的拷贝函数接口,而是直接使用BL2中对SD卡读写的函数。

这里直接给出ENV放到SD卡中的BL2和BL1中间的32个扇区的位置上。

代码拷贝完后,PC指针是如何跳到BL2中运行的呢?在启动文件start.S中有一条指令为ldrpc,_start_armboot,而start_armboot是在BL2中的程序,这样就实现了BL1到BL2的转换过程。

但是,PC指针
实际是跳到了start_armboot在编译时的地址,因此在拷贝BL2时是把整个的u-boot.bin搬运到原来设计的地址。

这样就保证以后所有的程序都在原本设计的位置开始运行。

3.3Kernel的引导
通过上述可以了解到系统从BL0引导BL1,从BL1引导BL2,在BL2中获取了ENV中的环境变量。

但是对于Linux内核如何引导到内存还一直不清楚。

其实Kernel是通过ENV中设置的环境变量引导的。

在BL2中,u-boot会从SD卡读取ENV中的环境变量并且利用crc32来校验环境变量是否正确。

如果校验正确则使用ENV中的环境变量。

如果错误则使用u-boot中默认的环境变量。

我们以系统默认的环境变量为例来说明,其中系统默认的环境变量为common目录下的env_common.c中的default_environment。

d efault_environment中有这条语句“bootcmd=”CONFIG_BOOT-COMMAND。

在include目录下smdk6410.h中又定义了#defin
e CON-FIG_BOOTCOMMAND“movi read320×008000000×c0008000;bootm0×c0008000”。

当系统执行到引导内核时,实际上是执行上面命令中的两个命令:
第一个命令执行的是common目录下的cmd_movi.c中的do_movi函数,read参数是表示读操作的意思,32参数表示从第32个扇区开始操作,0×00800000个参数表示操作的大小为0×00800000个字节,0×c0008000表示操作的目的地址从0×c0008000开始。

其功能执行的是从SD/MMC的第32个扇区读取大小为0×00800000多的字节到内存中的0×c0008000开始的地址位置上。

第二个命令执行的是common目录下的cmd_bootm.c中的do_bootm函数,0×c0008000参数表示执行的虚拟地址。

其功能是从0×c0008000这个虚拟地址对应的物理地址0×50008000中开始执行程序。

从上面的介绍现在已经了解到Kernel的代码默认应该放到SD 卡的第32个扇区开始的位置上,大小应该在8M字节以内。

并且也知道了内核的执行默认是从物理地址为0×50008000中开始执行的。

因此PC指针最后跳到了这个地址上执行,并且从这以后u-boot 的执行权利就交给了Linux的内核。

4结语
通过SD卡在Samsung公司的S3C6410上引导Linux内核,已经成功地把Linux的内核启动起来了。

对于BL2和ENV在SD卡的存放位置和大小的改变可以通过修改u-boot代码来完成。

对于如何把程序写入到SD卡中相应的位置,我推荐使用WinHex软件。

WinHex软件的下载和使用非常方便。

下一个阶段的工作就是如何制作文件系统和在整个系统上做属于自己的应用程序,这是我今后主要研究的方向。

[参考文献]
[1]USER'SMANUALS3C6410XRISCMicroprocessorAug22,2008REV1.10
[2]ApplicationNote(InternalROMBooting)RISCMicroproces-sorS3C6410XJuly24,2008REV1.00
收稿日期:2010-06-28
作者简介:孙伟忠(1981-),男,辽宁海城人,助教,硕士,研究方向:图像处理、模式识别、嵌入式系统。

表1代码在SD卡分布结构
SD/MMC
MBR Kernel User File System BL2ENV BL1(8kB)1kB 42。

相关文档
最新文档