2014-01-10 59 views
7

在嵌入式環境中(使用MSP430),我看到了由於對非易失性存儲器的部分寫入而導致的一些數據損壞。這似乎是由寫入過程中的功耗(FRAM或信息段)造成的。如何在斷電期間防止「部分寫入」數據損壞?

我使用CRC驗證存儲在這些位置的數據。

我的問題是,什麼是防止這種「部分寫入」腐敗的正確方法?目前,我修改了我的代碼以寫入兩個單獨的FRAM位置。所以,如果一個寫入被中斷導致無效的CRC,另一個位置應該保持有效。這是常見的做法嗎?我是否需要爲任何非易失性存儲器實現這種雙重寫入行爲?

回答

6

一個簡單的解決方案是維護兩個版本的數據(在閃存的單獨頁面中),當前版本和以前的版本。每個版本具有包含序列號的報頭,並且確認該序列號的字 - 只需將1的例如序列號的補體:

--------- 
| seq | 
--------- 
| ~seq | 
--------- 
|  | 
| data | 
|  | 
--------- 

關鍵的是,當數據被寫入所述seq~seq字寫最後

在啓動時你閱讀具有最高有效序列號(佔環繞也許 - 尤其是對於短序列字)的數據。當您寫入數據時,您會覆蓋並驗證最早的塊。

只要CRC寫入最後一個,您已經使用的解決方案是有效的,但它缺乏簡單性,並且可能不需要或不需要CRC計算開銷。

在FRAM上,您無需擔心耐久性,但這是閃存和EEPROM的問題。在這種情況下,我使用回寫式高速緩存方法,其中數據保存在RAM中,並且在修改時啓動或重新啓動計時器(如果計時器已經運行) - 計時器到期時寫入數據 - 這可以防止突發寫入從抖動內存開始,即使在FRAM上也很有用,因爲它最大限度地減少了數據寫入的軟件開銷。

+0

我看到如何在某些情況下使用seq和〜seq而不是CRC。但對於Flash而言,在我看來,CRC在內存塊不好的情況下會有所幫助? – schumacher574

+0

當然,除非寫入時由於內存塊不良而導致的寫入失敗,否則會阻止seq和〜seq被寫入,並阻止在啓動時讀取數據。 – schumacher574

+1

在我的實現中,單獨的數據項分別驗證;重要的是單個數據項失敗並不會導致所有數據被丟棄。這裏解決的問題具體是不完全寫入檢測而不是數據損壞。如果您想要將整塊數據驗證和不完整的寫保護結合起來,那麼CRC是一條可行的路線。 – Clifford

5

我們的工程團隊對這些問題採取雙管齊下的方法:用硬件和軟件解決問題!

第一種是二極管和電容器配置,在欠壓時提供幾毫秒的功率。如果我們注意到我們已經失去了外部力量,我們會阻止代碼進入任何非違規寫入。其次,我們的數據對於操作來說尤其重要,它經常更新,我們不想磨損我們的非侵害閃存存儲器(它只支持很多寫操作),因此我們實際上將數據存儲在16次使用CRC碼閃爍並保護每條記錄。在啓動時,我們找到最新的有效寫入,然後開始擦除/寫入循環。

自從實施我們坦率的偏執系統以來,我們從未見過數據損壞。

更新:

我要指出,我們的閃光燈外部對我們的CPU,所以CRC可以幫助驗證數據是否有CPU和閃存芯片之間的通信故障。此外,如果我們連續發生幾次故障,多次寫入可以防止數據丟失。

+0

對於Flash而言,多個副本很重要,但在FRAM設備上,由於它具有無限的續航能力,因此只需要兩個副本即可。即使在Flash上​​,根據更新模式和頻率,寫回緩存也可以滿足要求。 – Clifford

+0

在硬件方面的好建議。不幸的是,我目前的項目太過於要求改變,但這對於未來的項目肯定是需要考慮的事情。 – schumacher574

+0

對不起,我的經驗不足,但是通過硬件設置,當外部電源丟失時,是否會收到中斷? – schumacher574

4

我們已經使用了類似於克利福德的答案,但寫在一個寫操作。你需要兩份數據並在它們之間交替。使用遞增的序列號,以便有效的一個位置具有偶數序列號,並且有一個奇數序列號。 (如果你能在一個寫命令)

寫這樣的數據:

--------- 
| seq | 
--------- 
|  | 
| data | 
|  | 
--------- 
| seq | 
--------- 

當你讀這回確保兩個序列號都是一樣的 - 如果他們不那麼數據是無效的。在啓動時閱讀兩個位置,並計算出哪一個更近(考慮到序列號翻轉)。

0

總是以某種協議存儲數據,如START_BYTE,要寫入的總字節數,END BYTE。 寫入外部/內部存儲器之前,請務必檢查POWER MONITER寄存器/ ADC。 如果你的數據損壞,END字節也會損壞。因此,在整個協議驗證之後,該條目將不會變更。 校驗和不是一個好主意,如果你想在你的協議中包含CRC,你可以選擇CRC16而不是這個。

相關問題