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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #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.