1. 程式人生 > >ubi移植與flash替換問題

ubi移植與flash替換問題

我在用TI的dm368開發板,kernel是2.6.32.17,預設的flash檔案系統是jffs2,但是jffs2在大分割槽下,mount速度很慢,而且佔用ram較多,因此,我想使用ubifs看看效能是否會更好些。

ubifs的原理和配置過程,很多網頁都有介紹的,我給一個連結,大家可以看看,我就不轉載了,我重點說我移植過程中遇到並解決的問題。

kerne的配置很簡單,2.6.32裡面都有,選上並重新編譯就好了。

ubiattach、ubimkvol等工具,TI的dvsdk裡面自帶了,能用,我就偷了個懶,沒有重新編譯。

很輕鬆的照著網頁說明操作了下,mount 分割槽也成功了,複製檔案也成功了,很高興:)

ubiattach /dev/ubi_ctrl -m 3

ubimkvol  /dev/ubi0 -N rootfs -s 480MiB

mount -t ubifs  ubi0_0 /mnt/nand/ -o sync

但很快就遇到麻煩了,開發板關機重新啟動,我再mout ubi檔案系統就出錯了,提示了一堆錯誤,而且分割槽是空的,之前複製的檔案不見了。

問題如下:

ubiattach /dev/ubi_ctrl -m 3

UBI error: ubi_io_read: error -74while reading 64 bytes from PEB 1662:0, read 64 bytes

UBI error: ubi_io_read: error -74while reading 64 bytes from PEB 1663:0, read 64 bytes

為了分析問題,我把mtd和ubifs的debug log都打開了,看到了一些資訊;

#define   EBADMSG           74   /* Not a data message */

              /*Nand returns -EBADMSG on ecc errors, but it returns

               * the data. For our userspace tools it isimportant

               * to dump areas with ecc errors !

               * For kernel internal usage it also mightreturn -EUCLEAN

               * to signal the caller that a bitflip hasoccured and has

               * been corrected by the ECC algorithm.

               * Userspace software which accesses NAND thisway

               * must be aware of the fact that it deals withNAND

               */

nand_do_read_ops

       stats= mtd->ecc_stats;

       if(mtd->ecc_stats.failed - stats.failed)

              return-EBADMSG;

nand_read_page_hwecc

              stat= chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);

              if(stat < 0)

                     mtd->ecc_stats.failed++;

              else

                     mtd->ecc_stats.corrected+= stat;

看樣子,應該是ECC出錯了,可是我用的是硬體ECC校驗,怎麼可能幾乎全部的page都出現ecc校驗錯誤了呢?

[email protected]:~#flash_eraseall  /dev/mtd3

[email protected]:~# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    129024 bytes

UBI: smallest flash I/O unit:    2048

UBI: sub-page size:              512

UBI: VID header offset:          512 (aligned 512)

UBI: data offset:                2048

分析下UBI寫資料的過程,

UBI DBG (pid 1484): ubi_io_write:write 512 bytes to PEB 57:0

int ubi_io_write(struct ubi_device*ubi, const void *buf, int pnum, int offset,

               int len)

       addr= (loff_t)pnum * ubi->peb_size + offset;

       err= ubi->mtd->write(ubi->mtd, addr, len, &written, buf);

在io_init函式中可以看到幾個變數的賦值;

       ubi->peb_size   = ubi->mtd->erasesize;

       ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size,ubi->mtd);

       ubi->flash_size= ubi->mtd->size;

從debug log來看,這裡一次寫了512位元組,從某個block的起始page開始,offset是0;

那麼到了nand mtd底層驅動,行為就是;

nand_write->nand_do_write_ops:

       subpage= column || (writelen & (mtd->writesize - 1));

這裡,subpage就是writelen,512;

也可以得知一點,ubifs沒有使用oob,這跟jffs2和yaffs2是不同的;

              /*Partial page write ? */

              if(unlikely(column || writelen < (mtd->writesize - 1))) {

                     cached= 0;

                     bytes= min_t(int, bytes - column, (int) writelen);

                     chip->pagebuf= -1;

                     memset(chip->buffers->databuf,0xff, mtd->writesize);

                     memcpy(&chip->buffers->databuf[column],buf, bytes);

                     wbuf= chip->buffers->databuf;

              }

              ret= chip->write_page(mtd, chip, wbuf, page, cached,

                                   (ops->mode == MTD_OOB_RAW));

下面是write_page函式的程式碼;

static int nand_write_page(structmtd_info *mtd, struct nand_chip *chip,

                        const uint8_t *buf, int page, int cached,int raw)

