uClinux下使用MTD和jffs2方法
2012-10-19
标签: uClinux

uCLinux默认的根文件系统是romfs,由于romfs是一个只读的文件系统,当你的嵌入式设备动态的修改了一些文件,它无法保存。虽然 uClinux在缺省配置下在DRAM中开辟了一块区域用作 RAMDISK保存生成的文件,但是当设备在复位后所有在DRAM的数据都将消失。怎么才能保存动态生成的数据,如果需要存储的文件容量又不大(1M左右),JFFS是一个不错的选择。它可以动态的把DRAM中的数据烧入Flash中,它的垃圾收集功能可以清除过时的数据。JFFS2是它的第二版,由REDHAT公司开发。下面我就将阐述我是如何在uClinux下使用JFFS2的。

目前只有LINUX支持JFFS(JFFS2),据说eCos将要支持它,不过具体情况我不是很清楚。我用的uClinux是uClinux-dist-20030522.tar.gz。patch是由dailzh写的补丁,请到它的网址(http://www.dailzh.com/)下载。我使用的Mcu是Samsung公司的s3c4510b。

要使用JFFS2,必须先启用MTD,MTD把文件系统和具体的Flash设备相隔离,上层的文件系统不用关心你使用的是什么flash,自有MTD帮你处理Flash的具体操作(例如erase,write,read)。如果你想进一步了解MTD,请参阅附录的相关内容。所以,我必须先要修改MTD。

Step1:

由于ROM设备和MTDBlock设备的主设备号(major)都是31,所以如果你不想把JFFS2作为根文件系统的话,必须修改他们之一的major。如果你要修改JFFS2的设备major,在uClinux-dist\linux-2.4.x\include\linux\mtd\mtd.h中把

#defineMTD_BLOCK_MAJOR 31

改成

#defineMTD_BLOCK_MAJOR 30

如果你要修改ROM的major,在uClinux-dist\linux-2.4.x\include\linux\major.h和uClinux-dist\linux-2.4.x\drivers\block\blkmem.c中把

#defineBLKMEM_MAJOR31

改成

#defineBLKMEM_MAJOR30

Step2:

添加MTD设备。在uClinux-dist\vendors\Samsung\4510B\Makefile中添加MTD的字符设备和块设备。

mtd0,c,90,0mtd1,c,90,2 \

mtdblock0,b,30,0mtdblock1,b,30,1 \

添加设备的数目根据你自己的需要酌情确定,另一点要说明的是:mtd字符设备次设备号(minor)偶数是可擦写的,奇数是只读的。

Step3:

添加在flash上的map文件。在uClinux-dist\linux-2.4.x\drivers\mtd\maps下添加自己mcu的map,例如我添加的是s3c4510b.c,它是仿照m5272c3.c修改的,内容如下:

/*

*NormalmappingsofchipsonSamsungs3c4510binphysicalmemory

*/

#include

#include

#include

#include

#include

#include

#include

#include

#defineWINDOW_ADDR0x01000000

#defineWINDOW_SIZE0x100000

#defineBUSWIDTH2

staticstructmtd_info *mymtd;

__u8s3c4510b_read8(structmap_info *map,unsignedlongofs)

{

return__raw_readb(map->map_priv_1 +ofs);

}

__u16s3c4510b_read16(structmap_info *map,unsignedlongofs)

{

return__raw_readw(map->map_priv_1 +ofs);

}

__u32s3c4510b_read32(structmap_info *map,unsignedlongofs)

{

return__raw_readl(map->map_priv_1 +ofs);

}

voids3c4510b_copy_from(structmap_info *map,void *to,unsignedlongfrom,ssize_tlen)

{

memcpy(to, (void *)(map->map_priv_1 +from),len);

}

voids3c4510b_write8(structmap_info *map,__u8d,unsignedlongadr)

{

__raw_writeb(d,map->map_priv_1 +adr);

}

voids3c4510b_write16(structmap_info *map,__u16d,unsignedlongadr)

{

__raw_writew(d,map->map_priv_1 +adr);

}

voids3c4510b_write32(structmap_info *map,__u32d,unsignedlongadr)

{

__raw_writel(d,map->map_priv_1 +adr);

}

voids3c4510b_copy_to(structmap_info *map,unsignedlongto,constvoid *from,ssize_tlen)

{

memcpy((void *)(map->map_priv_1 +to),from,len);

}

structmap_infos3c4510b_map = {

name: "S3C4510Bflashdevice",

size:WINDOW_SIZE,

buswidth:BUSWIDTH,

read8:s3c4510b_read8,

read16:s3c4510b_read16,

read32:s3c4510b_read32,

copy_from:s3c4510b_copy_from,

write8:s3c4510b_write8,

write16:s3c4510b_write16,

write32:s3c4510b_write32,

copy_to:s3c4510b_copy_to

};

staticstructmtd_partitions3c4510b_partitions[] = {

{

name: "reservedforbootloader (64K)",

size:0x010000,

offset:0x0,

mask_flags:MTD_WRITEABLE

},

{

name: "user (960K)",

size:0xF0000,

offset:0x10000

}

};

int__initinit_s3c4510b(void)

{

printk(KERN_NOTICE "s3c4510bflashdevice: %xat %x\n",WINDOW_SIZE,WINDOW_ADDR);

s3c4510b_map.map_priv_1 = (unsignedlong)ioremap(WINDOW_ADDR,WINDOW_SIZE);

if (!s3c4510b_map.map_priv_1) {

printk("Failedtoioremap\n");

return-EIO;

}

mymtd =do_map_probe("jedec_probe", &s3c4510b_map);

if (mymtd) {

mymtd->module =THIS_MODULE;

mymtd->erasesize =0x10000;

returnadd_mtd_partitions(mymtd,s3c4510b_partitions,sizeof(s3c4510b_partitions) /sizeof(structmtd_partition));

}

iounmap((void *)s3c4510b_map.map_priv_1);

return-ENXIO;

}

staticvoid__exitcleanup_s3c4510b(void)

{

if (mymtd) {

del_mtd_partitions(mymtd);

map_destroy(mymtd);

}

if (s3c4510b_map.map_priv_1) {

iounmap((void *)s3c4510b_map.map_priv_1);

s3c4510b_map.map_priv_1 =0;

}

}

module_init(init_s3c4510b);

module_exit(cleanup_s3c4510b);

需要说明的几点

1. 我使用的flash是hy29f800tt,它的容量是1mbyte(或者512kword),

#defineWINDOW_ADDR0x01000000

#defineWINDOW_SIZE0x100000

#defineBUSWIDTH2

定义它的基地址,容量和宽度,它的基地址和容量可参看

uClinux-dist\linux-2.4.x\include\asm-armnommu\arch-snds100\hardware.h中的声明,BUSWIDTH =2表示是16bit。

2. 在m5272c3.c中的函数memcpy_fromio和memcpy_toio改有memcpy,原因是当使用前二个函数时cp命令不能使用,具体是什么原因目前我也不清楚。

3.

staticstructmtd_partitions3c4510b_partitions[] = {

{

name: "reservedforbootloader (64K)",

size:0x010000,

offset:0x0,

mask_flags:MTD_WRITEABLE

},

{

name: "user (960K)",

size:0xF0000,

offset:0x10000

}

};

是在你的flash设备中分区情况,我是分了二个区,你根据需要自己加减,mask_flags:MTD_WRITEABLE表示此区只读。

4.mymtd->erasesize =0x10000;表示擦除的大小,hy29f800tt是64kbyte。

为了把它集成到uClinux配置中,要修改uClinux-dist\linux-2.4.x\drivers\mtd\maps\config.in

if [ "$CONFIG_S3C4510B" ];then

dep_tristate 'CFIFlashdevicemappedonSamsungS3C4510B'CONFIG_MTD_S3C4510B $CONFIG_MTD_CFI

fi

不过我没有成功,应该是要选上另一个配置选项才能显示它,我在这里取了个巧,我把它加到

if [ "$CONFIG_ARM" = "y" ];then

dep_tristate ' CFIFlashdevicemappedonSamsungS3C4510B'CONFIG_MTD_S3C4510B $CONFIG_MTD_CFI

中去。

和uClinux-dist\linux-2.4.x\drivers\mtd\maps\Makefile

obj-$(CONFIG_MTD_S3C4510B) +=s3c4510b.o

Step4:

添加flash的驱动。(norflash分cfi 和jedec两种接口.)

uClinux-dist\linux-2.4.x\drivers\mtd\chips下的是chip的驱动层程序(《LinuxMTD源代码分析》有很好的说明),由于hy29f800tt不在支持范围之内,但它和AM29F800BT兼容,只不过Manufacturersid不同,所以我在jedec_table[]中添加

{

mfr_id:MANUFACTURER_HYNIX,

dev_id:HY29F800TT,

name: "HYNIXHY29F800TT",

DevSize:SIZE_1MiB,

NumEraseRegions:4,

regions: {ERASEINFO(0x10000,15),

ERASEINFO(0x08000,1),

ERASEINFO(0x02000,2),

ERASEINFO(0x04000,1)

}

}

其他不支持的flash芯片的驱动如何添加,我没有试。

Step5:

在makemenuconfig下配置选项。

在linuxKernelv2.4.20-uc0Configuration下

MemoryTechnologyDevices(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

RAM/ROM/Flashchipdrivers下

CONFIG_MTD_CFI=Y

CONFIG_MTD_JEDECPROBE=Y

CONFIG_MTD_CFI_AMDSTD=Y

Mappingdriversforchipaccess下

CONFIG_S3C4510B=Y

Filesystems下

CONFIG_JFFS2_FS=Y

CONFIG_JFFS2_FS_DEBUG=2

在uClinuxv1.3.4Configuration下

FlashTools下

CONFIG_USER_MTDUTILS=Y

CONFIG_USER_MTDUTILS_ERASE=Y

CONFIG_USER_MTDUTILS_ERASEALL=Y

CONFIG_USER_MTDUTILS_MKFSJFFS2=Y

BusyBox下选中cat ,cp ,dd,mount,umount,mkdir工具。

还有要说明的几点:(可能是uClinux的bugs吧,不是很清楚!)

(1)在uClinux-dist\user\mtd-utils\mkfs.jffs2.c中注释#include

(2)JFFS2是采用压缩格式,我没有采用zlib库,而是把uClinux-dist\user\pppd\pppdump\zlib.c和zlib.h拷贝到uClinux-dist\user\mtd-utils下,在它的Makefile中改成

JFFS2_OBJS =crc32.omkfs.jffs2.ocompr_zlib.ocompr_rtime.ozlib.o

mkfs.jffs2: $(JFFS2_OBJS)

$(CC) $(LDFLAGS) $(CFLAGS)-o $@ $^ $(LDPATH)-lz $(LDLIBS) –lz不要

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号