u-boot支持yaffs映像燒寫的補丁

u-boot的nand flash驅動有兩個版本,彷佛是以u-boot1.1.5爲分界點的,以前的版本使用的是本身寫的nand flash驅動,然後面的版本使用的是linux內核中nand flash的驅動。這兩個版本有可能在同一個u-boot中存在,都存放在
driver目錄下面,一個爲nand,一個爲nand_legacy,意思爲傳統的nand flash驅動。二者使用一個宏開關
CFG_NAND_LEGACY來打開,若是定義這個宏的話,將使用傳統的nand flash驅動,不然使用最新的flash驅動。
關於傳統的flash驅動中的yaffs文件映像的下載問題,我已經解決,能夠看個人另外的一篇文章,使用的內核版本是2.6.15,你去看內核的yaffs代碼,2.6.17是內核中yaffs的一個分界點,因此你2.6.17的內核可能能夠使用我說的方法,2.618的內核可能就不能用我說的那個方法,2.6.18以上的內核沒有驗證過,熱心的朋友能夠幫忙使用2.6.18以上的內核幫忙驗證一下,而後在這裏告訴一下在下。
最新的flash中的yaffs文件映像燒寫的問題,我放出一個老外的驅動,我驗證過映像下載是沒有問題,可是產生了一些其餘的問題,我一直沒有解決,因此這篇文章也拖到如今。
              
                diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index b011b5e..2760874 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -351,6 +351,23 @@ #endif
                 opts.quiet      = quiet;
                 ret = nand_write_opts(nand, &opts);
             }
