ESP8266學習筆記(2)——內存分佈及Flash讀寫接口

一、存儲芯片W25Q系列

w25q 系列生產的加工的商家很多,但是裏面的分佈和命名規則都是一樣的。比如華邦的w25q64,spi通訊接口,64就是指 64Mbit 也就是 8M 的容量。而我們平時的8266-12f的 32Mbit 就是 4M 容量。

以 w25q32 爲例,裏面的存儲分佈。w25q32把4M容量分爲了 64 塊,每一塊又分爲 16 個扇區,而每個扇區佔 4K 大小。由此可計算到,w25q32有 32Mbit / 8 * 1024 / 16 / 4 = 64 塊 ,有 64 * 16 = 1024 個扇區。

注:1B=8 Bit ,1KB=1024B ,1MB=1024KB

 

二、ESP8266內存分佈

  • 程序區:代碼編譯生成的 bin 文件,燒錄到 Flash 佔用的區域,請勿改寫
  • 系統參數區: esp_iot_sdk 中底層用於存放系統參數的區域,請勿改寫
  • 用戶參數區:上層應用程序存儲用戶參數的區域。開發者請根據實際使用的 Flash size 設置,可 以參考文檔“2A-ESP8266__IOT_SDK_User_Manual” 中的 “Flash Map” 一章。

2.1 Non-FOTA

2.2 FOTA

 

更多圖查看:

鏈接:https://blog.csdn.net/k7arm/article/details/51812021

 

三、Flash讀寫接口

SPI Flash 接口位於 /ESP8266_NONOS_SDK/include/spi_flash.h

system_param_xxx 接口位於 /ESP8266_NONOS_SDK/include/user_interface.h

3.1 spi_flash_erase_sector

3.2 spi_flash_write

注意:

  • Flash 請先擦再寫。
  • Flash 讀寫必須 4 字節對齊。

示例代碼:   

#define N 0x7C

uint32 data[M];

spi_flash_erase_sector (N);

spi_flash_write (N*4*1024, data, M*4);

3.3 spi_flash_read

3.4 system_param_save_with_protect

3.5 system_param_load

示例代碼:

/***************Flash 讀寫結構體聲明***************/

struct esp_platform_saved_param {

// 服務器參數
uint8 devkey[40];
uint8 token[40];
uint8 activeflag;
char server_domain[64];
ip_addr_t server_ip;
int server_port;

// AP參數
uint8 ssid[32];
uint8 password[64];
int authmode;
uint8 ssid_hidden;

// 填充
uint8 pad[2];
};

/***************Flash 讀寫結構體定義***************/
struct esp_platform_saved_param esp_param;

/***************Flash 寫入數據***************/
system_param_save_with_protect(0x7D, &esp_param, sizeof(esp_param));

/***************Flash 讀出數據***************/
system_param_load(0x7D, 0, &esp_param, sizeof(esp_param)); 

 

四、Flash讀寫保護

4.1 Espressif Flash讀寫保護示例

4.1.1 實現原理

Espressif Flash 讀寫保護示例,使用 三個 sector(扇區)實現(每 sector 4KB),提供 4KB 的可靠存儲空間。 將 sector 1 和 sector 2 作爲數據 sector,輪流讀寫,始終分別存放“本次”數據和“前一次”數據, 確保了至少有一份數據存儲安全;sector 3 作爲 flag sector,標誌最新的數據存儲 sector。

保護機制如下:

  1. 初始上電時,數據存儲在 sector 2 中,從 sector 2 中將數據讀到 RAM。
  2. 第一次寫數據時,將數據寫入 sector 1。此時若突然掉電,sector 1寫入失敗,sector 2 & 3數據未改變;重新上電時,仍是從 sector 2 中 讀取數據,不影響使用。
  3. 改寫 sector 3,將標誌置爲 0,表示數據存於 sector 1。此時若突然掉電,sector 3 寫入失敗,sector 1 & 2 均存有一份完整數據;重新上電時,因 sector 3 無有效 flag,默認從 sector 2 中讀取數據,則仍能正常使用,只是未能包含掉電前對 sector 1 寫入的數據。
  4. 再一次寫數據時,先從 sector 3 讀取 flag,若 flag 爲0,則上次數據存於 sector 1,此次應將數據寫入 sector 2;若 flag 爲非 0,則認爲上次數據存於 sector 2,此次應將數據寫入 sector 1。此時若寫數據出錯,請參考步驟 2、 3的說明,同理。
  5. 寫入 sector 1(或 sector 2)完成後,纔會寫 sector 3,重置 flag。注意:只有數據扇區(sector 1或 sector 2)寫完之後,纔會寫 flag sector(sector 3),這樣即使 flag sector 寫入出錯,兩個數據扇區都已存有完整數據內容,目前默認會讀取 sector 2。

