JZ2440:yaffs2 格式根文件系统制作

时间:2021-10-19 18:48:25
YAFFS目前有yaffs、yaffs2两个版本,一般来说,yaffs对小页(512B+16B/页)的NandFlash(68M)有很好的支持,yaffs2对大页(2K+64B/页)的NandFlash(128M、256M或者更大)支持更好。
我的 nandflash 型号是:K9F2G08U0C大小是:256M因此采用 mkyaffs2image 工具:韦东山的mkyaffs2image工具

1. 首先下载 yaffs2 源码

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

2. 将 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重新生成uImage

4. 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)     }, };

一个值得参考的设置:

JZ2440:yaffs2 格式根文件系统制作


6. 用tftp 命令,将 uImage和fs_mini.yaffs2分别下载到nand中去

首先查看 uImage 和 fs_mini.yaffs2 的大小分别是 2.4M 和 6.1M     tftp 0x30008000 uImage
    nand erase 0x100000 0x400000     nand write 0x30008000 0x100000 0x400000
    tftp 0x30008000 fs_mini.yaffs2     nand erase 0x500000 0x6400000     nand write.yaffs2 0x30008000 0x500000 [实际下载进去的大小,防止产生坏块]

7. 修改 uboot 的启动参数:

boot_from_nand=noinitrd root=/dev/mtdblock2 rw rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200boot_from_nfs=noinitrd boot=/dev/nfs rw nfsroot=10.100.151.215:/source/fs_mini,tcp ip=10.100.151.222:10.100.151.215:10.100.151.2:255.255.255.0:jz2440::off console=ttySAC0,115200 mem=64M init=/linuxrcbootargs=noinitrd root=/dev/mtdblock3 rw rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200bootcmd=nand read 0x31000000 0x100000 0x400000;bootm 0x31000000bootcmd_from_nand=nand read 0x31000000 0x100000 0x400000;bootm 0x31000000bootcmd_from_nfs=tftp 31000000 uImage;bootm 31000000