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;
}

This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts here