EasyFlash V4.0 ENV 功能設計與實現

聲明:本文檔來源於EasyFlash的倉庫,原作者armink。因github上圖片顯示緩慢,我轉載到了CSDN。
文檔鏈接:EasyFlash V4.0 ENV 功能設計與實現

EasyFlash V4.0 ENV 功能設計與實現

1、爲什麼要開發 V4.0

EasyFlash 是我個人開發的第二款開源軟件,自 2015 年初正式開源出來,至今(2019.02)已經經歷了 4 年多時間。期間有很多其他行業的嵌入式開發者與我取得聯繫,得知他們已經將 EasyFlash 應用於自己的產品上,我心裏也倍感欣慰,可見 EasyFlash 的成熟性已經得到了很多行業的認可。

1.1 功能簡潔,但性能差強人意

大家普遍的感覺是 EasyFlash 功能簡潔,可以很容易的應用於產品上。但隨着技術的演進,大家對於 KV 需求的多樣化,對於 MCU 資源(主要是 RAM)、Flash 存儲資源、Flash 壽命等性能指標越來越高,舊版本的 EasyFlash 在這些方面還是有提升的空間。比如:

1.2 舊版本的痛點

  • 每個存儲在 Flash 上的 ENV 都會在 RAM 中緩存一份,這樣做雖然能夠簡化實現,但確實會佔用很多 RAM 資源;
  • ENV 的值類型只支持字符串,如果想要保存其他類型的值(比如:數組、結構體)就比較麻煩了,雖然我後來爲此又專門開發了 struct2json 開源軟件,但還是不夠便捷;
  • 每次保存 ENV 都需要重新擦寫整個 Flash 扇區,那麼位於扇區尾部未使用的區域始終無法得到利用,降低了 Flash 的使用效率,也就降低了 Flash 的使用壽命

1.3 從 0 開始的 NG 版本

也就是從 2017 年初開始,我便開始準備 EasyFlash 的性能優化工作,結合大家的需求,不斷的整理、迭代設計文檔,也與一些社區愛好者做過非常深入的交流。最終確定下來,如果單純的在原有基礎上進行完善,那麼會有太多的功能實現受到限制,所以乾脆重新開發全新一代 ENV 功能組件,這個版本被命名爲 NG(Next Generation) 版本。

NG 版本差不多在 2017 年底就已經設計完畢,但一直沒時間去開發。後來在親人的支持下,終於利用 2019 年豬年春節的假期,在岳父母家完成了 V4.0 NG 版本的開發(在此感謝岳父母、愛人的支持)。

2、V4.0 的特色有哪些

  • 更小的資源佔用,內存佔用 幾乎爲 0
  • ENV 的值類型支持 任意類型 、任意長度,相當於直接 memcpy 變量至 flash ;
  • ENV 操作效率比以前的模式高,充分利用剩餘空閒區域,擦除次數及操作時間顯著降低;
  • 原生支持 磨損平衡、掉電保護功能 (V4.0 之前需要佔用額外的 Flash 扇區);
  • ENV 支持 增量升級 ,固件升級後 ENV 也支持升級;
  • 支持大數據存儲模式,長度無限制,數據可在多個 Flash 扇區上順序存儲。像腳本程序、音頻等佔用 Flash 超過 1 個扇區的資源也都可以存入 ENV;
  • 支持 數據加密 ,提升存儲的安全性,物聯網時代的必備功能;
  • 支持 數據壓縮 ,減低 Flash 佔用;

3、如何實現

3.1 算法

假定 ENV 分區裏有 4 個扇區,以下將按照操作 ENV 的方式,逐一舉例講解不同操作下,對應的 Flash 狀態及數據變化。

3.1.1 ENV 操作過程1(常規模式)

3.1.1.1 首次使用

在這裏插入圖片描述

