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
更多图查看:
链接:https://blog.csdn.net/k7arm/article/details/51812021
SPI Flash 接口位于 /ESP8266_NONOS_SDK/include/spi_flash.h。
system_param_xxx 接口位于 /ESP8266_NONOS_SDK/include/user_interface.h。
注意:
示例代码:
#define N 0x7C
uint32 data[M];
spi_flash_erase_sector (N);
spi_flash_write (N*4*1024, data, M*4);
示例代码:
/***************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));
Espressif Flash 读写保护示例,使用 三个 sector(扇区)实现(每 sector 4KB),提供 4KB 的可靠存储空间。 将 sector 1 和 sector 2 作为数据 sector,轮流读写,始终分别存放“本次”数据和“前一次”数据, 确保了至少有一份数据存储安全;sector 3 作为 flag sector,标志最新的数据存储 sector。
保护机制如下:
在 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 读写即可。
方法: “轮流写入”+“首部记数”+“尾部校验”
占用空间: 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 的数据,校验,并执行。
方法: “备份扇区”+“尾部校验”
占用空间: 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》