物联网loT从业者物联网相关技术研究ESP8266 WIFI模块 & NodeMCU

ESP8266学习笔记(2)——Flash读写

2018-09-14  本文已影响9人  Leung_ManWah

一、存储芯片W25Q系列

esp8266-12f

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读写接口

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读写保护

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.2 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 读写说明》《ESP8266 Non-OS SDK IoT_Demo 指南》《ESP8266 Non-OS SDK API 参考》

             《Esp8266 进阶之路24》

             《ESP8266 Flash》

上一篇 下一篇

猜你喜欢

热点阅读