首次使用時,EasyFlash 會檢查各個扇區的 header,如果不符合規定的格式將執行全部格式化操作,格式化後,每個扇區的頂部將被存入 header ,負責記錄當前扇區的狀態、魔數等信息。格式化的初始化狀態爲空狀態。

3.1.1.2 添加 KV1、KV2、KV3

在這裏插入圖片描述

在執行添加操作前,會先檢索合適地址來存放即將添加的新 KV,這裏檢索策略主要是:

  • 確定當前選擇的扇區剩餘容量充足
  • 優選選擇正在使用狀態的扇區,最後使用空狀態扇區
  • 檢查新 KV 是否有同名的 KV 存在,存在還需要額外執行刪除舊值的動作

通過上圖可以看出, KV1、KV2 及 KV3 已經被放入 sector1 ,添加後,扇區狀態也被修改爲正在使用

3.1.1.3 修改 KV2 KV3,刪除 KV1,添加 KV4


修改 ENV 時,舊的 ENV 將被刪除,扇區的狀態也將被修改爲髒狀態,然後再執行新增 ENV 的操作。

  • 執行修改 KV2 時,已經存在的 KV2 舊值被修改爲已刪除,sector1 狀態被修改爲髒狀態,此後將 KV2 新值放入 sector1,發現 sector1 已經沒有空間了,sector1 的狀態還會被修改爲已滿狀態;

  • 執行修改 KV3 時,已經存在的 KV3 舊值被修改爲已刪除,sector1 狀態已經爲髒狀態,無需再做修改。經過查找發現 KV3 的新值只能放到 sector2,放到 sector2 後將其修改爲正在使用狀態;

  • 執行刪除 KV1 時,找到 KV1 的位置,將其修改爲已刪除狀態,sector1 狀態已經爲髒狀態,無需再做修改;

  • 執行添加 KV4 時,經過查找在 sector2 找到合適的存儲位置,將其添加後,sector2 狀態已經爲正在使用狀態,無需再做修改。

3.1.1.4 添加 KV5 KV6,觸發 GC

  • 執行添加 KV5 操作,由於 KV5 體積較大,sector2 放不下,所以只能放在一個新扇區 sector3 上,添加後,修改 sector3 狀態爲正在使用
  • 執行添加 KV6 操作,KV6 也只能放在 sector3 下,將其放入 sector 3 後,發現 sector3 空間已滿,所以將其修改已滿狀態。執行完成後,發現整個 ENV 的 4 個扇區只有 1 個狀態爲空的扇區了,這個扇區如果再繼續使用就沒法再執行 GC 操作了,所以此時觸發了 GC 請求;
  • 執行 GC 請求,EasyFlash 會找到所有被標記爲已滿並且爲髒狀態的扇區,並將其內部的 ENV 搬運至其他位置。就這樣 sector1 上的 KV2 被搬運至了 sector2,騰空 sector1 後,又對其執行了格式化操作,這樣整個 ENV 分區裏又多了一個空狀態的扇區。

3.1.2 ENV 操作過程2(開啓大數據存儲模式)

馬上就來……

3.2 數據結構

結合上面的算法不難發現,其實所有的操作都圍繞着 扇區狀態ENV狀態 ,這些狀態將被存放在扇區及 ENV 頭部,並且保證在不擦除扇區數據的前提下進行單向修改,在程序代碼實現上稱這些狀態及其他一些數據信息爲 元數據

除了常規功能外,還有一項重要指標是 EasyFlash 非常看重的,那就是掉電保護能力,相當於在任何操作出現掉電異常,整個 EasyFlash 的容錯能力是否過硬,是否可以進行掉電恢復。像 準備寫入、準備刪除這些中間狀態就是爲了掉電保護功能而設計。

出於後期擴展性的考慮這裏也預留了一些保留屬性,還有一些提前規劃好的狀態及屬性後面將用過多扇區存儲、加密、壓縮功能的實現。

設計完成後,整個 ENV 的數據結構如下圖,該圖最終也可轉換爲對應的結構體。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章