摘要:本文针对 ARM7 芯片 S3C4510 开发板,对 uCLinux 在嵌入式设备中的系统开发做了介绍,如何组建软件开发平台,并对引导装载程序,设备驱动程序作了例证和分析。
关键词:嵌入式 uCLinux ARM BootLoader 驱动程序
1 引言
信息家电和手持设备大大加速了嵌入式系统的发展,而 ARM 体系 32 位高性能、低功耗处理器和嵌入式操作系统 Linux 无疑成为佼佼者。因为 Linux源代码开放、免费,任何将其定制于 PDA、掌上机或者便携式设备感兴趣的人都可以从因特网免费下载其内核和应用程序,并开始移植或开发,所以 Linux 在嵌入式开发领域得到稳步发展。uCLinux 即是目前嵌入式 linux 中最流行的一种,它是针对微控制领域而设计的Linux 系统,其最大特征就是没有 MMU(内存管理单元模块),适合嵌入式系统小型化应用。
uCLinux 支持多任务,支持多种文件系统,提供了对网络的强大支持,具有完整的 TCP/IP 协议栈,以及标准丰富的 API。由于它的很多核心代码都为没有被 MMU 的处理器重新编写过,对标准 Linux庞大的应用程序库和驱动程序库作了删改,所以它的内核要比常规的 Linux 内核小很多;uCLinux 包含Linux 常用的 API 和小于 512k 的内核及相关的工具,总代码只有 900k 左右,但同时保留了常规 Linux 操作系统绝大多数的优点。
2 基于ARM 的硬件平台
嵌入式领域 32 位处理器以 ARM 公司的 ARM 核最为流行,本文以 Samsung公司的 ARM7TDMI 芯片S3C4510 为处理器开发板为硬件平台,开发板上与 S3C4510 相关的部分主要集成了如下器件:
(2M+512k)B 的 Flash,其中 AT29C010A为 512B 作为 BootLoader,一片 SST49VF160 为 1M×16bitFlash;
16MB 的 DRAM,由两片 4M×16bits 的HY57V641620 提供 ;
16MB 的 SRAM,由 M-systems 的新一代闪存盘 DOC2000 构成;
Ethernet 接口;
ARM JTAG 接口。
开发板上与 S3C4510相关部分功能框图如图 1 所示。
3 uCLinux 内核移植
嵌入式 Linux 开发大致涉及三个层次:引导装载程序、Linux 内核和驱动及应用程序。我们将讨论涉及这三层的一些基本概念;深入了解引导装载程序、内核和文件系统是如何交互的。
引导程序 BootLoader 的主要作用包括初始化处理器;初始化必备的设备;下载系统映象;初始化操作系统系统并准备执行。
引导装载程序有两种方法:专用软件和微小的引导代码。专用软件可以直接与远程系统上的闪存设备进行交互并将引导装载程序安装在闪存的给定位置中。而某些种类的嵌入式设备具有微小的引导代码:根据几个字节的指令,它将初始化一些 DRAM 设置并启用目标上的一个串行(或者 USB,或者以太网)端口与主机程序通信;然后,主机程序或装入程序可以使用这个连接将引导装载程序传送到目标上,并将
它写入闪存。
嵌入式设备上一些流行的并可免费使用的 Linux 引导装载程序有 Blob、Redboot 和 Bootldr。所有这些引导装载程序都用于基于 ARM 设备上的 Linux,并需要 Jflash-linux 工具用于安装。一旦将引导装载程序安装到目标的闪存中,它就会执行我们上面提到的所有初始化工作。然后,它准备接收来自主机的内核和文件系统。一旦装入了内核,引导装载程序就将控制转给内核。
Linux内核移植首先需要配置内核,可以用make menuconfig进行,根据板卡选择必要的选项。主要包括系统类型选定(ARM system type),配置SDRAM/Flash地址;对块设备、字符设备进行选择和配置;配置文件系统;是否配置图形用户界面(GUI)。修改内核,我们选用www.lomx.net上的uClinux-2.4.26-uc0.diff,已经为S3C4510 移植好的内核,需要修改的地方很少。
编译内核,首先要在宿主机(安装有Linux)上建立交叉编译环境,下载arm-elf-tools安装在Linux 宿主机上的/usr/local/bin 目录下。现在的BLOB 和将来的uClinux 都要在这个环境下编译。
开始编译 uClinux
编译内核:执行命令:
make menuconfig 在出现的对话框选 Samsung/4510B 和 uC-libc,然后退出。如果选择 uC-libc 编译出错,可以改选 uClibc!
make dep
make lib_only
make user_only
make romfs
make image 产生 romfs.o,这一步将会出现一些错误报告,可忽略继续下面的命令
make
如果 make 无错误,在 images 的目录下你会看到有 image.ram 和 image.rom 两个二进制的内核文件。即 image.ram和 image.rom。 image.ram可以通过 Bootloader 下载到 SDRAM 中运行。image.rom可以写入到 Flash SST39VF160 中直接运行。
down image.ram看看能不能运行
最后一步,uClinux 调试完毕,通过 jflashp 将其写入到 Flash 中:开发板断电,把 JTAG仿真器接到计算机的并口和板子的 14Pin JTAG 插座上;接通 5V电源;执行 FlashP w -f image.rom,大约 30 分钟以后烧写完毕。撤掉 JTAG仿真器以后再上电就应该运行 uClinux 了。如果想把 BootLoader写回 Flash,执行 FlashP w -f bios.img 即可。
4 uCLinux 驱动程序开发
嵌入式系统通常有许多设备用于与用户交互,象触摸屏、小键盘、滚动轮、传感器、RS232 接口、LCD 等等。除了这些设备外,还有许多其它专用设备,包括闪存、USB、GSM、GPS 等。内核通过所有这些设备各自的设备驱动程序来控制它们,包括 GUI 用户应用程序也通过访问这些驱动程序来访问设备。uClinux 的驱动程序库不可能包括实际项目系统中所有外围硬件的驱动,所以在应用开发中,编写驱动程序
是一个重要步骤,驱动程序设计的好坏直接影响系统运行的稳定性和运行效率。
在 uClinux 内核编写驱动程序并不像其他操作系统那么复杂,实际上,所要做的只是为相应的设备编写几个基本函数并向 VFS(virtual file system) 注册即可。当上层应用要使用该设备时,VFS 就会调用相应的设备函数。设备驱动程序通常可归为以下 3 类:
a) 块设备(block) ,以块为单位,允许随机访问,多用缓存技术;
b) 字符设备(char) ,以字节为单位,只能按顺序访问,不用缓存;
c)网络接口(net) 。
在本系统中,DOC 作为块设备可被模拟为 IDE 设备进行识别,系统用主设备号(MAJOR)和次设备号(MINOR)来唯一标识一般设备;相同主设备号表示同一类设备,次设备号表示同类设备的个数。所有设备在适当的目录(通常是/dev 目录)下必须有相应的文件,这样字符设备和块设备都可以通过文件操作的系统调用完成。不同的是,块设备操作经常和缓冲区联系在一起。
字符设备的驱动程序通过在 device_struct 数据结构的 chrdevs 向量中增加一项的方法来向内核注册自己。然后对这个设备的所有调用都用这个设备号来实现;
块设备和字符设备都需要定义功能函数:对于每一个驱动函数来说,都有一些和此设备密切相关的功能函数,就最常用的字符设备来说,都存在着诸如 open()、read()、write()、ioctrol( ) 这一类的操作。当系统调用这些操作时,将自动的使用 file-operations 结构中对应的函数来实现具体的操作;块设备由于使用高速缓存,其驱动程序不需要保护自己的 read()、write()和 fsync()函数,但必须使用自己的 open()、release()和ioctl()函数,函数原型为:
static int my_open(struct inode *inode,struct file *file);
static int my_release(struct inode *inode,struct file *file);
static int my_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long age);
块设备驱动程序的请求处理函数一般通过中断实现。驱动程序被调用时 CPU 由内核程序控制,故不可抢占,驱动程序必须调用 sleep_on()函数释放对 CPU的占用,在中断服务子程序将数据复制到内核内核后,再发出 wake_up()调用。
字符设备如 LCD、USB 应用广泛,下面以此为例详细说明添加设备驱动的过程。设备名称为 scre,设备号为 254。块设备与网络设备可以比照处理。
在目录/linux_2.4/drives/char编写源程序 scre.c,编写字符设备的处理函数。
1.设备驱动原文件必须包括这样的一个函数:
void scre_init(void){register(254, 'scre', &scre_fops)} 这个函数完成注册.在 linux-2.4.x/driver/mem.c 将会调用它。
2.修改 linux-2.4.x/driver/char/Makefile 在适当位置添加一行:obj_$(CONFIG_SCRE) += scre.o
3.修改 linux-2.4.x/driver/char/Config.in, 添加一行:
bool 'scre device' CONFIG_SCRE,便于在 make menuconfig 时选择
4.修改 linux-2.4.x/driver/char/mem.c ,在适当位置(你去找就会发现,在文件头部)添加:
#ifdef CONFIG_SCRE
extern void scre_init(void);
#endif
在 chr_dev_init()函数添加:
#ifdef CONFIG_SCRE
scre_init();
#endif
5.修改 vendor/Samsung/4510b/Makefile ,建立设备节点;在 12---35 行间,DEVICE 部分添加如下内容 :scre,c,254,0 。
6.make menuconfig 选中 scre device,编译,下载;启动后你会看到 /proc/devices 中字符设备多了一项 scre 254 。
uClinux 的 Web 技术,主要有三个 Web 服务器:httpd,thttpd 和 boa。Httpd 简单,但只能 Web 浏览,不支持认证、CGI,thttpd 和boa Web服务器功能较全;而 boa Web 代码简单、速度快,适合嵌入式应用。Boa 作为一个简单的 http 服务器,与传统服务器的主要区别是它是单进程的。boa 在uClinux 下的实现需要对 boa.conf和 mime.types 作一些配置和修改,并且需在命令行指定配置文件所在目录。配置完成后需要重新编译内核,并选中 boa选项,将编译好的内核下载到开发板,启动 uClinux,完成 IP设置,启动 boa Web 后便可通过 IE 访问网页了。
5 结语
uClinux 在嵌入式领域凭借其稳定、良好的移植性,优秀的网络功能,灵活完备的文件系统以及众多的技术支持等优点得到广泛应用,并将有更广阔的应用前景。本文针对 uClinux 的开发应用步骤作了大致的阐述,对 ARM 应用平台上的系统移植和应用开发作了分析,具有一定的指导意义。
参考文献
[1].刘安昱 温晓辉 刘志红,基于 S3C44B0X的uClinux 的移植,《单片机与嵌入式系统应用》[J]2003.12.
[2].徐雪松等,基于嵌入式 Linux 的DiskOnChip设备的驱动开发实现,《电子设计应用》[J]2003.12
[3].Linux on module project-Lom ARM7 ,www.lomx.net.
[4].朱珂等译,《Linux 编程白皮书》[M],机械工业出版社,2000.
[5].赵炯,《Linux 内核完全注释(内核版本 0.11)》[M],2003