1 引言
嵌入式系统(Embedded System)是当今最热门的领域之一,它可以定义为:以应用为中心、以计算机技术为基础、软硬件可裁剪、适用于应用系统,对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。构建嵌入式系统需要从两个方面进行选型,一是硬件平台的选择,二是嵌入式操作系统的选择。
硬件平台的选择包括处理器以及相关芯片的选型。嵌入式处理器种类繁多,有ARM、MIPS、 PPC等多种构架。这里选择三星公司的ARM9芯片S3C2440。ARM处理器的文档丰富,各类嵌入式软件大多支持ARM处理器,开发起来相对容易上手。在嵌入式操作系统方面,目前比较流行的几个嵌入式操作系统是Linux、Windows CE、VxWorks、Palm OS等控制工程网版权所有,这里选择嵌入式Linux,其优点在于它是遵循GPL (General Public License)协议的开放源码操作系统,完全免费;其内核中支持的硬件种类繁多,几乎在网上可以找到所有的硬件驱动程序,有着大量的应用程序可用和庞大的开发人员群体。操作系统的选型极其重要,它会影响到工程后期的发布以及软件的维护。
2 软硬件环境构建
本设计采用主机与目标板结合的交叉开发模式, 如图1所示。
主机自然指PC机,目标板指S3C2440开发板。开发板采用S3C2440A作为CPU;两片总共64M bytes 的 SDRAM 芯片作为内存;具有64MB NAND Flash和2MB NOR Flash两种Flash芯片;另外还有需要串口、并口等。
嵌入式Linux开发可分为下面3个步骤:
(1)在主机上编译Bootloader,然后通过JTAG 烧入单板。此方法速度较慢,适用于烧写空白单板;
(2)在主机上编译嵌入式L i nu x内核,通过Bootloader烧入单板或者直接启动;
(3)在主机上编译各类应用程序,单板启动内核后通过NFS运行它们,经过验证后再烧入单板。本设计基于Ubuntu 8.10进行开发,需要注意的是,编译器版本与最后系统的搭建成功与否有着直接的关系,这里所用的是arm-linux-gcc3.4.5版本,用它编译U-Boot1.1.6,内核linux-2.6.29.3。
3 嵌入式Linux的裁剪与移植
3.1 Linux移植准备
使某一个平台的代码运行在其他平台上的过程叫移植。在进行内核裁剪时,需要结合自己的硬件电路,对内核代码进行修改。本系统选用Linux的稳定版本Linux-2.6.29.3内核作为移植对象。下面简要介绍 Linux的内核结构。
/a rch,体系结构相关的代码,对于每个架构的CPU,a rch目录下有一个对应的子目录,比如a rch/ arm/。
/drivers,所有的设备驱动程序,里面每一个子目录对应一类驱动程序,比如drivers/char/为字符设备驱动程序,drivers/mtd/为NOR Flash、NAND Flash 等存储设备的驱动程序。
/fs,Linux支持的文件系统的代码,每个子目录对应一种文件系统,比如fs/jffs2/、fs/ext2/、fs/ext3/。
/init,内核的初始化代码(不是系统的引导代码),其中的main.c文件中的start_kernel函数是内核引导后 运行的第一个函数。
/ include,内核头文件,有基本头文件(存放在include/linux/目录下),各种驱动或功能部件的头文件等。
/ipc,进程间通信的代码。
/kernel,内核管理的核心代码,与处理器相关的代码位于arch/*/kernel/目录下。
/lib,内核用到的一些库函数代码,比如string.c;与处理器相关的库函数代码位于arch/*/lib/目录下。
/mm,内存管理代码,与处理器相关的内存管理代码位于arch/*/mm/目录下。
/net,网络支持代码,每个子目录对应于网络的一个方面。
在移植Linux之前,先了解它的启动过程。Linux 的启动过程可以分为两部分:架构/单板相关的引导过程、后续的通用启动过程。ARM架构处理器上是Linux内核vmlinux的启动。之所以强调是vmlinux,是因为其他格式的内核在进行与vmlinux相同的流程之前会有一些独特的操作。比如对于压缩格式的内核 zImage,它首先进行自解压得到vmlinux,然后执行vmlinux开始“正常的”启动流程。
3.2 Linux内核移植
首先配置、编译内核,确保内核可以正确编译。先修改顶层Makefile,
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
改为
RCH ?= arm
CROSS_COMPILE ?= arm-linux-
使用交叉编译器,然后执行下面的命令“make s3c2410_deconf ig”配置内核,最后,执行“make uImage”,可生成U-Boot格式的内核映像文件。这时生成的镜像文件还是不能在开发板上用的,因为内核还没有支持S3C2440CONTROL ENGINEERING China版权所有,需要做一些修改来使其支持S3C2440开发板。
在arch/arm/mach-s3c2440/mach-smdk2440.c 中,进行如下修改:
static void __init smdk2440_map_io(void)
{
s3c24x x _ i n i t _ io (smd k 24 4 0 _ io d e s c ,
ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(12000000);
// 修改开发板晶振的频率,为12MHz
s3c24xx_init_uar ts(smdk2440_uar tcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
晶振的频率不匹配是上面编译出的uImage不能正常使用的原因,将其改成开发板晶振频率12MHz。
内核中,对于每种支持的单板(“机器类型ID”), 都会使用宏MACHINE_START、MACHINE_END 来定义一个machine_desc结构。它定义了单板相关的 一些属性及函数,比如机器类型ID、起始I /O物理地 址、Bootloader传入的参数的地址、中断初始化函数、 I/O映射函数等。
Bootloader调用内核时,会在r1寄存器中给出单板的标记——机器类型ID。__lookup_machine_typ函数将这个值与machine_desc结构中的nr成员(机器类 型)比较,如果两者相等则表示找到匹配的machine_ desc结构,返回它的地址(存在r5中),否则返回0。
对于本系统,Bootloader传入的机器类型ID为 MACH_TYPE_S3C2440在arch/arm/tools/machtypes 中,S3C2440的机器码修改成和Bootloader的一 样,因为Bootloader中设置的是782,所以这里也设置 成782。再次执行“make uImage”,生成的uImage就 可以使用了,这时还需要修改mtd分区、增加对yaffs文 件系统的支持。
3.3 设置MTD分区
MTD(Memory Technology Device内存技术设 备),是Linux中对ROM、NOR Flash、NAND Flash 等存储设备抽象出来的一个设备层,MTD相当于在硬件和上层之间提供了一个抽象的接口,可以把它理解 为Flash的设备驱动程序,它主要向上提供两个接口: MTD字符设备和MTD块设备。通过这两个接口,就可 以像读写普通文件一样对Flash设备进行读写操作,屏 蔽了底层硬件的操作、各类存储设备的差别。经过简 单的配置后,MTD在系统启动以后可以自动识别支持 CFI或JEDEC接口的Flash芯片,并自动采用适当的命 令参数对Flash进行读写或擦除。得益于MTD设备的 作用,划分NAND Flash的分区很简单。
对于本文中S3C24 40开发板,需要根据a rch / arm/plat-s3c24xx/commom-smdk.c文件中的smdk_ default_nand_part结构来告诉内核本系统Flash存储 器中存放的文件类型和大小。
将NAND Flash划分3个分区,前256KB用来存放 U-Bootwww.cechina.cn,接下来的2MB用来存放内核,剩下的用来存 放YAFFS 文件系统。如下:
static struct mtd_partition smdk_default_nand _part[] = {
[0]={
.name = "U-Boot",
.size = SZ_256K,
.offset = 0,
},
[1] ={
.name = "kernel",
.size = SZ_2M,
.offset = MTDPART_OFS_APPEND,
},
[2] = {
.name = "yaffs",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULLwww.cechina.cn,
}
};
对以上的smdk_default_nand_par t结构体,用 表1可解释本系统的NAND Flash存储器(地址空间 0x0~0x4000000)分区如下:
3.4 内核的裁剪
上面移植的内核已经可以应用到ARM板上,但是 因为嵌入式系统的存储空间通常很有限,因此需要对 Linux内核进行适当的裁剪。裁剪的第一步,就是以前 提到的,修改顶层的Makef ile文件www.cechina.cn,把交叉编译器改 为arm-linux-gcc,然后再执行“make menuconfig”, 会看到内核的配置的菜单。通过这个配置界面,首 先选择最重要的CPU类型,S3C2440,如图2。可以 选择芯片类型、所需要支持的文件系统以及驱动程 序,去掉不需要的选项。所有配置工具都是通过读取 arch/$(ARCH)/Kconfig文件来生成配置界面,这个 文件是所有配置文件的总入口,它会包含其它目录的 Kconfig文件。
Linux内核配置选项多达上千个,要了解每个配置选项的作用,一个个地进行选择很耗费时间。一般在某个默认配置文件的基础上进行修改,使用arch/ arm/configs/s3c2410_defconf ig文件来配置内核,它生成.conf ig配置文件,这样就可以直接使用“make menuconf ig”来选择芯片类型、设备驱动和文件系统 等前述的单板相关的软硬件设置,配置裁剪内核了。
4 结论
以上基于ARM-Linux和S3C2440的嵌入式内核设计,讨论了在嵌入式应用上如何对硬软件进行选型,并且给出结合Linux内核最新的稳定版本的移植过程。重点讨论了移植和裁剪中的关键函数和驱动程序。目前基于S3C2440的Bootloader、内核和文件系统已经成功启动操作系统,为以后的相关驱动程序及应 用程序的开发提供了有力的平台服务。随着IT业的不 断发展,嵌入式设备将是下一代的主流产品,而本身有着优势的Linux系统也将具有广阔的应用前景。