1. 程式人生 > 其它 >快閃記憶體中的鍵值對:無檔案系統 minINI

快閃記憶體中的鍵值對:無檔案系統 minINI

  許多嵌入式系統應用需要以持久的方式儲存某種資料:校準值、設定或日誌資訊。對於較少的資料量,使用外部儲存器或檔案系統是一種過度大材小用。在許多系統中,我使用minINI以“ini-file”的方式儲存鍵值解析,但它需要使用某種檔案系統。minINI很棒,效率很高,使獲取和儲存資料變得非常容易。但對於簡單的情況,單個快閃記憶體頁面或扇區正是我所需要的。相反,直接管理該頁面,為什麼不在沒有檔案系統的情況下使用minINI?

  例如,我使用上面的電路板驅動多達4個不同的步進電機和霍爾感測器。我需要儲存校準偏移量和電機資訊,並且每個電路板的資訊可能不同。這些板通過RS-485匯流排連線,因此每個板都有一個唯一的地址。對於此應用程式,我需要儲存鍵值對(例如,address=0x10)。為此,我使用minINI將資料儲存在內部快閃記憶體的一頁中,因此不需要檔案系統。

1、概述

  因為 minINI 處理檔案,所以它需要某種檔案系統。對於較小的系統或較小的資料量,隨著程式碼大小和資料需求的增加,這增加了複雜性。在本文中,我將介紹一種對 minINI 庫進行無檔案和無檔案系統適配的方法,該方法只需要一個小型且可配置的 RAM 緩衝區以及單個 FLASH 頁面或扇區。這樣,一個非常通用和使用者友好的鍵值儲存可用於小型嵌入式系統,而無需檔案系統。
  該實現可在 GitHub 上找到。

2、.ini檔案

  .ini檔案允許我將資料分組為“部分”和“鍵值”對。下面是一個示例:

[motor0]
name=split-flap 0
offset=30
x=0
 
[motor1]
offset=32

  使用minINI,我可以讀/寫這樣的值。它具有“只讀”模式,在這種模式下,我只能讀取資料。

3、minINI介面

  minINI 架構包括一個“粘合”介面。這樣,它可以很容易地適應不同的檔案系統。以下是 FatFS 的“粘合”實現:

#define INI_FILETYPE    FIL
#define ini_openread(filename,file)   (f_open((file), (filename), FA_READ+FA_OPEN_EXISTING) == FR_OK)
#define ini_openwrite(filename,file)  (f_open((file), (filename), FA_WRITE+FA_CREATE_ALWAYS) == FR_OK)
#define ini_close(file)               (f_close(file) == FR_OK)
#define ini_read(buffer,size,file)    f_gets((buffer), (size),(file))
#define ini_write(buffer,file)        f_puts((buffer), (file))
#define ini_remove(filename)          (f_unlink(filename) == FR_OK)
 
#define INI_FILEPOS                   unsigned long//DWORD
#define ini_tell(file,pos)            (*(pos) = f_tell((file)))
#define ini_seek(file,pos)            (f_lseek((file), *(pos)) == FR_OK)

4、FLASH介面

  我們的想法是新增一個新的“粘合”,它不需要檔案系統。相反,它直接讀取和寫入快閃記憶體,並模仿檔案系統。
  這有一個限制:僅支援單個“ini檔案”。該限制可以很容易地擴充套件到支援多個“檔案”,但我真的沒有看到這種需求,至少在我的應用程式中沒有。

5、配置

  配置是使用配置巨集(請參見軟體配置的不同方式)。下面是一個示例配置:

  這樣就可以配置快閃記憶體。資料大小巨集用於限制資料大小,以減少用於寫入快閃記憶體的記憶體緩衝區的數量。
需要從可用於連結器的快閃記憶體數量中減少/排除已使用的快閃記憶體,否則應用程式也可能使用它。以下是如何使用恩智浦MCUXpresso IDE從記憶體對映中減少記憶體:

6、命令列

  該實現包括一個命令列/shell 介面。
  低於只讀配置的狀態:

  “McuMinINI”顯示minINI的“核心”資訊,而“ini”組用於快閃記憶體實現它。
  使用命令列介面,可以檢查或修改資料:

7、用法

  將鍵值對與 minINI 結合使用非常簡單:我可以查詢整數、布林值、浮點值或字串值。下面是獲取裝置儲存地址的示例:

#define NVMC_MININI_FILE_NAME         "settings.ini" /* 'file' name used */
 
/* RS-485 bus settings */
#define NVMC_MININI_SECTION_RS485     "rs485"
#define NVMC_MININI_KEY_RS485_ADDR    "addr" /* long value: RS-485 address */
...
*addr = McuMinINI_ini_getl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, 0x1, NVMC_MININI_FILE_NAME);

  我真正喜歡minINI的是我可以提供預設值(在上面的示例中0x1):如果部分/鍵不存在,它將返回我指定的預設值:這樣預設值就不需要配置區域中的任何空間。
儲存值類似於下面的示例:

McuMinINI_ini_putl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, addr, NVMC_MININI_FILE_NAME);

8、記憶體要求

  當然,每個功能都會帶來一些成本。但在這種情況下,我認為它真的是最小的。
  為了在快閃記憶體中儲存資料,它至少需要一個扇區或快閃記憶體頁。其大小取決於所使用的系統,例如1 kByte(LPC845)或2 KByte(Kinetis K22),具體取決於微控制器。大小配置為McuMinINI_CONFIG_FLASH_NVM_BLOCK_SIZE。
  對於寫入訪問,它需要一個RAM緩衝區來備份和儲存來自FLASH的資料。該金額McuMinINI_CONFIG_FLASH_NVM_MAX_DATA_SIZE配置。最小值為 64 個位元組。根據要儲存的資料量,128 或 256 可能更合理。對於只讀訪問,緩衝區量為零。根據所使用的微控制器和SDK,需要快閃記憶體驅動程式的裝置控制代碼:例如,在Kinetis上,這需要額外的100位元組。對於像LP845這樣的其他產品,不需要手柄,因為ROM例程用於快閃記憶體程式設計。
  在 Kinetis 上,只讀配置會增加大約 6 KB 的程式碼大小(-O0,無優化),而使其讀寫會增加額外的 3 KB (-O0)。新增shell支援會增加額外的1 KB:因此這意味著最多需要10 KB的快閃記憶體,在啟用優化後降至約6 KB。到目前為止,還不到完整的檔案系統支援,很容易是30-50 KB的快閃記憶體。

9、總結

  有了這個用於minINI的附加粘合埠,可以在沒有檔案系統的情況下使用它。這使得它適用於較小的嵌入式系統。它支援只讀和讀寫資料儲存。它使用直接快閃記憶體讀/寫,只有在讀寫配置中,它才需要一個可配置的RAM緩衝區來寫入或擴充套件資料。這樣,就可以輕鬆地將“鍵值”對儲存新增到任何嵌入式系統,而快閃記憶體的成本不到10 KB。
  您可以在GitHub上的McuLib中找到該實現。

連結

英文原文​:Key-Value pairs in FLASH Memory: file-system-less minINI | MCU on Eclipse

歡迎關注: