我的 nandflash 型号是:K9F2G08U0C大小是:256M因此采用 mkyaffs2image 工具:韦东山的mkyaffs2image工具
1. 首先下载 yaffs2 源码
git clone git://www.aleph1.co.uk/yaffs22. 将 yaffs2 选项放到linux 内核的配置选项中:
cd yaffs2 ./patch-ker.sh c m linux-tree我的内核放在了 ~/wor_lip/linux-3.4.112 文件夹下,因此,命令为: ./patch-ker.sh c m ~/wor_lip/linux-3.4.112
3. 查看内核让内核支持yaffs2:
进入linux内核源码目录, make menuconfig File systems ---> [*] Miscellaneous filesystems ---> <*> yaffs2 file system support 其他配置也要配置好 make uImage重新生成uImage4. uboot 中添加 支持 yaffs2 的烧写:
支持 yaffs2 的烧写,就是添加 nand write.yaffs2 命令cmd/nand.c 文件中: @@ -617,7 +617,17 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } ret = nand_write_skip_bad(nand, off, &rwsize, NULL, maxsize, (u_char *)addr,- WITH_DROP_FFS | WITH_WR_VERIFY);+ WITH_DROP_FFS | WITH_WR_VERIFY);+#endif+#ifdef CONFIG_CMD_NAND_YAFFS+ } else if (!strcmp(s, ".yaffs2")) {+ if (read) {+ printf("Unknown nand command suffix '%s'\n", s);+ return 1;+ }+ ret = nand_write_skip_bad(nand, off, &rwsize, NULL,+ maxsize, (u_char *)addr,+ WITH_YAFFS_OOB); #endif } else if (!strcmp(s, ".oob")) { /* out-of-band data */@@ -765,6 +775,11 @@ static char nand_help_text[] = " 'addr', skipping bad blocks and dropping any pages at the end\n" " of eraseblocks that contain only 0xFF\n" #endif+#ifdef CONFIG_CMD_NAND_YAFFS+ "nand write.yaffs2 - addr off|partition size\n"+ " write 'size' bytes starting at offset 'off' with yaffs format\n"+ " from memory address 'addr', skipping bad blocks\n"+#endif "nand erase[.spread] [clean] off size - erase 'size' bytes " "from offset 'off'\n" " With '.spread', erase enough for given file size, otherwise,\n"
drivers/mtd/nand/nand_util.c @@ -580,8 +580,23 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
if (actual) *actual = 0;-+#ifdef CONFIG_CMD_NAND_YAFFS+ if (flags & WITH_YAFFS_OOB) {+ if (flags & ~WITH_YAFFS_OOB)+ return -EINVAL;+ int pages;+ pages = nand->erasesize / nand->writesize;+ blocksize = (pages * nand->oobsize) + nand->erasesize; + if (*length % (nand->writesize + nand->oobsize)){+ printf ("Attempt to write incomplete page"+ " in yaffs mode\n"); + return -EINVAL;+ }+ }else+#endif+ { blocksize = nand->erasesize;+ }
/* * nand_write() handles unaligned, partial page writes.@@ -650,24 +665,55 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, else write_size = blocksize - block_offset;
- truncated_write_size = write_size;-#ifdef CONFIG_CMD_NAND_TRIMFFS- if (flags & WITH_DROP_FFS)- truncated_write_size = drop_ffs(nand, p_buffer,- &write_size);+#ifdef CONFIG_CMD_NAND_YAFFS+ if (flags & WITH_YAFFS_OOB) {+ int page, pages;+ size_t pagesize = nand->writesize;+ size_t pagesize_oob = pagesize + nand->oobsize;+ struct mtd_oob_ops ops; ++ ops.len = pagesize;+ ops.ooblen = nand->oobsize;+ ops.mode = MTD_OPS_RAW; //这里要改为RAW+ ops.ooboffs = 0;++ pages = write_size / pagesize_oob;+ for (page = 0; page < pages; page++) {+ WATCHDOG_RESET();++ ops.datbuf = p_buffer;+ ops.oobbuf = ops.datbuf + pagesize;++ rval = nand->_write_oob(nand, offset, &ops);+ if (rval != 0)+ break; ++ offset += pagesize;+ p_buffer += pagesize_oob;+ }+ }+ else #endif+ {
- rval = nand_write(nand, offset, &truncated_write_size,- p_buffer);+ truncated_write_size = write_size;+#ifdef CONFIG_CMD_NAND_TRIMFFS+ if (flags & WITH_DROP_FFS)+ truncated_write_size = drop_ffs(nand, p_buffer,+ &write_size);+#endif
- if ((flags & WITH_WR_VERIFY) && !rval)- rval = nand_verify(nand, offset,- truncated_write_size, p_buffer);+ rval = nand_write(nand, offset, &truncated_write_size,+ p_buffer);
- offset += write_size;- p_buffer += write_size;+ if ((flags & WITH_WR_VERIFY) && !rval)+ rval = nand_verify(nand, offset,+ truncated_write_size, p_buffer);
- if (rval != 0) {+ offset += write_size;+ p_buffer += write_size;+ }+ if (rval != 0) { printf("NAND write to offset %llx failed %d\n", offset, rval); *length -= left_to_write;
include/configs/lip2440.h @@ -85,6 +85,7 @@ #define CONFIG_CMD_PING #define CONFIG_CMD_REGINFO #define CONFIG_CMD_USB+#define CONFIG_CMD_NAND_YAFFS
#define CONFIG_SYS_HUSH_PARSER #define CONFIG_CMDLINE_EDITING
include/nand.h @@ -27,6 +27,9 @@ #endif #endif
+#define WITH_YAFFS_OOB (1 << 0)+#define WITH_DROP_FFS (1 << 0)+ extern void nand_init(void);
#include <linux/compat.h>
重新编译,即可
4. 生成 yaffs2 类型的根文件系统:
这里用的制作 yaffs2 格式的工具是 韦东山 提供的工具,自己在yaffs2 源码的utils中make生成的是不能使用的,需要做一些相应的修改。cp /mnt/hgfs/share/mkyaffs2image ../mkyaffs2image fs_mini fs_mini.yaffs2 (这里有个坑,如果用 mkyaffs2image 则用的是系统中应用程序中文件夹中的 mkyaffs2image 程序,所以必须加上 ./ )sudo chmod 777 fs_mini.yaffs2cp fs_mini.yaffs2 /tftpboot/5. 将 yaffs2 类型的根文件系统烧写到nand的指定的如下中的 root 位置上。
对 linux 内核源码的 arch/arm/mach-s3c24xx/mach-mini2440.c 中的说明: static struct mtd_partition mini2440_default_nand_part[] __initdata = { [0] = { .name = "u-boot", // bootloader 所在分区,对应 /dev/mtdblock0 .size = SZ_512K, .offset = 0, }, [1] = { .name = "u-boot-env", // bootloader 的参数区,对应 /dev/mtdblock1 .size = SZ_512K, .offset = SZ_512K, }, [2] = { .name = "kernel", // 内核所在分区,对应 /dev/mtdblock2 /* 5 megabytes, for a kernel with no modules * or a uImage with a ramdisk attached */ /* *.size = 0x00500000, *.offset = SZ_256K + SZ_128K, */ .offset = SZ_1M, (0x10 0000).size = SZ_4M, (0x40 0000) }, [3] = { .name = "root", // 根文件系统所在分区,可用来存放 yaffs2 文件系统,对应 /dev/mtdblock3 /* *.offset = SZ_256K + SZ_128K + 0x00500000, *.size = MTDPART_SIZ_FULL, */ .offset = SZ_1M*5, (0x50 0000) .size = SZ_1M*100, (0x640 0000) }, };
一个值得参考的设置:
6. 用tftp 命令,将 uImage和fs_mini.yaffs2分别下载到nand中去
首先查看 uImage 和 fs_mini.yaffs2 的大小分别是 2.4M 和 6.1M tftp 0x30008000 uImagenand erase 0x100000 0x400000 nand write 0x30008000 0x100000 0x400000
tftp 0x30008000 fs_mini.yaffs2 nand erase 0x500000 0x6400000 nand write.yaffs2 0x30008000 0x500000 [实际下载进去的大小,防止产生坏块]