{

       intstatus;

       chip->cmdfunc(mtd,NAND_CMD_SEQIN, 0x00, page);

       if(unlikely(raw))

              chip->ecc.write_page_raw(mtd,chip, buf);

       else

              chip->ecc.write_page(mtd,chip, buf);

       /*

        * Cached progamming disabled for now, Not sureif its worth the

        * trouble. The speed gain is not veryimpressive. (2.3->2.6Mib/s)

        */

       cached= 0;

這裡需要注意的就是raw,如果是MTD_OOB_RAW,那麼不會做ECC校驗,也不會把ECC碼寫入OOB;

如果是這樣,在read的時候也必須指定是MTD_OOB_RAW,不需要ECC校驗;否則,就會出現我們最開始看到的錯誤;

       if(mtd->ecc_stats.failed - stats.failed)

              return-EBADMSG;

那麼,從這裡的情況來看,我們可能已經找到出錯的原因了;ubi使用了subpage write,而底層nand flash驅動實際上是不支援subpage write的,儘管ubi一次只寫了512位元組,但這個page的其他部分已經不能再次寫入新的資料了。

從Nand_base.c(drivers\mtd\nand)來看,large page的nand flash,對subpage write的支援是不完善的,限制條件比較多,比如,不能是MLC的nand flash,不能用硬體ECC;

更嚴重的問題是程式碼存在缺陷,在寫入部分data的時候,將其他部分的資料填充為0xff了,然後write整個page,並寫入全部ecc碼到oob,也許這就是前面ecc校驗出錯的原因吧。

nand_do_write_ops()

              /*Partial page write ? */

memset(chip->buffers->databuf, 0xff, mtd->writesize);

                     memcpy(&chip->buffers->databuf[column],buf, bytes);

因此,我想到的解決辦法就是在nand驅動中禁止subpage write。

第一步,在chip options中增加NAND_NO_SUBPAGE_WRITE;

static struct davinci_nand_pdatadavinci_nand_data = {

       .options         = NAND_USE_FLASH_BBT|NAND_NO_SUBPAGE_WRITE,

然後重新編譯下載kernel,但問題依舊;

[email protected]:~# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    129024 bytes

UBI: smallest flash I/O unit:    2048

UBI: sub-page size:              512

UBI: VID header offset:          512 (aligned 512)

心想很奇怪,為什麼 sub-page size還是512?

回頭檢視程式碼,想看看sub page size是怎樣計算出來的,

 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
     !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
  switch(chip->ecc.steps) {
  case 2:
   mtd->subpage_sft = 1;
   break;
  case 4:
  case 8:
  case 16:
   mtd->subpage_sft = 2;
   break;
  }
 }
 chip->subpagesize = mtd->writesize >> mtd->subpage_sft;

可是我已經給options增加了NAND_NO_SUBPAGE_WRITE啊?有些懷疑,我就在此處加了列印log,果然是這裡出了問題,

chip->options = 0x10101.

mtd->subpage_sft = 0.

chip->subpagesize = 512.

#define NAND_NO_SUBPAGE_WRITE    0x00000200

可是,這裡的options 明明是不對的!那我設定的NAND_NO_SUBPAGE_WRITE在哪裡丟掉了?

在下面的函式中有對chip->options賦值改變;

nand_get_flash_type()

              printk(KERN_INFO"nand_get_flash_type 1, chip->options = 0x%x.\n",chip->options);

       /*Get chip options, preserve non chip based options */

       chip->options &= ~NAND_CHIPOPTIONS_MSK;

       printk(KERN_INFO"nand_get_flash_type 2, chip->options = 0x%x.\n",chip->options);   

       chip->options|= type->options & NAND_CHIPOPTIONS_MSK;

       printk(KERN_INFO"nand_get_flash_type 3, chip->options = 0x%x.\n",chip->options);

       /*

        * Set chip as a default. Board drivers canoverride it, if necessary

        */

       chip->options|= NAND_NO_AUTOINCR;

       /*Check if chip is a not a samsung device. Do not clear the

        * options for chips which are not having anextended id.

        */

       if(*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)

              chip->options&= ~NAND_SAMSUNG_LP_OPTIONS;

       printk(KERN_INFO"nand_get_flash_type 4, chip->options = 0x%x.\n",chip->options);

nand_get_flash_type 1,chip->options = 0x10200.

nand_get_flash_type 2,chip->options = 0x10000.

nand_get_flash_type 3,chip->options = 0x1011c.

nand_get_flash_type 4,chip->options = 0x10101.

問題出在這裡,紅色的程式碼!

/* Mask to zero out thechip options, which come from the id table */

#defineNAND_CHIPOPTIONS_MSK (0x0000ffff &~NAND_NO_AUTOINCR)

/* Chip can not autoincrement pages */

#define NAND_NO_AUTOINCR  0x00000001

找到問題了,解決辦法就有了,註釋掉紅色的那行程式碼,就是他把NAND_NO_SUBPAGE_WRITE給丟掉了。

//chip->options &=~NAND_CHIPOPTIONS_MSK;

再重新編譯下載kernel,問題搞定了!

再次啟動開發板,載入ubi,一切正常了。

[email protected]:/# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    126976 bytes

UBI: smallest flash I/O unit:    2048

UBI: VID header offset:          2048 (aligned 2048)

UBI: data offset:                4096

UBI: attached mtd3 to ubi0

UBI: MTD device name:            "filesystem1"

UBI: MTD device size:            512 MiB

UBI: number of good PEBs:        4096

UBI: number of bad PEBs:         0

UBI: max. allowed volumes:       128

UBI: wear-leveling threshold:    4096

UBI: number of internal volumes: 1

UBI: number of user volumes:     1

UBI: available PEBs:             3639

UBI: total number of reserved PEBs:457

UBI: number of PEBs reserved for badPEB handling: 40

UBI: max/mean erase counter: 2/1

UBI: image sequence number: 0

UBI: background thread"ubi_bgt0d" started, PID 1483

UBI device number 0, total 4096 LEBs(520093696 bytes, 496.0 MiB), available 3639 LEBs (462065664 bytes, 440.7 MiB),LEB size 126976 bytes (124.0 KiB)

[email protected]:/# mount -tubifs  ubi0_0 /mnt/nand/ -o sync

UBIFS: mounted UBI device 0, volume0, name "rootfs"

UBIFS: file system size:   51171328 bytes (49972 KiB, 48 MiB, 403 LEBs)

UBIFS: journal size:       2539520 bytes (2480 KiB, 2 MiB, 20 LEBs)

UBIFS: media format:       w4/r0 (latest is w4/r0)

UBIFS: default compressor: lzo

UBIFS: reserved for root:  2416947 bytes (2360 KiB)

[email protected]:/# df

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/root             39544232  16239820 21295632  43% /

none                      1024        24     1000   2% /dev

tmpfs                    16384        20    16364   0% /var/volatile

tmpfs                    21760         0    21760   0% /dev/shm

tmpfs                    16384         0    16384   0% /media/ram

ubi0_0                   45528      1528    41640   4% /mnt/nand

最後,總結下,就是要禁止nand flash驅動裡面的subpage write,讓 chip->subpagesize == mtd->writesize 就好了。

這是我的解決辦法。如果有人要使用subpage write,那麼一定要保證你的讀寫邏輯是正確的,要麼不用ecc,要麼各個subpage的ecc都應是正確的。

http://www.61ic.com/Article/DaVinci/TMS320DM3x/201307/49496.html

相關推薦

ubi移植flash替換問題

我在用TI的dm368開發板,kernel是2.6.32.17,預設的flash檔案系統是jffs2,但是jffs2在大分割槽下,mount速度很慢,而且佔用ram較多,因此,我想使用ubifs看看效能是否會更好些。 ubifs的原理和配置過程,很多網頁都有介紹的,我給一個

嵌入式Linux截圖工具gsnap移植分析【轉】

ram creat 嵌入式linux mbed 生活 rip 改變 因此 sig 轉自:http://blog.csdn.net/lu_embedded/article/details/53934184 版權聲明:開心源自分享,快樂源於生活 —&mdash

替換元素替換元素

object ext input wan tro tex AR 非替換元素 標簽 替換元素: 替換元素是瀏覽器根據其標簽的元素與屬性來判斷顯示具體的內容。 比如:<input /> type="text" 的是,這是一個文本輸入框,換一個其他的時候,瀏覽器顯示就

<03>labview winCE的程序移植界面開發

soft 兼容性 執行 虛擬 模擬器 text exe wince6.0 lan 任務布置:labview與winCE開發 要求一:學會TouchPane的環境配置,建立調試通道;要求二:掌握觸控屏幕界面優化; 正文:  今天介紹labview虛擬儀器軟件中 TouchP

STemwin5.xx底層驅動移植優化 ------ 編寫自定義EmWin Driver參考

首先得說一下為什麼要用STemwin;很多人搞嵌入式的同志應該都想有一個自己的開發環境,每個功能每個模組都自己寫;但是到最後發現無從下手,寫出來的程式碼效率也並不高,因為腦袋裡就沒有這些模組或者功能執行的模式。就像很多人說的“你再怎麼寫,也超不過現有的成熟技術,除非你學會了,在做一些昇華”。 S

【Linux】程序等待程序替換

程序的銷燬     1.釋放資源     2.記賬資訊     3.將程序狀態設定成殭屍狀態     4.轉儲存排程 程序終止的方法     正常退出         1.exit  (C庫函式)  exit函式要先執行一些清除操作,然後才將控制權交給核心          

【dsPIC33E】Bootloader(一)Bootloader的介紹Flash結構

對於嵌入式開發而言,Bootloader幾乎與作業系統同等重要,它可以讓我們擺脫MCU官方工具,定製自己的燒錄工具,不僅提高產品辨識度,同時也大大減少了對外引腳數量(例如相容通訊的Uart或CAN等,而不需要另外接JTAG)。 要開發Bootloader,相對於普通程式,是有一定難度的,這其

環境隔離屬性替換

環境隔離的意義 不同環境下屬性值可能不同,比如開發環境和測試環境的資料庫連線的配置不同。 因此需要環境隔離機制,指定不同的環境。 maven環境隔離與屬性替換 <resources>與<profile>標籤共同定義不同的環境 <resources>指定配置檔案,&l

Linux基礎學習——Shell基礎——Bash變數—數值運算運算子和變數測試內容替換

一、數值運算與運算子: 思考引入: [[email protected] sh]# aa=11 [[email protected] sh]# bb=22 [[email protected] sh]# cc=$aa+$bb [[email pro

使MFC變漂亮一:MFCFlash互動示例

現在使用者越來越注重軟體的美觀,而應用程式給開發者提供的只是很強的控制力,在美觀方面相對較弱。多媒體的發展正是滿足了人們的感觀視覺,所以自然想到應用程式與多媒體的結合。Flash給應用程式提供了一個外部連線點事件FSCommondShockwave,應用程式可以通過它來實現事件,實現應用與多媒體互

Android系統移植平臺開發(五)- 編譯Android原始碼

2.3編譯Android原始碼 Android原始碼體積非常龐大,由Dalvik虛擬機器、Linux核心、編譯系統、框架程式碼、Android定製C庫、測試套件、系統應用程式等部分組成,在編譯Android原始碼之前,必須要先掌握Android原始碼的組成。 2.3.1An

Android系統移植平臺開發(八)- HAL Stub框架分析

HAL stub的框架比較簡單,三個結構體、兩個常量、一個函式,簡稱321架構,它的定義在:@hardware/libhardware/include/hardware/hardware.h@hardware/libhardware/hardware.c/* 每一個硬體都通

Android系統移植除錯之-------)如何修改Android系統預設顯示

1、首先解決【設定】介面預設顯示【開發者選項】的問題 檢視原始碼:packages/apps/Settings/src/com/android/settings/SettingsActivity.java 在updateTilesList(List target)方法中,可以找到【開發

QR code二維碼簡介及Qrencode庫的移植使用

現在生活中,二維碼可以說是無處不在,微信掃碼支付,支付寶掃碼支付,就連貼小廣告的都帶上了二維碼了。之前一直想去了解一下,還是太懶了,就沒去,現在專案中需要用到這東西,正好藉此機會瞭解一下。 上網一查,原來二維碼的還有很多種。下表是一個簡單的介紹: 二維碼的優點突出,

Linux晶片級移植底層驅動(基於3.7.4核心)

1.   SoC Linux底層驅動的組成和現狀 為了讓Linux在一個全新的ARM SoC上執行,需要提供大量的底層支撐,如定時器節拍、中斷控制器、SMP啟動、CPU hotplug以及底層的GPIO、clock、pinctrl和DMA硬體的封裝等。定時器

Linux晶片級移植底層驅動(基於3.7.4核心)(GPIO&&pinctrl&&clk)

6.   GPIO驅動 在drivers/gpio下實現了通用的基於gpiolib的GPIO驅動,其中定義了一個通用的用於描述底層GPIO控制器的gpio_chip結構體,並要求具體的SoC實現gpio_chip結構體的成員函式,最後透過gpiochip_add

Android系統移植平臺開發(七)- 初識HAL

1.      HAL的module與stubHAL(Hardware AbstractLayer)硬體抽象層是Google開發的Android系統裡上層應用對底層硬體操作遮蔽一個軟體層次,說白了,就是上層的應用不用關心底層硬體具體如何工作的,只要向上層提供一個統一的介面即可

Linux之變數引用命令替換

轉自https://www.linuxidc.com/Linux/2015-05/117259.htm在bash指令碼編寫中,我們時常需要引用變數與替換命令,為規範操作,現對其做簡單的總結說明。引用引用就是指將字串用引用符號括起來,以防止特殊字元被shell指令碼解釋為其他意

【原創】IP攝像頭技術縱覽(五)---網路攝像頭初試—mjpg-streamer移植部署

【原創】IP攝像頭技術縱覽(五)—網路攝像頭初試—mjpg-streamer移植與部署 本文屬於《IP攝像頭技術縱覽》系列文章之一: Author: chad Mail: [email protected] 1、vgrabbj、spacv

linux核心移植編譯

在瞭解了核心及其相關知識之後,就要著手核心移植的實驗了。 使用make menuconfig出現問題請移步make: *** 沒有規則可以建立目標“menuconfig”。 停止。   Linux核心移植與編譯 1.linux核心的下載 實驗開始之前,你需要自行下載li