{"id":1919,"date":"2015-01-12T00:36:43","date_gmt":"2015-01-12T00:36:43","guid":{"rendered":"http:\/\/41j.com\/blog\/?p=1919"},"modified":"2015-03-06T04:41:05","modified_gmt":"2015-03-06T04:41:05","slug":"esp8266-writing-internal-flash-basic-keyvalue-store","status":"publish","type":"post","link":"https:\/\/41j.com\/blog\/2015\/01\/esp8266-writing-internal-flash-basic-keyvalue-store\/","title":{"rendered":"esp8266 writing to internal flash (basic key\/value store)"},"content":{"rendered":"<p>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&#8217;t use this for anything, but the example may be instructive.<\/p>\n<p>The memory map of the esp8266 isn&#8217;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&#8217;s no possibility of user code overflowing into this area. I don&#8217;t know how large this region is. If you know, please comment below or send me an email.<\/p>\n<p>I&#8217;ve also noticed someone <a href=\"https:\/\/github.com\/igrr\/atproto\/blob\/master\/target\/esp8266\/config_store.c\">here<\/a> disabling UART interrupts during flash writes using  ETS_UART_INTR_DISABLE() and  ETS_UART_INTR_ENABLE(). I&#8217;m not doing this in the code below, but it is possibly important to do so.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &quot;flash.h&quot;\r\n\r\n\r\nICACHE_FLASH_ATTR static char *find_key(const char *key,char *settings) {\r\n\r\n  int n;\r\n  for(n=0;n&lt;1024;n+=128) {\r\n    if(strcmp(key,settings+n) == 0) return settings+n;\r\n  }\r\n  return 0;\r\n}\r\n\r\nICACHE_FLASH_ATTR static char *find_free(char *settings) {\r\n\r\n  int n;\r\n  for(n=0;n&lt;1024;n+=128) {\r\n    if(settings&#x5B;n] == 0) return settings+n;\r\n  }\r\n  return 0;\r\n}\r\n\r\nICACHE_FLASH_ATTR void flash_erase_all() {\r\n  char settings&#x5B;1024];\r\n\r\n  int n;\r\n  for(n=0;n&lt;1024;n++) settings&#x5B;n]=0;\r\n\r\n  spi_flash_erase_sector(0x3C);\r\n  spi_flash_write(0x3C000,settings,1024);\r\n}\r\n\r\n\r\nICACHE_FLASH_ATTR int flash_key_value_set(const char *key,const char *value) {\r\n  \r\n  if(strlen(key)   &gt; 64) return 1;\r\n  if(strlen(value) &gt; 64) return 1;\r\n\r\n  char settings&#x5B;1024];\r\n  spi_flash_read(0x3C000, (uint32 *) settings, 1024);\r\n\r\n  char *location = find_key(key,settings);\r\n  if(location == NULL) {\r\n    location = find_free(settings);\r\n  }\r\n\r\n  if(location == NULL) return 0;\r\n\r\n  strcpy(location,key);\r\n  strcpy(location+64,value);\r\n\r\n  spi_flash_erase_sector(0x3C);\r\n  spi_flash_write(0x3C000,settings,1024);\r\n\r\n  return 1;\r\n}\r\n\r\nICACHE_FLASH_ATTR int flash_key_value_get(char *key,char *value) {\r\n  if(strlen(key)   &gt; 64) return 0;\r\n  if(strlen(value) &gt; 64) return 0;\r\n\r\n  char settings&#x5B;1024];\r\n\r\n  spi_flash_read(0x3C000, (uint32 *) settings, 1024);\r\n\r\n  char *location = find_key(key,settings);\r\n\r\n  if(location == NULL) value&#x5B;0]=0;\r\n  strcpy(value,location+64);\r\n  return 1;\r\n}\r\n<\/pre>\n<p><\/p>\n<h4>This is a continuation of my notes on the esp8266 microcontroller, you can find a complete list of my esp8266 posts <a href=\"http:\/\/41j.com\/blog\/2015\/01\/esp8266-notes-summary\/\">here<\/a><\/h4>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t use this for anything, but the example may be instructive. The memory map of the esp8266 isn&#8217;t yet fully understood, but there appears to be a user writable area at the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-1919","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1RRoU-uX","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/1919","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/comments?post=1919"}],"version-history":[{"count":2,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/1919\/revisions"}],"predecessor-version":[{"id":2210,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/1919\/revisions\/2210"}],"wp:attachment":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/media?parent=1919"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/categories?post=1919"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/tags?post=1919"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}