yaffs2 inband_tag 文件系统制作与烧录

  • 硬件平台
    • 君正 x1000 halley2

uboot中对yaffs2文件系统的支持

一般yaffs2文件系统会使用nand的oob区域存放tag信息,nand的数据区域存放实际的数据,由于不同的nand oob区域所存放的数据不一样,对于128Bytes oob的nand, 一般第一个byte用来标记坏块,第64Byte之后存放硬件ecc,那么在制作yaffs文件系统的时候,就需要避开这两个区域。对于其他的nand还需要根据实际情况避开,使得在后续维护不同的nand时非常的不方便,需要调整oob的读写。查看uboot源码,发现当实现的mtd驱动告诉上层,oobavail为0时,yaffs2层会使用in_band__tags。如下

fs/yaffs2/yaffs_uboot_glue.c

if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2))
dev->param.inband_tags = 1;

inband_tags 存储方式即区别于oob存储tag方式,将tag存储在nand的数据区域

  • 非inband_tags方式如下存储格式
nand data area(2048Bytes) nand oob area(128Bytes)
yaffs2 chunkSize(DATA) yaffs2 spareSize(TAGS)

* inband_tags方式如下存储格式

nand data area(2048Bytes) nand oob area(128Bytes)
yaffs2 chunkSize + yaffs2 spareSize yaffs2 not used

继续跟踪uboot代码,发现tag在inband_tags方式下的具体存放位置为chunkSize的最后(notag_ecc时)。

代码中体现如下:

fs/yaffs2/yaffs_mtdif.c
=======================

/* For yaffs2 writing there must be both data and tags.
* If we're using inband tags, then the tags are stuffed into
* the end of the data buffer.
*/
if (!data || !tags)
BUG();
else if (dev->param.inband_tags) {
struct yaffs_packed_tags2_tags_only *pt2tp;
pt2tp =
(struct yaffs_packed_tags2_tags_only *)(data +
dev->
data_bytes_per_chunk);
yaffs_pack_tags2_tags_only(pt2tp, tags);
} else {
yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
}

在该文件中指定了inband_tags时,data_bytes_per_chunk的大小是总的一次消耗大小减除_yaffs_packed_tags2_tags_only的大小,

注意这里是yaffs_packed_tags2_tags_only是16Bytes,但是个人认为应该是减除struct yaffs_packed_tags2的大小(28Bytes),两个结构体如下:

struct yaffs_packed_tags2_tags_only {
unsigned seq_number;
unsigned obj_id;
unsigned chunk_id;
unsigned n_bytes;
};

struct yaffs_packed_tags2 {
struct yaffs_packed_tags2_tags_only t;
struct yaffs_ecc_other ecc;
};

既然uboot这么做,那就尽量不去改变了,减去16Bytes吧。那就是在制作镜像文件时,需要将tag放在一个chunkSize最后的16Byte处就好了。

fs/yaffs2/yaffs_mtdif.c
=======================

if (dev->param.inband_tags)
dev->data_bytes_per_chunk =
dev->param.total_bytes_per_chunk -
sizeof(struct yaffs_packed_tags2_tags_only);

其中total_bytes_per_chunk的大小为mtd->writeSize,即为一个nand页大小。这里也可以看出为什么下面的mkyaffs2img.c源码中需要做对应的修改了。_

下载yaffs2源码

git://www.aleph1.co.uk/yaffs2

git clone git://www.aleph1.co.uk/yaffs2

修改源码

主要修改一下配置,chunkSize正常应该设置成nand pagesize,表示一次处理的数据大小,这里我们设置为pagesize - 16,是因为tag占用了16个字节,并且uboot中的源码判断为inbandtag时,读取tag的位置也是在最后16bytes处,所以制作镜像的文件做如此修改。

+#define spareSize 16 /* struct yaffs_packed_tags2_tags_only */
+#define chunkSize (2048 - 16) /* 根据具体的nand page大小填写 */
+#define pagesPerBlock 64 /* 每个nand block包含的页个数 */
diff --git a/utils/mkyaffs2image.c b/utils/mkyaffs2image.c
index 92f3f61..956a530 100644
--- a/utils/mkyaffs2image.c
+++ b/utils/mkyaffs2image.c
@@ -40,12 +40,20 @@ unsigned yaffs_trace_mask=0;

#define MAX_OBJECTS 10000

-// Adjust these to match your NAND LAYOUT:
-#define chunkSize 2048
-#define spareSize 64
-#define pagesPerBlock 64
-
+/* store tag in data area. */
+#define INBANDTAGS 1

+#ifndef INBANDTAGS
+// Adjust these to match your NAND LAYOUT:
+#define chunkSize 2048 /* page size */
+#define spareSize 128 /* oob size */
+#define pagesPerBlock 64 /* ppb */
+#else
+#define spareSize 16 
+#define chunkSize (2048 - 16) 
+#define pagesPerBlock 64 
+#endif

typedef struct
{
@@ -189,9 +197,14 @@ static void little_to_big_endian(struct yaffs_ext_tags *tagsPtr)

static void shuffle_oob(char *spareData, struct yaffs_packed_tags2 *pt)
{
+#ifndef INBANDTAGS
assert(sizeof(*pt) <= spareSize);
// NAND LAYOUT: For non-trivial OOB orderings, here would be a good place to shuffle.
- memcpy(spareData, pt, sizeof(*pt));
+ memcpy(spareData , pt, sizeof(*pt));
+#else
+ /*tags only, no ecc*/
+ memcpy(spareData, &pt->t, sizeof(pt->t));
+#endif
}
  1. 编译工具

进入下载的源码utils目录执行make. 生成mkyaffs2image.

使用mkyaffs2image制作镜像文件

./mkyaffs2image [dir] [imgname]

使用uboot烧录镜像文件


将镜像文件烧录到flash中,由于使用in_bandtag的方式存储tag,那么对于镜像烧录就简单了,不用烧写oob区域,只需要将其当做正常的数据烧写进nand即可._

假设需要烧写的yaffs2文件系统已经加载到了内存0x80600000位置处,需要烧写进flash的0x900000位置处,在uboot中只需要执行一下命令就可以进行烧录

halley2-sfcnand# nand erase 0x900000 0x400000 #根据具体情况修改
halley2-sfcnand# nand write 0x80600000 0x900000 0x400000

使用君正提供的烧录工具进行烧录

将烧录的rootfs分区改为MTD_MODE烧录即可。

总结


介绍了inbandtag的镜像文件系统的制作和烧录,当然yaffs2还支持将tag信息写入oob区,但是这种方式对于后期维护,需要针对每个nand修改代码,比较繁琐,就没有采用这种方式。使用inband_tags方式,只需要修改mkyaffs2img.c源码,配置nand 页大小即可,相对将tag放入oob中,简单多了。

猜你喜欢

转载自blog.csdn.net/boysic/article/details/82178386