行喜梁 刘树东 戴学丰
摘 要:FLASH作为新型非易失性半导体存储器在嵌入式系统的开发中占有重要的地位。为了在嵌入式系统中实现数据的动态操作,介绍μClinux下的FLASH文件系统,特别是日志型文件系统的设计原理及特点;利用Linux提供的MTD接口,通过添加与FLASH对应的map driver和FLASH驱动,修改设备节点,配置内核等步骤,将JFFS2文件系统移植到s3c44b0使用的FLASH芯片上。通过挂载,用户可以像使用普通硬盘分区一样对此目录下面的文件进行操作,从而实现对FLASH的动态操作和管理。结果表明,在JFFS2 文件系统下,保存的文件是可读写的,系统掉电后创建的文件也不会丢失。
关键词:FLASH;JFFS2;内存技术设备;嵌入式系统
中图分类号:TN302文献标识码:A
文章编号:1004-373X(2009)10-051-04
Realization of JFFS2 File System in μClinux
XING Xiliang,LIU Shudong,DAI Xuefeng
(School of Computer and Control Engineering,Qiqihaer University,Qiqihaer,161006,China)
Abstract:FLASH as a new type of non-volatile semiconductor memory plays an important role in embedded systems development.For achieving operating the data dynamically under embedded system,the FLASH file system under μClinux,in particular the design principles and charactertistecs of JFFS2(log-file system)is introduced.Using MTD interface provided by Linux,through adding map driver and FLASH driver,modifying the device nodes,such as configuring core etc,transplanting JFFS2 file system to the FLASH chips of s3c44b0.Through the mount,users can operate the files under this directory as an ordinary hard driver partition,achieving operating dynamicly and managing for FLASH.The results show that files can be read and write after the creation under the JFFS2 file system.The files can′t be lost even if the power is down.
Keywords:FLASH;JFFS2;MTD;embedded system
0 引 言
嵌入式系统开发中,一些重要的工艺参数在控制过程中需要动态地改变和保存,使用硬盘等存储介质又显得不太现实,而FLASH芯片以相对低廉的价格提供了高可靠性和高密度的存储,已成为嵌入式系统重要的存储设备。在很多嵌入式系统中,操作系统及应用程序直接固化在FLASH上,系统启动时,代码可以直接在FLASH上开始运行。但是仅将FLASH作为ROM使用是大材小用,需要充分发挥FLASH可擦写的优势,在系统运行过程中,动态擦写FLASH来保存数据。
然而,μClinux的文件系统可以有多种选择,ROMFS是使用得较多的文件系统。它是一种简单、紧凑的文件系统,占用的空间小,但由于是只读的,使用起来有局限性。若采用EXT2作为文件系统,虽然可以把信息保存在ramdisk盘中,但系统掉电后,ramdisk中的信息将丢失,这对于需要保存运行过程中参数的应用程序是不允许的。建立在FLASH设备上的JFFS文件系统就是为解决这个问题而诞生的。
1 JFFS/MTD/JFFS2介绍
日志闪存文件系统(The Journalling FLASH File System,JFFS)最初由瑞典的Axis Communications开发,Red Hat的David Woodhouse对它进行了改进。通过JFFS文件系统,Linux用户就可以将FLASH作为系统的硬盘来使用,可以像操作硬盘上的文件一样操作FLASH芯片上的文件和数据。系统运行的参数可以实时保存到FLASH芯片中,在系统断电后数据仍然存储在FLASH芯片中。但是在使用过程中,JFFS设计中的局限被不断地暴露出来。2001年年初,Red Hat 决定实现一个新的JFFS2。
JFFS2在闪存上顺序地存储包含数据和原数据的meta-data的节点。JFFS2的日志结构存储方式使得它能对闪存进行out-of-place更新,它提供的垃圾回收机制,只需要对擦写越界的块设置一个“脏”块标志。当可用的块数不足时,垃圾回收机制才开始回收这些节点。目前,市场上的FLASH芯片千差万别,而JFFS2文件系统并不考虑这些差异,它只是要求下面有一个抽象平台屏蔽底层硬件差异,提供统一访问接口。这个抽象平台就是MTD层。
内存技术设备(Memory Technology Device,MTD)是用于访问Memory设备(ROM,FLASH)的μClinux的子系统。它的主要目标是在系统硬件驱动程序的上层或用户模块之间提供通用接口。硬件驱动程序不需要知道像JFFS和FTL那样的用户模块所使用的方法,它们真正需要提供的就是一组对底层闪存系统进行read,write和erase操作的简单例程,以及对MTD原始设备层的统一接口。
MTD支持的FLASH芯片主要有两种:HAND FLASH和NOR FLASH,它们的驱动程序有着很大的差异。NOR和HAND是现在市场上两种主要的非易失闪存技术,其主要区别在于:
(1) NOR的特点是芯片内执行(eXecute In Place,XIP),这样应用程序可以直接在FLASH闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,在1~4 MB的小容量时具有很高的成本效益,但是较低的写入和擦除速度大大影响了它的性能。而HAND结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用HAND的困难在于FLASH的管理和需要特殊的系统接口。
(2) 在对FLASH芯片中存储器单元块进行编程之前必须先执行擦除。HAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先将目标块内所有的位都写为0。
(3) NOR FLASH带有SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内部的每一个字节。HAND器件使用复杂的I/O口来串行地存取数据,各个产品或厂商的方法可能各不相同。8个引脚用来传送控制、地址和数据信息。
引入MTD和JFFS2概念后,FLASH设备驱动在Linux内核中的组织层次如图1所示。
从图1中可以看出,MTD设备分为四层(从设备节点直到底层硬件驱动),这四层从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。
设备节点:通过mknod在根文件系统/dev子目录下建立MTD字符设备节点(主设备号为90)和MTD块设备节点(主设备号为31)。这些节点为应用程序访问FLASH设备提供了通道,通过访问此设备节点即可访问MTD字符设备和块设备。
MTD设备层提供了两种不同访问MTD原始设备的方式,即字符设备、块设备。
MTD原始设备:为MTD的块设备(主设备号31)和字符设备(设备号90)提供一个统一的底层抽象。
FLASH硬件驱动层:负责具体FLASH芯片的读写,向内核注册FLASH设备上的分区等任务。
由于目前μClinux内核支持的ramdisk只能运行ROMFS,EXT2FS两种文件系统,所以JFFS2格式的FLASH分区必须通过mount命令挂载到根文件系统上才能使用。
2 在FLASH上建立JFFS2过程
JFFS2文件系统在μClinux下有两种使用方式:一种是作为μClinux的根文件系统,另一种是作为一般文件系统,在系统启动时或启动以后挂载到系统上。针对JFFS2文件系统所保存的数据比较少,这里选择后者。具体的实现步骤有以下几个:添加与FLASH对应的map driver和FLASH驱动;修改设备节点;配置内核。
进行试验的s3c44b0使用的FLASH是intel 28f320b,大小为4 MB,类型为NOR FLASH,工作在16 b双字节模式。使用的μClinux包为μClinux-dist-20040408.tar.gz。
设计NOR FLASH驱动程序时,只要让它能够被其上层MTD原始设备层正确地识别和操作,就能保证其正常工作。现实NOR FLASH驱动核心是定义map_info 结构体,它指定了NOR FLASH的基址、位宽、大小等信息及FLASH的读写函数,见图2。
其中:name用来在内核中惟一标识这块芯片的字符串;width用来访问FLASH芯片的总线宽度;size是FLASH芯片的容量,在该芯片中用字进行读取。其主要的函数原型为:
void(*read) (struct map_info *,unsignde long);
void(*write) (struct map_info *,const map_word,unsignde long);
void(*copy_from) (struct map_info *,void *,unsignde long,ssize_t);
void(*copy_to) (struct map_info *,unsignde long const void *,ssize_t);
2.1 添加FLASH上的map文件和FLASH的驱动
在μClinux-dist/linux-2.4.x/drivers/mtd/maps下添加自己的map文件。map文件可以根据具体的FLASH和挂载方式选择合适的文件加以修改,本系统是选择m5272c3.c修改的,并命名为s3c44b0.c。修改的关键点有:
(1) 定义FLASH的基地址、容量和宽度
#define WINDOW_ADDR 0x00000000
#define WINDOW_SIZE 0x00400000
#define BUSWIDTH 2
(2) 根据系统要求建立FLASH设备中的分区
static struct mtd_partition s3c44b0_partitions[ ] = {
{
name: "bootloader (64K)",
size: 0x00010000,
offset: 0x00000000
},
{
name: "μClinux kernel (960K)",
size: 0x00100000,
offset: 0x00010000
},
{
name: "ramdisk (1024K)"
size: 0x00100000,
offset: 0x00200000
},
{
name: "jffs2 (1024K)"
size: 0x00100000,
offset: 0x00300000
}
};
(3) FLASH芯片的内存映射
s3c44b0x_map.map_priv_1=(unsigned long)
ioremap(WINDOW_ ADDR,WINDOW_SIZE);
// if( !s3c44b0x_m ap.m ap_priv_1){
// printk(”Failed to ioremap\n");
// return -EIO;
// }
这里的ioremap()主要是将I/O端口映射到虚拟内存区域。对于有MMU的CPU,它会将对应的地址映射到高端区域,不过使用的是s3c44bOX处理器,这是一款没有MMU的处理器,其重映射就是会将端口地址按原地址返回;又由于这里的FLASH的起始地址是0x0,其映射后的起始地址也是0x0,所以ioremap()函数的返回值是0。在该系统中将接下来的4行注释掉。
(4) 为了把map文件集成到μClinux配置中,需要修改
μClinux-dist/linux-2.4.x/drivers/mtd/maps/config.in file:
if [ "MYMCONFIG_S3C44B0" ];then
dep_tristate 'CFI FLASH device mapped on samsung S3C44B0' CONFIG_MTD_S3C44B0 MYMCONFIG_MTD_CFI
fi
Clinux-dist/linux-2.4.x/drivers/mtd/maps/Makefile file:
Obj-MYM(CONFIG_MTD_S3C44B0) +=s3c44b0c.o
2.2 配置内核
选中和JFFS2文件系统相关的内核选项,在Memory Technology Devices(MTD)下选中:
CONFIG_MTD=Y
CONFIG_MTD_DEBUG=Y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=Y
CONFIG_MTD_CHAR=Y
CONFIG_MTD_BLOCK=Y
CONFIG_MTD_CFI=Y
CONFIG_MTD_JEDECPROBE=Y
CONFIG_MTD_GEN_PROBE=Y
CONFIG_MTD_CFI_AMDSTD=Y
CONFIG_MTD_S3C44B0=Y
2.3 修改μClinux内核并添加MTD设备
由于ROM设备和MTDBLock设备的主设备号(major)都是31,所以必须修改其中之一,在这里修改ROM的major,在μClinux-dist/linux-2.4.x/include/linux/major.h和μClinux-dist/linux-2.4.x/drives/block/blkmem.c中,把#define BLKMEM_MAJOR 31改为#define BlkMEM_MAJOR 30,在μClinux-dist/vendors/samsun/44B0/Makefile中rom的主设备号改为30并添加下面的行:
DEVICES=
tty,c,5,0 console,c5,1 cua0,c,64 cual,c,5,6,
mtd0,c,90,1 mtd1,c,90,3 mtd2,c,90,5 mtd3,c,90,0
mtdblock0,b,31,1 mtdblock1,b,31,3
mtdblock2,b,31,5 mtdblock3,b,31,0
编译内核后,可以看到MTD设备添加成功。
2.4 重新配置内核
选中JFFS2文件系统和相关的辅助工具,编译内核。在File systems下选中:
CONFIG_JFFS2_FS=Y
CONFIG_JFFS2_DEBUG=2
在μClinux application Configuration下选中:
CONFIG_USER_MTDUTILS=Y,
在BusyBox下,选中cat,cp,dd,mount,umount,mkdir工具。配置内核后,重新编译内核,编译好的内核已经实现了JFFS2文件系统。可以使用MTD工具mkfs.jffs2创建JFFS2文件系统的镜像。
如果编译内核前,在rc文件中加上mount-t jffs2 /dev/mtd-block3/mnt 系统启动后不用再执行挂载命令,则JFFS2 文件系统就被挂载到/mnt/ 目录下。在此目录下保存的文件可读写,系
统掉电后创建的文件也不会丢失。
3 结 语
JFFS2以其优异的性能在嵌入式系统中被越来越广泛的使用。这里只介绍了JFFS2以普通文件挂载的方式及其在μClinux中的应用,解决了如何动态保存少量数据的问题。JFFS2仍存在一些不足之处,由于压缩和解压算法的运算,数据存取的速度慢。
参考文献
[1]华清远见嵌入式培训中心,宋宝华.Linux设备驱动开发详解[M].北京:人民邮电出版社,2008.
[2]Kadionik:How to Use Mtd/Jees2 Under μClinux[EB/OL].http://uuu.enseirb.fr/~kadionik/embedded/μClinux/mtd/howto_mtd.html,2004.
[3]周斌,林喜荣,黄析伟.嵌入式Linux系统下NOR FLASH的配置和使用[J].单片机与嵌入式系统应用,2004(2):82-84.
[4]王学龙.嵌入式Linux系统设计与应用[M].北京:清华大学出版社,2001.
[5]黄布毅,郑安平,陈晓雷,等.μClinux下JFFS2文件系统的实现[J].单片机与嵌入式系统应用,2004(5):69-70,76.
[6]胡晨峰.JFFS2文件系统在μClinux中的应用[J].电子产品世界,2003(7):48-51.
[7]郑良辰.日志文件系统在嵌入式存储设备上的设计和实现[Z].北京:中国科学院软件研究所,2001.
[8]赵复生.JFFS2文件系统及其新特性介绍[EB/OL].http://www.128.ibm.com/developerworks/cn/linux/jffs2/,2005.
[9]张翔,刘鹏,戴国骏.嵌入式Linux闪存文件系统JFFS2的研究[J].杭州电子工业学院学报,2003,23(3):62-65.
[10]李桂良,刘发贵.JFFS2文件系统的关键技术及其在嵌入式系统中的应用[J].计算机应用,2003,23(7):135-137.
[11]陈智育.嵌入式系统中的FLASH文件系统.单片机与嵌入式系统应用,2002(2):5-8.
[12]代新冠,张超,田永鹏.基于S3C2440的嵌入式多媒体控制器设计.现代电子技术,2006,29(8):19-21.