esp8266 writing to internal flash (basic key/value store)
The following code for the esp8266 shows how you might write to the user flash area and implement a simple key/value store. I wouldn’t use this for anything, but the example may be instructive.
The memory map of the esp8266 isn’t yet fully understood, but there appears to be a user writable area at the location identified as 0x3C00. All flash reads/writes are executed via the library functions spi_flash_xxx. I assume this region of flash is marked for user applications only, and there’s no possibility of user code overflowing into this area. I don’t know how large this region is. If you know, please comment below or send me an email.
I’ve also noticed someone here disabling UART interrupts during flash writes using ETS_UART_INTR_DISABLE() and ETS_UART_INTR_ENABLE(). I’m not doing this in the code below, but it is possibly important to do so.
#include "flash.h"
ICACHE_FLASH_ATTR static char *find_key(const char *key,char *settings) {
int n;
for(n=0;n<1024;n+=128) {
if(strcmp(key,settings+n) == 0) return settings+n;
}
return 0;
}
ICACHE_FLASH_ATTR static char *find_free(char *settings) {
int n;
for(n=0;n<1024;n+=128) {
if(settings[n] == 0) return settings+n;
}
return 0;
}
ICACHE_FLASH_ATTR void flash_erase_all() {
char settings[1024];
int n;
for(n=0;n<1024;n++) settings[n]=0;
spi_flash_erase_sector(0x3C);
spi_flash_write(0x3C000,settings,1024);
}
ICACHE_FLASH_ATTR int flash_key_value_set(const char *key,const char *value) {
if(strlen(key) > 64) return 1;
if(strlen(value) > 64) return 1;
char settings[1024];
spi_flash_read(0x3C000, (uint32 *) settings, 1024);
char *location = find_key(key,settings);
if(location == NULL) {
location = find_free(settings);
}
if(location == NULL) return 0;
strcpy(location,key);
strcpy(location+64,value);
spi_flash_erase_sector(0x3C);
spi_flash_write(0x3C000,settings,1024);
return 1;
}
ICACHE_FLASH_ATTR int flash_key_value_get(char *key,char *value) {
if(strlen(key) > 64) return 0;
if(strlen(value) > 64) return 0;
char settings[1024];
spi_flash_read(0x3C000, (uint32 *) settings, 1024);
char *location = find_key(key,settings);
if(location == NULL) value[0]=0;
strcpy(value,location+64);
return 1;
}
Please note that the code above contains several bugs. For example, key and value should be checked for a maximum length of 63, because there must be space for the terminating zero character. Also, the length comparisons must return 0 when the input was too large.
Nevertheless I would like to thank Nava for his ESP8266 pages. They have been very helpful to me.