4.1.2 軟件示例

在 IOT_Demo 中,使用 0x3C000 開始的 4 個 sector(每 sector 4KB),作爲用戶參數存儲區。 其中 0x3D000、 0x3E000、 0x3F000 這 3 個 sector 實現了讀寫保護的功能,並存儲了應用級參數 esp_platform_saved_param

圖中“有讀寫保護的存儲區”, IOT_Demo 中建議調用 system_param_load 和 system_param_save_with_protect 進行讀寫。

system_param_load - 讀 Flash 用戶參數區數據

system_param_save_with_protect - 寫 Flash 用戶參數區數據

參數 struct esp_platform_saved_param 定義了目前樂鑫存儲於 Flash 的用戶應用級數據,用戶只需將自己要存儲的數據添加到結構體 struct esp_platform_saved_param 後面,調用上述兩個函數進行 Flash 讀寫即可。

4.2 Flash讀寫保護參考一

方法: “輪流寫入”+“首部記數”+“尾部校驗”

佔用空間: 2 個 sector,共計 8KB;提供 4KB 的帶數據保護存儲空間。

原理:

仍然 採用兩個數據 sector 輪流寫入來做備份數據保護,只是不再專門設立 flag sector。 記一個 counter,寫入數據 sector 的首部,每次寫入時計數加一,用記數比較來判別下一次應寫入哪個 sector;在數據尾部加入校驗碼(CRC、checksum 等任一種校驗方式),用以驗證數據的完整性。

(1) 假設初次上電,數據存儲在 sector A, sector A 的記數爲初始值 0xFF,從 sector A 將數據讀入 RAM。

(2) 第一次數據寫入 sector B,則在 sector B 首部信息中記錄 counter 爲 1,尾部加入校驗碼。

(3) 再次寫入數據時,先分別讀取 sector A/B 的 counter 值進行比較,此次應當將數據寫入 sector A, sector A 首部記錄 counter 爲 2,尾部加入校驗碼。

(4) 若發生突然掉電,當前正在寫入的 sector 數據丟失,重新上電時,先比較 sector A/B 的 counter 值,讀取 counter 值較大的完整 sector,根據 sector 尾部的校驗碼進行校驗,當前 sector 數據是否可靠,若校驗通過,則繼續執行;若校驗失敗,則讀取另一個 sector 的數據,校驗,並執行。

4.3 Flash讀寫保護參考二

方法: “備份扇區”+“尾部校驗”

佔用空間: 2 個 sector,共計 8KB;提供 4KB 的帶數據保護存儲空間。

原理:

始終往 sector A 讀寫數據,每次寫入時,同樣寫一遍 sector B 作爲 sector A 的備份扇區,每個 sector 尾部均加入校驗碼(CRC、checksum等任一種校驗方式)。

(1) 從 sector A 讀取數據,並進行校驗。

(2) 數據寫入 sector A,尾部爲校驗碼。

(3) sector A 寫入完成後,同樣的數據也寫入 sector B 進行備份。

(4) 若發生突然掉電,當前正在寫入的 sector 數據丟失,重新上電時,先從 sector A 讀取數據,根據尾部的校驗碼進行校驗,sector A 數據是否可靠,若校驗通過,則繼續執行;若校驗失敗,則讀取 sector B 的數據,校驗,並執行。

 


• 由 Leung 寫於 2018 年 9 月 14 日

• 參考:《ESP8266 Flash 讀寫說明》[25l1]

             《ESP8266 Non-OS SDK IoT_Demo 指南》[q878]

             《ESP8266 Non-OS SDK API 參考》[7qq6]

             《Esp8266 進階之路24》

             《ESP8266 Flash》

 

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