+#ifdef CFG_NAND_YAFFS_WRITE
+        } else if (!read && s != NULL &&
+               (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))) {
+            nand_write_options_t opts;
+            memset(&opts, 0, sizeof(opts));
+            opts.buffer    = (u_char*) addr;
+            opts.length    = size;
+            opts.offset    = off;
+            opts.pad    = 0;
+            opts.blockalign = 1;
+            opts.quiet      = quiet;
+            opts.writeoob    = 1;
+            opts.autoplace    = 1;
+            if (s[6] == '1')
+                opts.forceyaffs = 1;
+            ret = nand_write_opts(nand, &opts);
+#endif
         } else {
             if (read)
                 ret = nand_read(nand, off, &size, (u_char *)addr);
@@ -462,6 +479,10 @@ U_BOOT_CMD(nand, 5, 1, do_nand,
     "nand read[.jffs2]     - addr off|partition size\n"
     "nand write[.jffs2]    - addr off|partiton size - read/write `size' bytes starting\n"
     "    at offset `off' to/from memory address `addr'\n"
+#ifdef CFG_NAND_YAFFS_WRITE
+    "nand write[.yaffs[1]] - addr off|partition size - write `size' byte yaffs image\n"
+    "    starting at offset `off' from memory address `addr' (.yaffs1 for 512+16 NAND)\n"
+#endif
     "nand erase [clean] [off size] - erase `size' bytes from\n"
     "    offset `off' (entire device if not specified)\n"
     "nand bad - show bad blocks\n"
diff --git a/drivers/nand/nand_util.c b/drivers/nand/nand_util.c
index 10bf036..bea5c1e 100644
--- a/drivers/nand/nand_util.c
+++ b/drivers/nand/nand_util.c
@@ -343,6 +343,10 @@ int nand_write_opts(nand_info_t *meminfo
         struct nand_oobinfo *oobsel =
             opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;

+#ifdef CFG_NAND_YAFFS1_NEW_OOB_LAYOUT
+        /* jffs2_oobinfo matches 2.6.18+ MTD nand_oob_16 ecclayout */
+        oobsel = &jffs2_oobinfo;
+#endif
         if (meminfo->oobsize == 8) {
             if (opts->forceyaffs) {
                 printf("YAFSS cannot operate on "
@@ -443,6 +447,28 @@ int nand_write_opts(nand_info_t *meminfo
             memcpy(oob_buf, buffer, meminfo->oobsize);
             buffer += meminfo->oobsize;

+            if (opts->forceyaffs) {
+#ifdef CFG_NAND_YAFFS1_NEW_OOB_LAYOUT
+                /* translate OOB for yaffs1 on Linux 2.6.18+ */
+                oob_buf[15] = oob_buf[12];
+                oob_buf[14] = oob_buf[11];
+                oob_buf[13] = (oob_buf[7] & 0x3f)
+                    | (oob_buf[5] == 'Y' ? 0 : 0x80)
+                    | (oob_buf[4] == 0 ? 0 : 0x40);
+                oob_buf[12] = oob_buf[6];
+                oob_buf[11] = oob_buf[3];
+                oob_buf[10] = oob_buf[2];
+                oob_buf[9]  = oob_buf[1];
+                oob_buf[8]  = oob_buf[0];
+                memset(oob_buf, 0xff, 8);
+#else
+                /* set the ECC bytes to 0xff so MTD will
+                   calculate it */
+                int i;
+                for (i = 0; i  meminfo->oobinfo.eccbytes; i++)
+                    oob_buf[meminfo->oobinfo.eccpos[i]] = 0xff;
+#endif
+            }
             /* write OOB data first, as ecc will be placed
              * in there*/
             result = meminfo->write_oob(meminfo,

本身選擇性的添加吧。

這個補丁主要完成了一個oob字節順序的改變。


注意同時要查看一下你的mkyaffsimage命令的源文件裏面的oob的字節的順序!

這樣製做的u-boot下載yaffs文件系統映像沒有問題,可是垃圾回收(garbage collection)機制有問題,對該文件系統進行寫入操做(mkdir、 touch)時,系統提示:

page 1302 in gc has no object: 0 0 0
.
.
.
page 1311 in gc has no object : 0 0 0

具體緣由待查!


內核的一個編譯選項的意義:
Device Drivers->Memory Technolovy Devices->FTL(Flash Translation Layer) Support
這個選項的意義在於?
因爲沒法重複的在flash的同一塊存儲位置上作寫入的操做(必須事先擦除該快以後才能寫入),所以通常在硬盤上使用的文件系統,如:fat16,fat32,ntfs,ext2,ext3等將沒法直接用到flash上,爲了沿用這些文件系統,則必須透過一層轉換層來將邏輯地址對應到flash的存儲器的物理位置上,使系統能把flash看成普通的硬盤來使用,咱們將這一層稱之爲ftl(flash translation layer),flash主要用於nor flash上,而nftl則應用於nand flash上。
最簡單的ftl的實現方法就是一對一的映射,那麼當上層的文件系統要寫一個塊設備的扇區的時候,閃存作下面的操做來完成這個請求。
1、將這個扇區的所在的擦處塊讀到內存中,放入緩衝
2、按照寫要求更新該緩衝塊
3、對該快進行擦除
4、回寫
存在的問題:
1、效率低,一個chunk更新要對整個block進行擦除
2、沒有磨損均衡策略
3、很是不安全!容易引發數據的丟失,若是3步與第4步之間,數據將所有丟失

因此閃存轉換層採用的算法比這個複雜一點

在flash上,儘可能避免使用傳統的依賴閃存轉換層的文件系統,最好採用專門的針對flash的文件系統,如
jffs3和yaffs2

問題:加載cramfs文件系統分區(mount -t cramfs /dev/mtdblock1 /mnt/flash1)的時候,報出以下的錯誤:
end_request: I/O error, dev mtdblock2, sector 0
Buffer I/O error on device mtdblock2, logical block 0
end_request: I/O error, dev mtdblock2, sector 0
Buffer I/O error on device mtdblock2, logical block 0
end_request: I/O error, dev mtdblock2, sector 8
Buffer I/O error on device mtdblock2, logical block 1
end_request: I/O error, dev mtdblock2, sector 8
Buffer I/O error on device mtdblock2, logical block 1
end_request: I/O error, dev mtdblock2, sector 16
Buffer I/O error on device mtdblock2, logical block 2
end_request: I/O error, dev mtdblock2, sector 16
開始覺得是硬件錯誤,後來仔細一檢查發現:實際上是uboot寫入cramfs文件系統映像時使用的ecc校驗算法和內核使用的校驗算法不一致致使的,若是咱們將內核中的mtd層ecc校驗NAND_ECC_SOFT關掉,在/drivers/mtd/at91_nand.c文件中有定義。則系統在加載的時候將再也不報錯,驗證了這是校驗的問題,解覺的辦法是什麼?
首先在uboot中,使用nand erase 將cramfs分區擦除乾淨,以nfs的方式啓動linux,而後使用
cp root_fs_cramfs.img /dev/mtd1
將cramfs映像文件拷貝到相應的字符設備中。
而後使用mount -t cramfs /dev/mtdblock1 /mnt/flash1。
則cramfs文件系統加載正常。

這樣咱們能夠不使用ramdisk技術來加載根文件系統,能夠省去讀內存的時間,加快啓動速度。
這時的內核啓動參數爲:
noinitrd init=/linuxrc root=/dev/mtdblock1 ro console=ttyS0,115200 mem=64M ip=192.168.0.11 netmask=255.255.255.0
修改u-boot的bootcmd ,就能夠加快啓動速度,同時節省ram的空間!直接從cramfs的nandflash上啓動
相關文章
相關標籤/搜索