如何在uClinux下使用MTD/jffs2

原创 2007年09月13日 21:06:00

 如何在uClinux下使用MTD/jffs2
由于romfs是一个只读的文件系统,当你的嵌入式设备动态的修改了一些文件,它无法保存。虽然uClinux在缺省配置下在DRAM中开辟了一块区域用作RAMDISK保存生成的文件,但是当设备在复位后所有在DRAM的数据都将消失。怎么才能保存动态生成的数据那,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。
Step 1:
由于ROM设备和MTDBlock设备的主设备号(major)都是31,所以如果你不想把JFFS2作为根文件系统的话,必须修改他们之一的major。如果你要修改JFFS2的设备major,在uClinux-dist/linux-2.4.x/include/linux/mtd/mtd.h中把
#define MTD_BLOCK_MAJOR  31
改成 
#define MTD_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中把
#define BLKMEM_MAJOR 31
改成
#define BLKMEM_MAJOR 30
第二中方法我没有试过,不过应该可以。
  Step 2:
 添加MTD设备。在uClinux-dist/vendors/Samsung/4510B/Makefile中添加MTD的字符设备和块设备。
 mtd0,c,90,0 mtd1,c,90,2 /
 mtdblock0,b,30,0 mtdblock1,b,30,1 /
添加设备的数目根据你自己的需要酌情确定,另一点要说明的是:mtd字符设备次设备号(minor)偶数是可擦写的,奇数是只读的。
Step 3:
添加在flash上的map文件。在uClinux-dist/linux-2.4.x/drivers/mtd/maps下添加自己mcu的map,例如我添加的是s3c4510b.c,它是仿照m5272c3.c修改的,内容如下:
/*
 * Normal mappings of chips on Samsung s3c4510b in physical memory
 */

#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>


#define WINDOW_ADDR 0x01000000
#define WINDOW_SIZE 0x100000
#define BUSWIDTH 2

static struct mtd_info *mymtd;

__u8 s3c4510b_read8(struct map_info *map, unsigned long ofs)
{
 return __raw_readb(map->map_priv_1 + ofs);
}

__u16 s3c4510b_read16(struct map_info *map, unsigned long ofs)
{
 return __raw_readw(map->map_priv_1 + ofs);
}

__u32 s3c4510b_read32(struct map_info *map, unsigned long ofs)
{
 return __raw_readl(map->map_priv_1 + ofs);
}

void s3c4510b_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
{
 memcpy(to, (void *)(map->map_priv_1 + from), len);
}

void s3c4510b_write8(struct map_info *map, __u8 d, unsigned long adr)
{
 __raw_writeb(d, map->map_priv_1 + adr);
}

void s3c4510b_write16(struct map_info *map, __u16 d, unsigned long adr)
{
 __raw_writew(d, map->map_priv_1 + adr);
}

void s3c4510b_write32(struct map_info *map, __u32 d, unsigned long adr)
{
 __raw_writel(d, map->map_priv_1 + adr);
}

void s3c4510b_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{
 memcpy((void *)(map->map_priv_1 + to), from, len);
}

struct map_info s3c4510b_map = {
 name: "S3C4510B flash device",
 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
};

static struct mtd_partition s3c4510b_partitions[] = {
        {
                name: "reserved for bootloader (64K)",
                size: 0x010000,
                offset: 0x0,
  mask_flags: MTD_WRITEABLE
        },
 {
  name: "user (960K)",
  size: 0xF0000,
  offset: 0x10000
 }
};

int __init init_s3c4510b(void)
{
        printk(KERN_NOTICE "s3c4510b flash device: %x at %x/n", WINDOW_SIZE, WINDOW_ADDR);
 s3c4510b_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);

 if (!s3c4510b_map.map_priv_1) {
  printk("Failed to ioremap/n");
  return -EIO;
 }
 mymtd = do_map_probe("jedec_probe", &s3c4510b_map);
 if (mymtd) {
  mymtd->module = THIS_MODULE;
  mymtd->erasesize = 0x10000;
  return add_mtd_partitions(mymtd, s3c4510b_partitions, sizeof(s3c4510b_partitions) / sizeof(struct mtd_partition));
 }
 iounmap((void *)s3c4510b_map.map_priv_1);
 return -ENXIO;
}

