45fan.com - 路饭网

搜索: 您的位置主页 > 电脑频道 > 电脑教程 > 阅读资讯:如何在uClinux下使用MTD和jffs2?

如何在uClinux下使用MTD和jffs2?

2016-09-03 11:17:26 来源:www.45fan.com 【

如何在uClinux下使用MTD和jffs2?

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_MAJOR31
改成
#defineMTD_BLOCK_MAJOR30
如果你要修改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<linux/module.h>
#include<linux/types.h>
#include<linux/kernel.h>
#include<asm/io.h>
#include<linux/mtd/mtd.h>
#include<linux/mtd/map.h>
#include<linux/mtd/partitions.h>
#include<linux/config.h>


#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<libgen.h>
(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不要

 

本文地址:http://www.45fan.com/dnjc/71645.html
Tags: uClinux MTD jffs2
编辑:路饭网
相关文章列表
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部