1. 程式人生 > >JZ2440:yaffs2 格式根檔案系統製作

JZ2440:yaffs2 格式根檔案系統製作

YAFFS目前有yaffs、yaffs2兩個版本,一般來說,yaffs對小頁(512B+16B/頁)的NandFlash(68M)有很好的支援,yaffs2對大頁(2K+64B/頁)的NandFlash(128M、256M或者更大)支援更好。 我的 nandflash 型號是:K9F2G08U0C 大小是:256M 因此採用 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 . ./mkyaffs2imagefs_mini fs_mini.yaffs2 (這裡有個坑,如果用 mkyaffs2image 則用的是系統中應用程式中資料夾中的 mkyaffs2image 程式,所以必須加上 ./ ) sudo chmod 777 fs_mini.yaffs2 cp 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 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,115200 boot_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=/linuxrc bootargs=noinitrd root=/dev/mtdblock3 rw rootfstype=yaffs2 init=/linuxrc console=ttySAC0,115200 bootcmd=nand read 0x31000000 0x100000 0x400000;bootm 0x31000000 bootcmd_from_nand=nand read 0x31000000 0x100000 0x400000;bootm 0x31000000 bootcmd_from_nfs=tftp 31000000 uImage;bootm 31000000