基于ARM的μCLinux启动引导实现的分析
扫描二维码
随时随地手机看文章
摘 要:本文介绍了ARM-μC嵌入式系统的结构组成,结合ARM体系结构的特点和嵌入式操作系统μC的应用的普遍性,着重分析了ARM-μC嵌入式系统启动引导程序的过程实现以及该系统启动引导的关键点,提出了一种有效的启动引导方案。
关键词:嵌入式系统 引导 ARM μCLinux 嵌入式操作系统
引言
32位ARM嵌入式处理器具有高性能、低功耗的特性,已被广泛应用于消费电子产品、无线通信和网络通信等领域。μCLinux是专门为无MMU处理器设计的嵌入式操作系统,支持ARM、等微处理器。目前国内外采用ARM-μCLinux作为嵌入式系统非常普遍。而嵌入式系统的启动引导技术是嵌入式系统开发的一个难点。系统启动引导的成功与否决定了应用程序的运行环境是否能正确构建,即系统启动成功是应用正确运行的前提。
常用的嵌入式系统启动方法是先通过JTAG将嵌入式操作系统内核烧入,再由其带的引导程序Bootloader完成嵌入式系统的启动引导工作。这种方法要借助昂贵的JTAG设备完成操作系统内核的烧写工作,并且不能方便地更新嵌入式系统中的软件平台。本文提出一种基于ARM-μCLinux嵌入式系统的启动引导方案,不但可以通过简易的串口方便地更新嵌入式系统内的软件平台,而且解决了这种架构的嵌入式系统的启动、初始化、操作系统内核的固化和引导等问题。本文简略说明ARM-μCLinux嵌入式系统的硬件平台和软件平台;描述系统引导程序Bootloader的设计,阐述设计时考虑的因素和需解决的技术难点,给出一套可行的引导程序流程;针对μCLinux内核的引导程序,说明μCLinux内核的加载和初始化过程。
1 系统组成
典型的ARM嵌入式系统硬件平台一般包括一个以ARM为内核的微处理器、存储器和必要的外部接口与外设。在本系统中,微处理器采用内嵌的ung公司的处理器,存储器使用2MB的和的,外部接口除了用于下载和通信的串口,还配备了一个以太网接口,以支持的网络功能。
软件平台由以下部分组成:系统引导程序、嵌入式操作系统内核、文件系统。系统引导程序通常也称为Bootloader,该引导程序包括两个方面:引导内核的Bootloader和内核自身的引导程序部分,代码量虽少,但是作用非常大,相当于PC上的,负责将操作系统内核固化到中和系统初始化工作,然后将系统控制权交给操作系统。Bootloader是CPU开机后执行的第一个程序,它的任务就是将内核(压缩或非压缩)装载到内核要求的地址。内核引导程序部分有狭义和广义之分,狭义指内核运行前的一段代码,一般在压缩的内核映像前有一段解压缩程序,负责将内核解压缩到某个地址,从开始解压缩到将控制权交给解压缩好的内核,这一段代码称为内核的引导程序部分。广义定义还要包括内核初始化部分,即直到有进程产生才算引导程序的结束。嵌入式操作系统内核是嵌入式系统加电运行后的管理平台,完成嵌入式应用的任务调度和控制等核心功能。具有内核较精简、可配置、与高层应用紧密关联等特点。嵌入式操作系统具有相对不变性。
是一款没有MMU的处理器 ,因此采用μCLinux作为本系统的操作系统内核。μCLinux是Linux是一个分支,主要是针对无MMU的微处理器设计开发的,大多数内核的二进制代码和源代码都被重写,但继承了Linux 操作系统的主要优点:稳定性、优异的网络能力和多任务管理功能以及优秀的文件系统支持,并对内存管理和进程管理进行了改写,满足了无MMU处理器的开发要求。文件系统是嵌入式系统软件平台占用存储量最大的一部分,也是与用户开发最相关的一部分。它是负责存取和管理文件信息的机构,也可以说是负责文件的建立、撤消、组织、读写、修改、复制及对文件管理所需要的资源实施管理的软件部分。
软件平台固化在Flash中。通常根据软件平台的内容 对Flash的地址空间进行分区,一般分三个区,分别存放Bootloader、μCLinux内核和文件系统。分区的方式一般有两种:一种是根据三个部分预定的存储空量,允许Bootloader、内核和文件系统拥有自己固定的分区和首地址;另一种就是按照这三部分的实际分配区间,一个部分紧跟着另一个部分后存储,没有固定的分区和首地址。通常采用第一种方式,虽然可能会浪费一部分Flash空间,但是方便内核的加载和文件系统的挂载,同时也利于系统的调试和开发。而如果充分利用Flash的存储区间,节约成本,那么可采用第二种方式。
2 系统引导程序的设计
系统引导程序Bootloader是嵌入式系统加电后执行的第一个程序, Bootloader一般是被烧录或者下载到bootrom的0x0地址处,作为上电后执行的第一部分指令,Bootloader需要完成两个任务:
(1). remap,
(2). 把kernel装载到里合适的位置上去。在完成这两个任务后,Bootloader就“功成身退”了。进行功能设计时首先要考虑以下问题:
(1)将μCLinux内核和文件系统固化在Flash中
μCLinux内核和文件系统固化在Flash中的手段很多。主机可以通过JTAG口,将内核和文件系统的映像文件烧写到指定的Flash位置上;也可以通过以太网接口,将映像文件下载到Flash中;另外还可以通过串口烧写到Flash中。前两种方法的下载速度比后一种方法快得多。在本系统中,采用串口烧写Flash。这是因为一方面配置一个串口方便且廉价,而JTAG烧写还要配置昂贵的JTAG仿真器和相关的驱动程序以及协议转换程序,网口下载还要有以太网支持;另一方面μCLinux默认通过串口打印其运行的信息,那么串口不但可以提供烧写Flash的功能,还可作为调试μCLinux内核的通道。在本系统中,Flash在刚开始时,只存储了Bootloader,还没有存储μCLinux内核和文件系统。因此Bootloader在系统加电完成初始化工作后,要初始化一条链接主机和目标机的串口通道,并提供串口下载功能。
(2)系统初始化
因为系统刚加电时,操作系统的内核还没有被加载,系统的初始化工作由Bootloader完成。一般嵌入式设备上电后,程序寄存器首先指向ROM(Flash)的首地址,执行事先已经固化好的Bootloader程序。Bootloader程序一般首先初始化CPU的寄存器,设置处理器的工作模式,关掉中断,设置Flash和RAM让他们能够工作,并把内核从Flash中复制到RAM中,然后调用解压缩函数解压内核,最后把控制权交给解压缩好的内核,并开始内核的初始化。
(3)μCLinux内核加载方式
μCLinux的内核有两种可选的运行方式:一是在Flash上直接运行;二是加载到内存中运行。后者可以减少内存需要。Flash运行方式是把内核的可执行映像文件烧制到Flash上, Bootloader进行系统初始化工作后系统启动时从Flash的某个地址开始逐句执行内核自带的引导程序,由该引导程序完成内核的加载工作。这种方法实际上是很多嵌入式系统采用的方法,也是本系统采用的内核加载方式。内核加载方式是把内核的压缩文件存放在Flash上,系统启动时读取压缩文件在内存里解压,然后开始执行,这种方式相对复杂一些,需要在内存中运行程序,但是其运行速度可能更快(RAM的存取速率要比Flash高),并且可以通过RAM快速引导技术实现这种加载方式,同时这也是标准Linux系统采用的启动方式。其主要是针对NAND型Flash的情况。与NOR型Flash最大的不同点是:NOR型Flash使用内存随机读取技术,与一样,可以直接执行存储在Flash中的程序;而NAND一样,可以直接内存随机读取技术,它是一次读取一整块内存,因此不能直接执行存储在NAND型Flash中的程序,必须把NAND型Flash中的程序先拷贝到SDRAM,再在SDRAM中执行该程序。但是NAND型Flash价格比NOR型Flash廉价,所以很多嵌入式系统还是采用NOR型Flash(几百K字节)+NAND型Flash(几兆字节)的存储模式。其中NOR型Flash存放可执行的且代码量小的Bootloader和一些必要的数据,而NAND型Flash保存存储量较大的内核和文件系统。
在本系统中,由于采用NOR型Flash存储Bootloader、内核和文件系统,所以可以直接访问内核所在地址区间的首地址,执行内核自己的引导程序,而且内核自带的引导程序功能强大,可以方便地内核的加载,向内核传递有关的硬件参数。本系统采用第一种加载方式。
(4)自举模式和内核启动模式的切换
Bootloader一般要实现两种启动模式:自举模式和内核启动模式。自举模式也称为bootstrap模式,该模式的主要作用是目标机通过串口与主机通信,可以接收主机发送过来的映像文件,例如内核、文件系统和应用程序,并将其固化在Flash中,也可以将Flash中的映像文件上传到主机。内核启动模式允许嵌入式系统加电启动后加载μCLinux内核,然后将系统交由μCLinux操作系统管理。在本系统中,采用一个实现两种模式的切换。在系统的Flash中只有Bootloader时,首先将拔上去,提示系统进入自举模式,加电启动后,Bootloader根据的状态,进入自举模式,接收主机发送过来的内核和文件系统的映像文件。接着将开关拔下来,提示系统进入内核启动模式,Bootloader根据此时的开关状态进入内核启动模式,加载内核和文件系统,由操作系统接管。以后也可以根据需要,设置开关的状态,以提示系统进入不同的启动模式。
(5)地址映射表的配置和重映射
地址映射表的配置包括设置Flash地址空间、SDRAM地址空间、外部I/O地址范围和处理器寄存器地址范围。嵌入式设备上电启动后,Flash中的程序获得控制权,Flash中的程序包括bootloader和一个压缩过的内核(另外还含有一个romfs的文件系统)。
Flash中的程序首先配置内存地址,将本身由原来系统默认的地址配置为0x0到0x200000(2MByte),SDRAM配置为0x1000000(yte)到0x2000000(32MByte)。然后把Flash的内容整体拷贝SDRAM中。拷贝完后,将SDRAM地址重新配置为0x0到0x1000000,Flash的地址改为0x1000000到0x1200000。注意,这里Flash和RAM地址是同时修改的,修改地址后,接下来的指令就将从SDRAM中获得,由于SDRAM中的程序和原来Flash中的程序一样,并且地址也一样,所以不会影响指令的执行。这需要在内核引导程序中对Flash和SDRAM的地址空间进行重映射。
3 μCLinux内核的加载和初始化
本启动方案中采用μCLinux自带的引导程序加载内核。该引导程序代码在/arch/armnommu/boot/compressed目 录,其中.s的作用最关键,它完成了加载内核的大部分工作;.c则提供加载内核所需要的子程序,其中解压内核的子程序是.s调用的重要程序,另外内核的加载还必须知道系统必要的硬件信息,该硬件信息在.h中并被.s所引用。当Bootloader将控制权交给内核的引导程序时,第一个执行的程序就是Head.s。下面基于本系统介绍Head.s加载内核的主要过程。Head.s首先配置的系统寄存器;再初始化S3C4510的ROM、RAM以及总线等控制寄存器,将Flash和SDRAM的地址范围分别设置为0x0-0x200000和0x1000000-0x2000000;接着将内核的映像文件从Flash拷贝到SDRAM,并将Flash和SDRAM的地址区间分别重映射为0x1000000-0x1200000和0x0-0x1000000;然后调用.c中的解压内核函数(decompress_kernel),对拷贝到SDRAM的内核映像文件进行解压缩;最后跳转到执行调用内核函数(_kernel),将控制权交给解压后的μCLinux系统。执行_kernel函数实际上是执行//main.c中的start_kernel函数,中包括处理器结构的初始化、中断的初始化、进程相关的初始化以及内存初始化等重要工作。
4 结论
该启动引导方案实现了自举模式和内核启动模式以及两种模式的切换,既可以采用自举模式方便地烧写Flash,更新嵌入式系统中的软件平台,又能够切换到内核启动模式,自动安全地启动系统;其次,本方案采用简易的串口通道主机与目标系统的通信渠道,既可以方便地将操作系统内核、文件系统和应用程序下载到目标系统中,又可以作为调试μCLinux内核和应用程序通道;此外针对的无MMU特性,采用修改后的μCLinux内核引导程序加载操作系统和初始化操作系统环境,解决内核加载的地址重映射问题和操作系统的内存管理问题。
参考文献
[1] 刘安昱,温晓辉,刘志红. 基于的uC的移植. 与嵌入式系统应用,2003(12)
[2王田苗.嵌入式系统设计与实例开发 清华大学出版社,2002
[3]K ,M Watson,M Whitis.Linux Unleashed [M].Sams,1999
[4]John Goerzen. Linux Bilble [M]. of Electronic Industry,1999