最近研究了下nor flash的掉電問題,對nor的掉電有了更多的認識。總結分享以下html
nor flash的物理特性是,寫入以前須要先進行擦除。擦除後數據爲全0xFF,此時寫入操做,其實是將數據從1改爲0。
通常先擦後寫,但實際上擦除後每一個位置是能夠寫入屢次的,只要每次寫入都是讓某些bit從1變0便可。
例如在擦除後數據爲0xFF,此時寫入0x0F,可讀出0x0F,再寫入0x01,可讀出0x01,再寫入0x00,可讀出0x00。
而對於0x00,就沒法再改寫成任何值了,由於此時每一個bit都是0,想要改寫就必須先擦除,讓其恢復到0xFF,再進行寫入改爲目標值。post
在uboot中就有一個利用nor這個特性的例子。當使用了冗餘env功能時,flash上會維護兩份env,咱們記爲envA和envB吧。
既然有兩份env,那就須要一種方式來區分哪份env的數據更新。對此uboot支持幾種策略,其中一種可適用於nor的策略FLAG_BOOLEAN,uboot會在env的頭部結構中,使用了一個字節flags來表示其是否有效。
假設當前A有效,B無效,則A的flags爲0x1,B的flags爲0x0. 讀取時能夠據此判斷哪份env爲新的。
寫入時,uboot會先在ram的buffer中構造好flags爲1的新env數據,再對envB進行擦除和寫入。寫入後flash上兩份env的flags就都是0x1了。接着uboot直接對A的flags的位置寫入0x0,即將本來的0x1不經擦除,直接改寫爲0,這樣就快速地達到將A標記爲無效的目的了。htm
對於nor來講,一次寫入能夠連續寫256 bytes,那若是在中途發生了掉電,再次上電後讀出來的數據會是什麼樣的呢?
這個問題咱們很容易獲得兩種猜想:
假設nor中存在一片buffer,集齊256 bytes後再一次性刷到顆粒中,那麼中途掉電大機率就是徹底沒有寫入,由於數據還在buffer中。也有小几率是正在刷buffer到顆粒中掉電了,那麼這個時候寫入的數據應該是亂序的。
假設nor中沒有維護buffer,每一個bytes的波形接收到以後就寫入固化下來,那麼中途掉電大機率就是部分寫入,並且是順序的,即前面的數據寫入了,後面的數據仍然爲0xFF。blog
實測實際狀況爲假設二所述。
當寫入一筆數據時,nor就是按順序寫入的,掉電後的數據特徵爲前面部分數據是正確數據,後面部分數據是0xFF。先後的交界點並未對齊到256 bytes。
get
從nor flash原廠瞭解到,erase操做其實在flash內部分紅三個步驟:
1)pre-program all "00";
2)erase;
3)post-program all "FF"flash
那麼在擦除過程當中掉電,可能出現的數據特徵就比較多了。it
第一步驟:pre-program all "00";
當收到擦除命令時,首先flash會對這4k寫入全0數據,這個是按前後順序串行寫入的,就理解爲一個正常的寫入全0數據。
若是在這個過程當中掉電,那麼觀察到的數據會是,前半部分的數據爲0x00,後半部分的數據爲原始的數據。狀況跟上面描述的寫入過程掉電同樣。
class
第二步驟:erase
所有寫入0以後,就進行擦除,擦除是會將全部的0都變成0xFF,這個是4k的數據並行進行的,在這個過程當中掉電,能夠看到全部的數據都介於0-0xFF之間,亂七八糟的數據,沒有任何規律。
並行
第三步驟:post-program all "FF"
這一步其實我沒太理解,但從掉電後的數據特徵看,有一種狀態可能跟這一步沒完成有關。
即4k的數據,處於不穩定的0xFF狀態。不穩定的意思是,某次上電讀出來爲全0xFF,從新上電再讀,可能就是夾雜着一些0xFD, 0xBF之類的數據。
im
以上咱們觀察了寫入和擦除中途掉電的數據特徵。
從寫入過程掉電的特徵看,寫入過程掉電可能致使nor僅將部分數據寫入的,致使頭部數據存在但總體數據是不完整的,所以不能簡單依賴頭部結構的MAGIC值來斷定數據是否有效,重要數據須要作完整性校驗。
從擦除過程掉電的特徵看,擦除過程掉電可能致使flash上存在雜亂數據,或者不穩定的全0xFF數據,所以對於全0xFF的數據,寫入以前仍是要先作一次擦除讓nor達到穩定狀態。