需求

由于字库文件超过13MB一个文件,而且内存有限,导致无法正常启动。

从原来的裸机程序,改为FreeRTOS程序

所以需要将图片,字库从原来的代码中分离,生成独立的bin文件,存储到NAND Flash中。

LVGL动态从NAND Flash中加载图片,字库等内容。

Eclipse开发工具设置

修改Eclipse配置

1
2
3
4
5
6
7
8
CONFIG_YAFFS_DIRECT=1
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=1
CONFIG_YAFFS_YAFFS2=1
NO_Y_INLINE=1
CONFIG_YAFFS_PROVIDE_DEFS=1
CONFIG_YAFFSFS_PROVIDE_VALUES=1
__UBOOT__=1
CONFIG_MTD_PARTITIONS=1

添加头文件路径

添加C文件

代码修改

配置硬件

配置LVGL的lv_port_fs.c

初始化

调用

创建yaffs2镜像

1
mkyaffs2 rootfs rootfs_yaffs2.img

—————————-参考文章—————————————-

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

1
2
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/* 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),两个结构体如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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

1
2
3
4
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

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

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

1
2
3
+#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 }

编译工具

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

使用mkyaffs2image制作镜像文件

1
./mkyaffs2image [dir] [imgname]

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

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

1
2
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中,简单多了。