摘 要:对以S3C44B0X微处理器为核心的嵌入式系统的特点进行了详细讨论,分析了在不支持Remap的系统中实现JFFS2的必要性和可能性。通过在MTD中加关/开中断的方法,实现了在不支持Remap的系统中建立JFFS2文件系统。
关键词:S3C44B0X JFFS2 Remap 文件系统
JFFS2文件系统是针对Flash存储设备而专门设计的一种日志文件系统,已在嵌入式系统中得到广泛应用。但是它的实现通常都依赖于Remap(地址可重映射)的嵌入式处理器。本文在不支持地址重映射的嵌入式系统中实现了JFFS2,与传统的实现相比,它有着其自身的特点。
1 JFFS2文件系统简介
ROMFS是?滋Clinux默认的根文件系统,它相对于一般的EXT2文件系统具有节约空间等优点,但它却是一种只读文件系统,不支持动态擦写和保存。尽管对于需要动态保存的数据可以采用虚拟ram盘的方法来保存,可是一旦系统掉电,ram盘的内容就会全部丢失。
为了克服上述问题,人们设计开发了JFFS2文件系统。JFFS文件系统是一种基于Flash的日志文件系统。它在设计时充分考虑了Flash的读写特性和嵌入式系统用电池供电的特点,在读取文件时,若遇系统突然掉电,确保其文件的可靠性不受影响。后来,JFFS文件系统又进行了一系列改进,形成了JFFS2文件系统。JFFS2主要改善了存取策略以提高Flash的抗疲劳性,同时也优化了碎片整理性能,增加了数据压缩功能。JFFS2的不足是:当文件系统已满或接近满时,由于垃圾收集方面的原因,会引起JFFS2运行速度显著降低。
JFFS是建立在MTD(Memory Technology Device)基础之上的文件系统,MTD在硬件和上层之间提供一个抽象接口。MTD可以理解为Flash的驱动程序,它主要向上提供两个接口,一个是MTD字符设备,另一个是MTD块设备。通过这两个接口,可以像读写普通文件一样对Flash设备进行读写操作。经过简单的配置,MTD在系统启动后可以自动识别支持CFI或JEDEC接口的Flash芯片,并自动采用适当的命令参数对Flash进行读写或擦除。
MTD支持NOR型和NAND型的Flash。NOR型Flash的主要特点是芯片内执行(XIP,eXecute In Place),应用程序可以直接在Flash内运行;而NAND型Flash具有存储密度高和写入/擦除速度快的特点。
2 硬件系统
系统采用Samsung的ARM7TDMI芯片S3C44B0X作为微处理器。S3C44B0X上的存储系统地址空间分为8个存储体,每个存储体可达32MB,共计256MB。Bank0~Bank5可支持ROM、SRAM,Bank6和Bank7可支持ROM、SRAM和FP/EDO/SDRAM等。Flash芯片采用的是SST公司的NOR型芯片SST39VF160(1×16MB),将它的片选连接到S3C44B0X的nGCS0引脚,映射到Bank0上,地址范围为0x00000000~0x001fffff。SDRAM选用Samsung的16位芯片K4S641632F,将它与S3C44B0X的GCS6引脚相接,映射到Bank6上,地址范围为0x0c000000~0x0c7fffff[6]。
S3C44B0X与其他处理器相比具有一个很重要的特点,即不支持Remap。图1是复位后的S3C44B0X的存储器映射图。一旦Flash和SDRAM的片选与S3C44B0X的nGCSx引脚连接之后,它们在S3C44B0X地址空间中的映射位置就固定不变了。而支持地址重映射的处理器则不同。下面以Samsung的另一款专门针对网络应用的ARM7TDMI处理器S3C4510B为例来介绍。
S3C4510B内部有几个特殊寄存器,用于实现各存储介质在地址空间中的重映射。
(1)SYSCFG:该寄存器决定系统管理器中特殊寄存器的起始地址,以及片内SRAM的使用方式和起始地址。
(2)ROMCON0~ROMCON5:分别对应S3C4510B支持的6个ROM/SRAM/FLASH组。可设置每组的起始物理地址和结束物理地址。
(3)DRAMCON0~DRAMCON3:分别对应S3C4510B所支持的4个DRAM组。可设置每组的起始物理地址和结束物理地址。
可以通过改变ROMCONx和DRAMCONx寄存器中基指针和尾指针的相应位来方便地实现S3C4510B系统中地址空间的重映射。图2是S3C4510B在实际应用中典型的Remap实现。
明确了地址可重映射与不可重映射的关系之后,下面将详细讨论如何在一个不支持Remap的系统中实现JFFS2文件系统。
3 JFFS2文件系统的实现
3.1 添加Flash的Map文件及芯片参数
在μClinux-dist/linux-2.4.x/drivers/mtd/maps下添加本系统MPU的Map文件s3c44b0x.c。该文件包含了系统中Flash的相关信息,如Flash的起始物理地址、大小、数据总线的宽度、分区、读写函数、初始化和注销程序等。具体配置如下:
(1)定义SST39VF160在系统中的起始地址、大小、总线宽度:
#define WINDOW_ADDR 0x00000000/*从0地址开始*/
#define WINDOW_SIZE 0x00200000/*2MB*/
#define BUSWIDTH 2/*16位*/
(2)定义SST39VF160中字节、半字及字的读写操作函数。
(3)定义SST39VF160中的具体分区。在本系统中ROMFS文件系统是与内核编译在一起的,因此定义了三个分区,分别用于放置引导内核启动的BootLoader程序、经过压缩的系统内核以及需要保存的动态数据。其中第三个区是要实现JFFS2文件系统的分区。
(4)定义用于初始化SST39VF160的int_init init_s3c-44b0x(void)函数。因为S3C44B0X不支持Remap,所以注释掉了与ioremap有关的语句,否则在系统启动时将返回一个错误“Failed to ioremap”。另外SST39VF160是遵循JEDEC标准的Flash芯片,在探测时直接采用“jedec_probe”。
int _init init_s3c44b0x(void) {
……
/*s3c44b0x_map.map_priv_1 =(unsigned long)ioremap
(WINDOW_ADDR,WINDOW_SIZE);
if(!s3c44b0x_map.map_priv_1) {
printk(″Failed to ioremap\n″);
return -EIO;
}*/
mymtd=do_map_probe(″jedec_probe″,&s3c44b0x_map);
……
/*iounmap((void *)s3c44b0x_map.map_priv_1);*/
……
}
(5)定义用于注销SST39VF160的static void _exit cle-anup_s3c44b0x(void)函数。同理,注释掉了与ioremap有关的语句。
static void _exit cleanup_s3c44b0x(void)
{ ……
/*if (s3c44b0x_map.map_priv_1) {
iounmap((void *)s3c44b0x_map.map_priv_1);
s3c44b0x_map.map_priv_1=0;
}*/
}
(6)由于在linux-2.4.x版本中没有关于SST39VF160的定义,所以需要在μClinux-dist/linux-2.4.x/drivers/mtd/chips/jedec_probe.c中添加SST39VF160的相关信息。
3.2 修改MTD配置文件
本节将论述地址可重映射与不支持地址重映射的嵌入式系统在实现JFFS2文件系统上的最大差别。当ARM处理器发生异常时,程序计数器PC会被强制地从异常类型对应的固定存储器地址开始执行程序。这些固定的地址称为异常向量(exception vector)。ARM中异常向量定位在32位地址空间的低端,正常地址范围为:0x00000000~0x0000001C。每个异常向量内存放用户编写的一条跳转指令,可以转到中断服务子程序的首地址。
在嵌入式系统中,为了保证系统上电或复位时Boot-Loader 程序能够首先被加载运行,Flash只能连接到存储空间的0地址处。对于地址可重映射的系统,当系统启动后,可将存放在Flash中的异常向量表的内容拷贝到SDRAM的基地址处,然后修改相应的寄存器,将SDRAM 重映射到0地址。这样系统产生异常时,PC就可以直接从SDRAM中取指令,从而加快了程序的存取速度,缩短了中断的响应时间。
对于不支持地址重映射的系统,异常向量表中的内容只能存放在Flash的0地址处。每次系统进入异常的时候,系统必须从Flash中读取指令。这一点对于实时性要求不高的场合影响不大,但要在这样的系统上实现JFFS2文件系统则会出现问题。具体情况为:对Flash进行擦除(erase/eraseall)或写入(cp/cat/dd)操作时会发生中断,这时系统将强制PC指向异常向量表中的相应位置。在不支持地址重映射的系统中,异常向量表存放在Flash的0地址处。当PC开始从Flash中读取指令时,系统就会死机。这是因为Flash在擦除或写入的时候是不能执行读操作的,否则就会发生不可预料的错误,从而不能完成擦除或写入操作。相反,在支持地址重映射的系统中就不会出现这样的问题。因为它是从SDRAM中读取中断跳转指令的,不会出现在Flash擦除或写入时执行读操作的情况。
为了解决在不支持地址重映射的系统中不能对Flash进行正常擦除或写入的问题,采用了在MTD最低层的驱动函数的相应位置加关中断和开中断的方法。具体过程如下:
在μClinux-dist/linux-2.4.x/include/asm/arch/hard-ware.h中定义:
#define INT_ENABLE(n) IntMask &=~(1<<(n))
#define INT_DISABLE(n) IntMask |=(1<<(n))
在μClinux-dist/linux-2.4.x/include/asm/arch/irqs.h中定义:
#define INT_GLOBAL 26 /*总中断允许位*/
对μClinux-dist/linux-2.4.x/drivers/mtd/chips/cfi_cmdset_0002.c文件做如下修改:
#include
#include
static inline int do_erase_oneblock(struct map_info *map,
struct flchip *chip,unsigned long adr)
{ ……
INT_DISABLE(INT_GLOBAL);
……
INT_ENABLE(INT_GLOBAL);
……
}
static int do_write_oneword(struct map_info *map,struct flchip *chip,unsigned long adr,_u32 datum,int fast)
{ ……
INT_DISABLE(INT_GLOBAL);
……
INT_ENABLE(INT_GLOBAL);
……
}
3.3 内核配置文件设置
Menuconfig下的配置选项与在支持地址重映射的系统中实现JFFS2时的配置相同。为了避免MTDBLOCK与BLK-MEM主设备号的冲突,将μClinux-dist/linux-2.4.x/drivers/block/blkmem.c与μClinux-dist/linux-2.4.x/includee/linux/major.h中的BLKMEM_MAJOR值从“31”改为“30”,然后添加MTD设备节点到/vendors/Samsung/44B0目录下的Makefile文件中。
3.4 内核的编译与启动
以上步骤完成之后,运行内核编译命令,启动内核。在超级终端中将显示:
s3c44b0x flash device:200000 at 0
Found:SST SST39VF160
number of JEDEC chips:1
Creating 3 MTD partitions on ″S3C44B0X flash device″:
0x00000000-0x00020000:″reserved for bootloader(128k)″
mtd:Giving out device 0 to reserved for bootloader(128k)
0x00020000-0x00140000:″kernel(1152K)″
mtd:Giving out device 1 to kernel(1152K)
0x00140000-0x00200000:″jffs2(768K)″
mtd:Giving out device 2 to jffs2(768K)
3.5 创建和拷贝JFFS2映像文件
/> eraseall /dev/mtd2
Erased 768 Kibyte @ 0 - 100% complete.
/> cd /var/tmp
/var/tmp> mkdir jffs2
/var/tmp> mkdir jffs2/file
/var/tmp> mkfs.jffs2 -d jffs2 -o jffs2.img
/var/tmp> cp jffs2.img /dev/mtd2
3.6 Mount JFFS2分区
/var/tmp> mount -t jffs2 /dev/mtdblock2 /mnt
/var/tmp> cd /proc
/proc> cat mounts
……
/dev/mtdblock2 /mnt jffs2 rw 0 0 /*mount成功*/
/proc> cd /mnt
/mnt> ls
file
如果希望μClinux每次启动时,自动将Flash的第三个分区mount到/mnt目录,可以在/vendors/Samsung/44B0目录下的rc文件中加入:mount -t jffs2 /dev/mtdblock2/mnt。
4 结束语
本文讨论了在不支持Remap的系统中建立JFFS2文件系统的必要性和可能性,并结合Samsung的S3C44B0X芯片,通过在MTD Driver中加关中断和开中断的方法实现了在不支持Remap的系统中建立JFFS2文件系统。由于在MTD Driver中关中断和开中断的操作增加了系统的复杂性,因此推荐采用两片Flash:一片NOR型Flash用于存储启动装载程序和内核;一片NAND型Flash用于存储用户的动态数据和应用程序。其中NAND型Flash可以采用新型的YAFFS文件系统。
参考文献
1 贾东耀.μClinux下Nor Flash的JFFS2文件系统构建.国外电子元器件,2004;(9)
2 李桂良,刘发贵.JFFS2文件系统的关键技术及其在嵌入式系统中的应用.计算机应用,2003;(7)
3 胡晨峰.JFFS2文件系统在μClinux中的应用.电子产品世界,2004;(4)
4 吴明晖,徐睿,黄健等.基于ARM的嵌入式系统开发与应用.北京:人民邮电出版社,2004
5 王田苗.嵌入式系统设计与实例开发.北京:清华大学出版社,2002