读写操作API
基本操作
(1)
spi_flash_erase_sector
功能 擦除 Flash 的某个扇区。 函数定义 SpiFlashOpResult spi_flash_erase_sector (uint16 sec)
参数 uint16 sec
- 扇区号,从0 开始计数,每个扇区大小为4KB
。返回值 SpiFlashOpResult
(2)
spi_flash_write
功能 将数据写入Flash 。
请先调用spi_flash_erase_sector
擦除待写区域,再写入数据。函数定义 SpiFlashOpResult spi_flash_write (uint32 des_addr, uint32 *src_addr, uint32
size)参数 uint32 des_addr
– 写入Flash 的地址,起始位置。uint32 *src_addr
– 写入Flash 的数据指针。uint32 size
– 写入数据的长度,单位:byte。返回值 SpiFlashOpResult
(3)
spi_flash_read
功能 从 Flash 读取数据。 函数定义 SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 * des_addr, uint32 size)
参数 uint32 src_addr
– 读取Flash 的地址,起始位置。
uint32 *des_addr
– 读取Flash 的数据指针。
uint32 size
– 读取数据的长度,单位:byte。返回值 SpiFlashOpResult
(4)返回值
Typedef enum{
SPI_FLASH_RESULT_OK,
SPI_FLASH_RESULT_ERR,
SPI_FLASH_RESULT_TIMEOUT
}SpiFlashOpResult;
注意事项
每个扇区的大小为
4kB
,即4*1024 bytes
。Flash读写数据要以四字节对齐。
Flash要先擦除再写入。
示例代码
/* * 方式一 */ #define LEN 1 //以读写4字节的数据为例 #define SEC 123 //读写的扇区(Sector)号 #define SEC_OFFSET 0 //扇区内偏移量(必须是4的倍数) uint32 write_data[LEN]; uint32 read_data[LEN]; //TODO //Fill the write_data //读取数据 spi_flash_read(SEC*4*1024+SEC_OFFSET, read_data, LEN*4); //写入数据 spi_flash_erase_sector(SEC); spi_flash_write(SEC*4*1024+SEC_OFFSET, write_data, LEN*4); /* * 方式二 */ #define LEN 1 //以读写4字节的数据为例 #define SEC 123 //读写的扇区(Sector)号 #define SEC_OFFSET 0 //扇区内偏移量(必须是4的倍数) uint8 write_data[LEN*4]; uint8 read_data[LEN*4]; //TODO //Fill the write_data //读取数据 spi_flash_read(SEC*4*1024+SEC_OFFSET, (uint32 *)&read_data, LEN*4); //写入数据 spi_flash_erase_sector(SEC); spi_flash_write(SEC*4*1024+SEC_OFFSET, (uint32 *)&write_data, LEN*4);
【总结】读写地址
scr_addr=SEC*4*1024+SEC_OFFSET
Flash地址映射
ESP8266提供了读写Flash的接口,操作很简单,但不能随便找个地方就开始擦除然后写入自己的数据,这样很容易把数据写到不该写入的地方,造成一些潜在的问题,因此难点在于确定读写数据的安全位置。
这里以
8M bits
即1M bytes(1024 bytes)
的Flash为例做以说明,其Flash布局如下。
bin | 烧录地址 | 说明 |
---|---|---|
boot.bin(boot_v1.6.bin) |
0x00000 |
启动程序,SDK 中提供。 |
user1.bin(user1.1024.new.2.bin) |
0x01000 |
主程序,编译代码生成。 |
esp_init_data_default.bin |
0x0fc000 |
初始化射频参数,SDK 中提供。 |
blank.bin |
0x0fe000 |
初始化系统参数,SDK 中提供。 |
[注]上表参考ESP8266 Flash的维基百科的第三节(Layout With OTA)以及实际烧录配置。
程序区 | boot.bin 起始地址0x00000 user1.bin 起始地址0x01000 |
---|---|
系统参数区 | Flash最后4个扇区(即Flash最后16K Bytes ) esp_init_data_default.bin 位于Flash倒数第4个 sectorblank.bin 位于Flash倒数第2个sector |
[注]软件支持云端升级(boot),上表参考自《ESP8266 Flash 读写说明》。
下面的图更加直观地展示了1024KB Flash
的分布情况:
结合这张图,说明两个问题。
[注]对于1024KB
的Flash,可以分为256(1024/4)
个扇区,扇区号为0~255
。
确定各个文件的烧录地址
(1)
boot.bin
,启动程序,烧录地址固定为Flash的开始位置,即0x00000
;(2)
user1.bin
,用户程序,紧跟在boot
之后,boot
占用第0个扇区(4KB
),则user1.bin
的起始地址应为第一个扇区的起始地址:
4096
换算成十六进制就是0x01000
;(3)
esp_init_data_default.bin
,初始化射频参数,位于Flash倒数第4个 sector(即252号扇区
),则烧录地址应为:
1032192
换算成十六进制就是0x0fc000
;(4)
blank.bin
,初始化系统参数,位于Flash倒数第2个sector(即254
号扇区),则烧录地址为:
1040384
换算成十六进制就是0x0fe000
;用户存储数据的安全区域
如果用户程序
user1.bin
小于492KB
,则剩余的空间可以用于存储用户数据;假设用户程序大小为
480KB
,则存储数据可用区域起始地址为:
起始地址为:495616
—->0x79000
,可用空间大小为此后的3个扇区(121号、122号、123号)。[推荐]存储在用户参数区(该区域专门用于上层应用程序存储用户参数),起始扇区号为:
则可用起始地址为:
起始地址为507904
–>0x7C000
,可用此后的4个扇区(124号、125号、126号、127号)。[注]由上述计算可知,用户参数区是与程序区是相连的,因此用户程序大小不能超过
492KB
。
【参考资料】
1. ESP8266 Flash 读写说明
2. ESP8266 Flash