2010-08-23 100 views
9

我最近確定需要將不經常更新的配置變量存儲在微控制器的EEPROM中。添加狀態,本程序將立即迫使人們擔心安全地存儲和訪問EEPROM

  • 檢測EEPROM未初始化的數據(即第一次啓動),
  • 轉換或無效舊固件版本的數據,並
  • 解決多重結構,每個固件更新都可能會增長。

廣泛的谷歌搜索只發現了一篇文章,地址keeping your EEPROM data valid through firmware updates。有沒有人使用過這篇文章中討論的方法?有更好的替代方法嗎?

回答

7

就我個人而言,我更喜歡「標籤表格」格式。

在這種格式中,您的數據被分成一系列「表格」。每個表格都有一個標題,它遵循可預測的格式和可根據需要更改的正文。

這裏是什麼樣的一個表看起來像一個例子:

Byte 0: Table Length (in 16-bit words) 
Byte 1: Table ID  (used by firmware to determine what this data is) 
Byte 2: Format Version (incremented every time the format of this table changes) 
Byte 3: Checksum  (simple sum-to-zero checksum) 
Byte 4: Start of body 
... 
Byte N: End of body 

我不是存儲大量的數據,所以我用一個字節在標題中的每個領域。只要你不改變它,你可以使用任何你需要的尺寸。數據表被一個接一個地寫入EEPROM中。

當您的固件需要從EEPROM讀取數據時,它會從第一個表開始讀取。如果固件識別了表ID並且支持列出的表格版本,則它將數據加載到表格的主體之外(當然,在驗證校驗和之後)。如果ID,版本或校驗和不檢出,則簡單地跳過該表。長度字段用於查找鏈中的下一個表。當固件發現長度爲零的表時,它知道它已經達到數據的末尾,並且沒有更多的表要處理。我發現這種格式很靈活(我可以將任何類型的數據添加到表格主體中)和健壯的(保持頭部格式不變,數據表格將兼容前向和後向)。

有幾個注意事項,儘管它們不是太繁重。首先,您需要確保您的固件可以處理重要數據不在表格中或正在使用不受支持的格式版本的情況。您還需要將EEPROM存儲區的第一個字節初始化爲零(以便在第一次啓動時,您不會開始加載垃圾,認爲它是數據)。由於每個表格都知道它的長度,所以可以擴大或縮小表格;但是,爲了確保沒有「漏洞」(如果整個錶鏈不適合您設備的內存,那麼這個過程可能很煩人),您必須移動表格存儲區的其餘部分。就我個人而言,我並沒有發現任何這些問題是很大的問題,而且使用其他一些數據存儲方法可以省去很多麻煩。

+0

這聽起來像是一個很好的解決方案來處理固件版本之間表格大小的變化。除了複製數據之外,您是否有任何建議讓它能夠容忍中間寫入功耗? – 2010-08-23 22:45:44

+2

用無效校驗和寫整個表,然後(在單獨的事務中)返回並寫入正確的校驗和。如果在寫入過程中出現問題,讀取數據時校驗和就會出錯。 – bta 2010-08-24 18:23:59

+0

這是一個優雅的解決方案,實現起來微不足道:謝謝你的跟進。 – 2010-08-24 22:27:07

3

奈傑爾瓊斯已經介紹了一些在您的參考基礎知識。有很多選擇。

一個替代方案,你有很多空間,存儲鍵值對而不是結構。然後,您可以更新一個值(通過附加它)而不擦除所有內容。這在擦除週期數量有限的設備中非常有用。您的讀取例程將需要從頭開始掃描,每次遇到密鑰時更新值。當然,你的更新例程需要有一個「垃圾回收器」,當內存已滿時啓動。

要處理更新過程中的設備錯誤和電源故障,我們通常會存儲多份數據。最簡單的方法是使用序列號在設備的兩半之間ping通以確定哪一個更新。每個部分的CRC都用於驗證它。這也解決了未初始化的數據問題。

對於鍵值版本,您需要在每次寫入後追加新的CRC。

+0

我真的很喜歡這種方法的理論上的聲音,但不幸的是,沒有足夠的EEPROM來使其可行:ATmega328p上只有1 kB。感謝您的描述! – 2010-08-23 22:46:32