MTD的壞塊管理 一 快速了解MTD的壞塊管理

2021-05-27 12:41:38 字數 4826 閱讀 9085

由於nand flash的現有工藝不能保證nand的memory array在其生命週期中保持效能的可靠,因此在nand晶元出廠的時候,廠家只能保證block 0不是壞塊,對於其它block,則均有可能存在壞塊,而且nand晶元在使用的過程中也很容易產生壞塊。因此,我們在讀寫nand flash 的時候,需要檢測壞塊,同時還需在nand驅動中加入壞塊管理的功能。

nand驅動在載入的時候,會呼叫nand_scan函式,對bad block table的搜尋,建立等操作就是在這個函式的第二部分,即nand_scan_tail函式中完成的。

在nand_scan_tail函式中,會首先檢查struct nand_chip結構體中的options成員變數是否被賦上了nand_skip_bbtscan,這個巨集表示跳過掃瞄bbt。所以,只有當你的driver中沒有為options定義nand_skip_bbtscan時,mtd才會繼續與bbt相關工作,即呼叫struct nand_chip中的scan_bbt函式指標所指向的函式,在mtd中,這個函式指標指向nand_default_bbt函式。

bbt有兩種儲存方式,一種是把bbt儲存在nand晶元中,另一種是把bbt儲存在記憶體中。對於前者,好處是驅動載入更快,因為它只會在第一次載入nand驅動時掃瞄整個nand晶元,然後在nand晶元的某個block中建立bbt,壞處是需要至少消耗nand晶元乙個block的儲存容量;而對於後者,好處是不會耗用nand晶元的容量,壞處是驅動載入稍慢,因為儲存在記憶體中的bbt每次斷電後都不會儲存,所以在每次載入nand驅動時,都會掃瞄整個nand晶元,以便建立bbt。

如果你系統中的nand晶元容量不是太大的話,我建議還是把bbt儲存在記憶體中比較好,因為根據本人的使用經驗,對一塊容量為2g bits的nand晶元,分別採用這兩種儲存方式的驅動的載入速度相差不大,甚至幾乎感覺不出來。

建立bbt後,以後在做擦除等操作時,就不用每次都去驗證當前block是否是個壞塊了,因為從bbt中就可以得到這個資訊。另外,若在讀寫等操作時,發現產生了新的壞塊,那麼除了標誌這個block是個壞塊外,也還需更新bbt。

接下來,介紹一下mtd是如何查詢或者建立bbt的。

1、mtd中與bbt相關的結構體

struct nand_chip中的scan_bbt函式指標所指向的函式,即nand_default_bbt函式會首先檢查struct nand_chip中options成員變數,如果當前nand晶元是ag-and型別的,會強制把bbt儲存在nand晶元中,因為這種型別的nand晶元中含有廠家標註的「好塊」資訊,擦除這些block時會導致丟失壞塊資訊。

接著nand_default_bbt函式會再次檢查struct nand_chip中options成員變數,根據它是否定義了nand_use_flash_bbt,而為struct nand_chip中3個與bbt相關的結構體附上不同的值,然後再統一呼叫nand_scan_bbt函式,nand_scan_bbt函式會那3個結構體的不同的值做不同的動作,或者把bbt儲存在nand晶元中,或者把bbt儲存在記憶體中。

在struct nand_chip中與bbt相關的結構體如下:

struct nand_chip ;

bbt指向一塊在nand_default_bbt函式中分配的記憶體,若options中沒有定義nand_use_flash_bbt,mtd就直接在bbt指向的記憶體中建立bbt,否則就會先從nand晶元中查詢bbt是否存在,若存在,就把bbt的內容讀出來並儲存到bbt指向的記憶體中,若不存在,則在bbt指向的記憶體中建立bbt,最後把它寫入到nand晶元中去。

bbt_td、bbt_md和badblock_pattern就是在nand_default_bbt函式中賦值的3個結構體。它們雖然是相同的結構體型別,但卻有不同的作用和含義。

其中bbt_td和bbt_md是主bbt和映象bbt的描述符(映象bbt主要用來對bbt的update和備份),它們只在把bbt儲存在nand晶元的情況下使用,用來從nand晶元中查詢bbt。若bbt儲存在記憶體中,bbt_td和bbt_md將會被賦值為null。

badblock_pattern就是壞塊資訊的pattern,其中定義了壞塊資訊在oob中的儲存位置,以及內容(即用什麼值表示這個block是個壞塊)。

通常用1或2個位元組來標誌乙個block是否為壞塊,這1或2個位元組就是壞塊資訊,如果這1或2個位元組的內容是0xff,那就說明這個block是好的,否則就是壞塊。對於壞塊資訊在nand晶元中的儲存位置,small page(每頁512 byte)和big page(每頁2048 byte)的兩種nand晶元不盡相同。一般來說,small page的nand晶元,壞塊資訊儲存在每個block的第乙個page的oob的第六個位元組中,而big page的nand晶元,壞塊資訊儲存在每個block的第乙個page的oob的第1和第2個位元組中。

我不能確定是否所有的nand晶元都是如此布局,但應該絕大多數nand晶元是這樣的,不過,即使某種nand晶元的壞塊資訊不是這樣的儲存方式也沒關係,因為我們可以在badblock_pattern中自己指定壞塊資訊的儲存位置,以及用什麼值來標誌壞塊(其實這個值表示的應該是「好塊」,因為mtd會把從oob中壞塊資訊儲存位置讀出的內容與這個值做比較,若相等,則表示是個「好塊」,否則就是壞塊)。

bbt_td、bbt_md和badblock_pattern的結構體型別定義如下:

struct nand_bbt_descr ;

