内容
Flash
ESP-12F模组的外部Flash,除了储存系统程序、系统参数外,还可以用来存储用户数据,复位/掉电也不会丢失用户数据
Flash的大小、地址等
- ESP-12F模组的外部Flash = 32Mbit = 4MB
- Flash_4MB 的地址 == 0x000 000 ~ 0x3FF FFF
- 扇区编号:0x000 ~ 0x3FF 【Flash扇区 = 4 KB】
注意
- 读/写Flash的地址,不能和系统程序1区冲突。可以放在【0x70 000】地址后
- Flash读写,必须【4个字节】对齐
- 向Flash某扇区写数据前,须先将此扇区擦除。
Flash擦除函数的参数==【扇区编号】!=【字节地址】 - 读/写Flash数据函数的参数==【字节地址】!=【扇区编号】
步骤
- 设置扇区编号
- 擦除扇区【spi_flash_erase_sector(N_Data_FLASH_SEC); //擦除0x77扇区】
- 向扇区写数据【spi_flash_write(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_W_Data, sizeof(A_W_Data));】
- 读取扇区数据【spi_flash_read(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_R_Data, sizeof(A_W_Data));】
效果
代码
头文件
#include "user_config.h" // 用户配置
#include "driver/uart.h" // 串口
//#include "at_custom.h"
#include "c_types.h" // 变量类型
#include "eagle_soc.h" // GPIO函数、宏定义
#include "ip_addr.h" // 被"espconn.h"使用
#include "espconn.h" // TCP/UDP接口
//#include "espnow.h"
#include "ets_sys.h" // 回调函数
//#include "gpio.h"
#include "mem.h" // 内存申请等函数
#include "os_type.h" // os_XXX
#include "osapi.h" // os_XXX、软件定时器
//#include "ping.h"
//#include "pwm.h"
//#include "queue.h"
//#include "smartconfig.h"
//#include "sntp.h"
//#include "spi_flash.h"
//#include "upgrade.h"
#include "user_interface.h" // 系统接口、system_param_xxx接口、WIFI、RateContro
宏定义
#define ProjectName "Flash"
#define SPI_FLASH_SEC_SIZE 4096
全局变量
u16 N_Data_FLASH_SEC = 0X77; //存储数据的扇区编号
u32 A_W_Data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,12,14,15,16}; //写入Flash的数据
u32 A_R_Data[16] = {0}; //缓存读Flash的数据
user_init函数
void ICACHE_FLASH_ATTR user_init(void)
{
u8 C_loop = 0;
uart_init(115200,115200); // 初始化串口波特率
os_delay_us(10000); // 等待串口稳定
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
spi_flash_erase_sector(N_Data_FLASH_SEC); //擦除0x77扇区
// 向Flash写数据(参数1=【字节地址】、参数2=写入数据的指针、参数3=数据长度)
spi_flash_write(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_W_Data, sizeof(A_W_Data));
os_printf("\r\n---------- Write Flash Data OVER ----------\r\n");
//从【0x77 000】地址起,读取16个数据(每个数据占4字节)
spi_flash_read(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_R_Data, sizeof(A_W_Data));
for(C_loop=0; C_loop<16; C_loop++)
{
os_printf("Read Data = %d \r\n",A_R_Data[C_loop]);
delay_ms(10);
}
os_printf("\r\n\r\n------------ user_init OVER ------------\r\n\r\n");
}
整体代码
#include "user_config.h" // 用户配置
#include "driver/uart.h" // 串口
//#include "at_custom.h"
#include "c_types.h" // 变量类型
#include "eagle_soc.h" // GPIO函数、宏定义
#include "ip_addr.h" // 被"espconn.h"使用
#include "espconn.h" // TCP/UDP接口
//#include "espnow.h"
#include "ets_sys.h" // 回调函数
//#include "gpio.h"
#include "mem.h" // 内存申请等函数
#include "os_type.h" // os_XXX
#include "osapi.h" // os_XXX、软件定时器
//#include "ping.h"
//#include "pwm.h"
//#include "queue.h"
//#include "smartconfig.h"
//#include "sntp.h"
//#include "spi_flash.h"
//#include "upgrade.h"
#include "user_interface.h" // 系统接口、system_param_xxx接口、WIFI、RateContro
#define ProjectName "Flash"
#define SPI_FLASH_SEC_SIZE 4096
u16 N_Data_FLASH_SEC = 0X77; //存储数据的扇区编号
u32 A_W_Data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,12,14,15,16}; //写入Flash的数据
u32 A_R_Data[16] = {0}; //缓存读Flash的数据
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{ for(;C_time>0;C_time--)
os_delay_us(1000);
}
void ICACHE_FLASH_ATTR user_init(void)
{
u8 C_loop = 0;
uart_init(115200,115200); // 初始化串口波特率
os_delay_us(10000); // 等待串口稳定
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
spi_flash_erase_sector(N_Data_FLASH_SEC); //擦除0x77扇区
// 向Flash写数据(参数1=【字节地址】、参数2=写入数据的指针、参数3=数据长度)
spi_flash_write(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_W_Data, sizeof(A_W_Data));
os_printf("\r\n---------- Write Flash Data OVER ----------\r\n");
//从【0x77 000】地址起,读取16个数据(每个数据占4字节)
spi_flash_read(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_R_Data, sizeof(A_W_Data));
for(C_loop=0; C_loop<16; C_loop++)
{
os_printf("Read Data = %d \r\n",A_R_Data[C_loop]);
delay_ms(10);
}
os_printf("\r\n\r\n------------ user_init OVER ------------\r\n\r\n");
}
/******************************************************************************
* FunctionName : user_rf_cal_sector_set
* Description : SDK just reversed 4 sectors, used for rf init data and paramters.
* We add this function to force users to set rf cal sector, since
* we don't know which sector is free in user's application.
* sector map for last several sectors : ABCCC
* A : rf cal
* B : rf init data
* C : sdk parameters
* Parameters : none
* Returns : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{}
总结框架
#define SPI_FLASH_SEC_SIZE 4096
u16 N_Data_FLASH_SEC = 0X77; //存储数据的扇区编号
u32 A_W_Data[16] = {1,2,3,4,5,6,7,8,9,10,11,12,12,14,15,16}; //写入Flash的数据
u32 A_R_Data[16] = {0}; //缓存读Flash的数据
void ICACHE_FLASH_ATTR user_init(void)
{
spi_flash_erase_sector(N_Data_FLASH_SEC); //擦除0x77扇区
// 向Flash写数据(参数1=【字节地址】、参数2=写入数据的指针、参数3=数据长度)
spi_flash_write(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_W_Data, sizeof(A_W_Data));
//从【0x77 000】地址起,读取16个数据(每个数据占4字节)
spi_flash_read(N_Data_FLASH_SEC*SPI_FLASH_SEC_SIZE, (uint32 *)A_R_Data, sizeof(A_W_Data));
}