static void __exit cleanup_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),
#define WINDOW_ADDR 0x01000000
#define WINDOW_SIZE 0x100000
#define BUSWIDTH 2
定义它的基地址,容量和宽度,它的基地址和容量可参看
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.
 static struct mtd_partition s3c4510b_partitions[] = {
        {
                name: "reserved for bootloader (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 ' CFI Flash device mapped on Samsung S3C4510B' CONFIG_MTD_S3C4510B $CONFIG_MTD_CFI
fi
不过我没有成功,应该是要选上另一个配置选项才能显示它,我在这里取了个巧,我把它加到
if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate '  CFI Flash device mapped on Samsung S3C4510B' CONFIG_MTD_S3C4510B $CONFIG_MTD_CFI
中去。
和uClinux-dist/linux-2.4.x/drivers/mtd/maps/Makefile
obj-$(CONFIG_MTD_S3C4510B) += s3c4510b.o
Step 4:
添加flash的驱动。(nor flash分cfi 和jedec两种接口.)
uClinux-dist/linux-2.4.x/drivers/mtd/chips下的是chip的驱动层程序(《Linux MTD源代码分析》有很好的说明),由于hy29f800tt不在支持范围之内,但它和AM29F800BT
兼容,只不过Manufacturers id不同,所以我在jedec_table[]中添加
{
  mfr_id: MANUFACTURER_HYNIX,
  dev_id: HY29F800TT,
  name: "HYNIX HY29F800TT",
  DevSize: SIZE_1MiB,
  NumEraseRegions: 4,
  regions: {ERASEINFO(0x10000,15),
     ERASEINFO(0x08000,1),
     ERASEINFO(0x02000,2),
     ERASEINFO(0x04000,1)
  }
 }
其他不支持的flash芯片的驱动如何添加,我没有试。
Step 5:
在make menuconfig下配置选项。
在linux Kernel v2.4.20-uc0 Configuration下
 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  
  RAM/ROM/Flash chip drivers下
   CONFIG_MTD_CFI=Y
     CONFIG_MTD_JEDECPROBE=Y
     CONFIG_MTD_CFI_AMDSTD=Y
  Mapping drivers for chip access下
   CONFIG_S3C4510B=Y
 File systems下
  CONFIG_JFFS2_FS=Y
    CONFIG_JFFS2_FS_DEBUG=2
在uClinux v1.3.4 Configuration下
 Flash Tools下
  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.o mkfs.jffs2.o compr_zlib.o compr_rtime.o zlib.o
mkfs.jffs2: $(JFFS2_OBJS)
 $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LDPATH)  -lz $(LDLIBS) –lz不要


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

mtd设备操作、jffs2

安装 手动安装mtd-utils,根据系统自行选择 举例 #include #include #include #include int non_region_erase(int Fd...

mtd device上的JFFS2等文件系统不建议使用在block device上

I am going to use JFFS2 on top of my hard drive, is it OK? First off, JFFS2 was designed for MTD de...
  • xjzlq
  • xjzlq
  • 2014-04-30 15:19
  • 379

raspberry pi 3上使用jffs2

raspberry pi 3上使用jffs2最近准备学习linux mtd以及nand flash驱动,无奈手上的mini6410无法使用,而另一块板子—raspberry pi 3上没有nand f...

如何制作和使用Jffs2文件系统

本文主要介绍如何在AT91SAM9261EK板子上制作和使用jffs2文件系统,使用的是linux-2.6.21内核。 首先配置MTD $ make menu...

U-Boot1.3.1中JFFS2文件系统支持和U盘支持的使用备忘

U-Boot1.3.1中JFFS2文件系统支持和U盘支持的使用备忘   在U-Boot可能早就有了对JFFS2和U盘的支持,但是由于我没有移植是注意到,就没有使用。在这次的移植中,我通过往网上的资...
  • sydjm
  • sydjm
  • 2011-10-12 14:56
  • 642

u-boot 使用 jffs2 文件系统加载内核 备忘

u-boot 使用 jffs2 文件系统加载内核 备忘 1. 修改kernel 中的 nand.c #define MV_NUM_OF_NAND_PARTS 7 static struct ...

jffs2文件系统工具

  • 2016-10-21 16:20
  • 4.90MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)