options:bad block table或者bad block的選項,可用的選擇以及各選項具體表示什麼含義,可以參考。

pages:bbt專用。在查詢bbt的時候,若找到了bbt,就把bbt所在的page號儲存在這個成員變數中。若沒找到bbt,就會把新建立的bbt的儲存位置賦值給它。因為系統中可能會有多個nand晶元,我們可以為每一片nand晶元建立乙個bbt,也可以只在其中一片nand晶元中建立唯一的乙個bbt,所以這裡的pages是個維數為nand_max_chips的數值,用來儲存每一片nand晶元的bbt位置。當然,若只建立了乙個bbt,那麼就只使用pages[0]。

offs、len和pattern:mtd會從oob的offs中讀出len長度的內容,然後與pattern指標指向的內容做比較,若相等,則表示找到了bbt,或者表示這個block是好的。

veroffs和version:bbt專用。mtd會從oob的veroffs中讀出乙個位元組的內容,作為bbt的版本值儲存在version中。

maxblocks:bbt專用。mtd在查詢bbt的時候,不會查詢nand晶元中所有的block,而是最多查詢maxblocks個block。

2、bbt儲存在記憶體中時的工作流程

前文說過,不管bbt是儲存在nand晶元中,還是儲存在記憶體中,nand_default_bbt函式都會呼叫nand_scan_bbt函式。

nand_scan_bbt函式會判斷bbt_td的值,若是null,則表示bbt儲存在記憶體中,它就在呼叫nand_memory_bbt函式後返回。nand_memory_bbt函式的主要工作就是在記憶體中建立bbt,其實就是呼叫了create_bbt函式。

create_bbt函式的工作方式很簡單,就是掃瞄nand晶元所有的block,讀取每個block中第乙個page的oob內容,然後根據oob中的壞塊資訊建立起bbt,可以參見上節關於struct nand_bbt_descr中的offs、len和pattern成員變數的解釋。

3、bbt儲存在nand晶元時的工作流程

相對於把bbt儲存在記憶體中,這種方式的工作流程稍顯複雜一點。

nand_scan_bbt函式首先從nand晶元中讀取bbt的內容,它讀取的方式分為兩種:

其一是呼叫read_abs_bbts函式直接從給定的page位址讀取,那麼這個page位址在什麼時候指定呢?就是在你的nand driver中指定。前文說過,在struct nand_chip結構體中有兩個成員變數,分別是bbt_td和bbt_md,mtd為它們附上了default的值,但是你也可以根據你的需要為它們附上你自己定義的值。假如你為bbt_td和bbt_md的options成員變數定義了nand_bbt_abspage,同時又把你的bbt所在的page位址儲存在bbt_td和bbt_md的pages成員變數中,mtd就可以直接在這個page位址中讀取bbt了。值得一提的是,在實際使用時一般不這麼幹,因為你不能保證你儲存bbt的那個block就永遠不會壞,而且這樣也不靈活;

其二是呼叫那個search_read_bbts函式試著在nand晶元的maxblocks(請見上文關於struct nand_bbt_descr中maxblocks的說明)個block中查詢bbt是否存在,若找到,就可以讀取bbt了。

mtd查詢bbt的過程為:如果你在bbt_td和bbt_md的options 成員變數中定義了 nand_bbt_lastblock,那麼mtd就會從nand晶元的最後乙個block開始查詢(在default情況下,mtd就是這麼幹的),否則就從第乙個block開始查詢。

與查詢oob中的壞塊資訊時類似,mtd會從所查詢block的第乙個page的oob中讀取內容,然後與bbt_td或bbt_md中patter指向的內容做比較,若相等,則表示找到了bbt,否則就繼續查詢下乙個block。順利的情況下,只需查詢乙個block中就可以找到bbt,否則mtd最多會查詢maxblocks個block。

若找到了bbt,就把該bbt所在的page位址儲存到bbt_td或bbt_md的pages成員變數中,否則pages的值為-1。

如果系統中有多片nand晶元,並且為每一片nand晶元都建立乙個bbt,那麼就會在每片nand晶元上重複以上過程。

接著,nand_scan_bbt函式會呼叫check_create函式,該函式會判斷是否找到了bbt,其實就是判斷bbt_td或者bbt_md中pages成員變數的值是否有效。若找到了bbt,就會把bbt從nand晶元中讀取出來,並儲存到struct nand_chip中bbt指標指向的記憶體中;若沒找到,就會呼叫create_bbt函式建立bbt(與bbt儲存在記憶體中時情況一樣),同時把bbt寫入到nand晶元中去。

NAND FLASH儲存器的壞塊管理

nand flash儲存器的壞塊管理 hal 硬體適配層管理壞塊,通常工廠在出廠時建立乙個壞塊表標記壞塊。壞塊是那些包含一位或者多位無效位,可靠性不能保證的塊。壞塊可能在出廠時已經存在,也可能在使用過程中產生。有壞塊的裝置和無壞塊的裝置有相同的質量等級和相同的ac,dc特性,乙個壞塊不會影響有效塊的...

對於nandflash壞塊的一些處理辦法

對於壞塊的處理 使用 nandflash,免不了出現個別的壞塊,一般情況下,有一些壞塊是正常的,也不會影響系統的正常啟動執行。如果出現因為壞塊無法啟動 linux 作業系統,那就需要乙個方法來處理這些邏輯上的壞塊 實際上壞塊不一定是真的壞了 邏輯壞塊引起的系統無法啟動,可以使用下面這種方法 開機按下...

uboot和核心的mtd分割槽保持一致

setenv bootargs mem 64m console ttyama0,115200 root dev mtdblock2 rootfstype yaffs2 mtdparts nand flash 1m boot 15m kernel 32m rootfs 16m test mtdpart...