{"id":347,"date":"2016-05-03T11:35:47","date_gmt":"2016-05-03T09:35:47","guid":{"rendered":"http:\/\/benjaminmarty.ch\/blog\/?p=347"},"modified":"2016-07-23T17:49:43","modified_gmt":"2016-07-23T15:49:43","slug":"esp8266-flash-eeprom","status":"publish","type":"post","link":"https:\/\/benjaminmarty.ch\/blog\/2016\/05\/03\/esp8266-flash-eeprom\/","title":{"rendered":"ESP8266 FLASH (\/EEPROM)"},"content":{"rendered":"<p><a href=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/04\/esp_dev_kit.jpg\" rel=\"attachment wp-att-273\"><img loading=\"lazy\" class=\"size-medium wp-image-273 alignleft\" src=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/04\/esp_dev_kit-300x168.jpg\" alt=\"esp_dev_kit\" width=\"300\" height=\"168\" srcset=\"https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/04\/esp_dev_kit-300x168.jpg 300w, https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/04\/esp_dev_kit.jpg 578w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Es geht weiter mit dem ESP8266. Die Grunddinge (softAP, station etc.) sitzen, wir kommen an den Punkt an welchem wir Daten speichern m\u00fcssen. Daten k\u00f6nnen Zugangsdaten, Passw\u00f6rter, Einstellungen, Stellungen etc. sein. Normalerweise nutzt man auf einer MCU dazu das altbekannte EEPROM. Dabei handelt es sich um einen persistenten Speicher, welcher seinen Inhalt im stromlosen Zustand beh\u00e4lt. Auf dem ESP8266 haben wir jedoch kein solches EEPROM. Daf\u00fcr haben wir einen sch\u00f6n grosssen FLASH Speicher. Unter anderem ist darauf Speicher f\u00fcr genau solche &#8222;User parameter&#8220; reserviert. In diesem Artikel m\u00f6chte ich einige Kernpunkte\/Stolpersteine zur Verwendung davon nennen.<\/p>\n<p>Haupts\u00e4chlich werden folgende 3 Funktionen genutzt. Diese sind im Espressif SDK vorhanden und in der API guide von Espressif beschrieben:<\/p>\n<pre><code class=\"cpp\">spi_\ufb02ash_erase_sector (uint16 sec)\r\nspi_\ufb02ash_write (uint32 des_addr, uint32 *src_addr, uint32 size)\r\nspi_\ufb02ash_read(uint32 src_addr, uint32 * des_addr,\u00a0uint32 size)<\/code><\/pre>\n<p>Der Nutzen der Befehle sollte im grossen und ganzen bereits durch dessen Namen klar sein.<\/p>\n<p>Es wird von Sektoren und Adressen gesprochen. Woher weiss man nun wo man Daten schreiben kann\/darf? Ganz einfach, es ist alles sch\u00f6n im Dokument &#8222;OTA Upgrade&#8220; von Espressif beschrieben:<a href=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/512kb_esp8266.png\" rel=\"attachment wp-att-353\"><img loading=\"lazy\" class=\"alignnone wp-image-353 size-full\" src=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/512kb_esp8266.png\" alt=\"512kb_esp8266\" width=\"678\" height=\"224\" srcset=\"https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/512kb_esp8266.png 678w, https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/512kb_esp8266-300x99.png 300w\" sizes=\"(max-width: 678px) 100vw, 678px\" \/><\/a><br \/>\nAnhand dieser Map k\u00f6nnen wir nun die Adressen\/Sektoren berechnen. Interessant f\u00fcr uns ist der Block &#8222;User param&#8220;. Dieser umfasst 16KB, das heisst 4 Sektoren. Ein Sektor ist immer 4KB gross. Die erste Adresse berechnen wir nun wie folgt:<\/p>\n<p>(64 + 176) \u00a0* 1024 = <strong>0x3C000<\/strong><\/p>\n<p>Sektor ist demnach <strong>0x3C<\/strong> (Adresse \/ 4096)<\/p>\n<p>Am besten rechnet man sowas im Windows Taschenrechner, die Rechnung an sich ist Dezimal, danach um das Resultat in Hex zu haben auf Hexidezimal wechseln:<\/p>\n<p><a href=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/calc_0x3c.png\" rel=\"attachment wp-att-354\"><img loading=\"lazy\" class=\"alignnone size-medium wp-image-354\" src=\"http:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/calc_0x3c-300x275.png\" alt=\"calc_0x3c\" width=\"300\" height=\"275\" srcset=\"https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/calc_0x3c-300x275.png 300w, https:\/\/benjaminmarty.ch\/blog\/wp-content\/uploads\/2016\/05\/calc_0x3c.png 423w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Ich arbeite im weiteren Verlauf jedoch mit dem zweiten User param Sektor. Dieser hat die Adresse <strong>0x3D000<\/strong> bzw. Sektor <strong>0x3D<\/strong>. Berechnen kann man diesen indem man die Adresse f\u00fcr 4KB\u00a0sp\u00e4ter berechnet.<\/p>\n<p>Nun haben wir alle Infos um mit dem &#8222;arbeiten&#8220; zu beginnen. Am besten f\u00e4ngt man mit einem simplen Programm wie folgt an:<\/p>\n<pre><code class=\"cpp\">unsigned char meinsatz[1024] = \"Ich nutze ab jetzt den Flash Speicher f\u00fcr meine Daten!\\n\";\r\nunsigned char meinflash[1024];\r\n\r\nspi_flash_erase_sector(0x3D);\r\nspi_flash_write(0x3D000, (uint32 *) meinsatz, sizeof(meinsatz));\r\nspi_flash_read(0x3D000, (uint32 *) meinflash, sizeof(meinflash));\r\nos_printf(\"%s\", meinflash);<\/code><\/pre>\n<p>Das Programm l\u00f6scht den Sektor (4KB) zuerst (zwingend!), danach wird der Speicher mit dem meinsatz beschrieben, dabei wird automatisch mit dem sizeof die Gr\u00f6sse ermittelt. Danach wird genau der Satz wieder geladen und mit printf ausgegeben.<\/p>\n<p>So haben wir nun schon mal was. Sch\u00f6n ist das ganze jedoch nat\u00fcrlich noch nicht. Normalerweise hat man mehrere Parameter, z.B. einen Parameter f\u00fcr eine RGB Lampe Rot, Gr\u00fcn, Blau. Diese k\u00f6nnte man nur mit einem zus\u00e4tzlichen (selbstgestrickten) handler trennen und organisieren. Das ganze l\u00e4sst sich jedoch bereits ziemlich einfach und gut mit C Bordmitteln l\u00f6sen.\u00a0Dabei bauen wir uns sozusagen einen eigenen Datentyp. Diesen k\u00f6nnen wir mit bekannten Datentypen spicken (int, char, bool etc.).<\/p>\n<pre><code class=\"cpp\">struct parameter {\r\n char red, green, blue;\r\n};<\/code><\/pre>\n<p>Diesen k\u00f6nnen wir nun wie folgt, \u00e4hnlich wie Variablen, nutzen.<\/p>\n<pre><code class=\"cpp\">struct parameter myparameter\r\n\r\nmyparameter.red = 120;\r\nmyparameter.green = 135;\r\nmyparameter.blue = 145;<\/code><\/pre>\n<p>Nun wird man sich fragen warum das f\u00fcr die Geschichte mit dem Flash gut sein soll. Ganz einfach: Wir k\u00f6nnen das ganze Struct in den Flash speichern und auch wieder holen \ud83d\ude42<\/p>\n<pre><code class=\"cpp\">struct parameter myparameter\r\nstruct parameter myparameterfromflash\r\nmyparameter.red = 120;\r\nmyparameter.green = 135;\r\nmyparameter.blue = 145;\r\n\r\nspi_flash_erase_sector(0x3D);\r\nspi_flash_write(0x3D000, (uint32 *) &amp;myparameter, sizeof(myparameter));\r\nspi_flash_read(0x3D000, (uint32 *) myparameterfromflash, sizeof(myparameterfromflash));\r\nos_printf(\"%s\", myparameterfromflash.red);\r\nos_printf(\"%s\", myparameterfromflash.green);\r\nos_printf(\"%s\", myparameterfromflash.blue);<\/code><\/pre>\n<p>So k\u00f6nnen wir nun ganz Bequem und aufger\u00e4umt Parameter zwischenspeichern, nutzen und vorallem auch persistens in den Flash speichern.<\/p>\n<p>Ich habe dabei mit der NONOS SDK Version 1.5.2 gearbeitet. Konfiguiert wurde der Compiler auf den 512k Mode 0 ohne Boot.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Es geht weiter mit dem ESP8266. Die Grunddinge (softAP, station etc.) sitzen, wir kommen an den Punkt an welchem wir Daten speichern m\u00fcssen. Daten k\u00f6nnen Zugangsdaten, Passw\u00f6rter, Einstellungen, Stellungen etc. sein. Normalerweise nutzt man auf einer MCU dazu das altbekannte EEPROM. Dabei handelt es sich um einen persistenten Speicher, welcher seinen Inhalt im stromlosen Zustand &#8230; <a class=\"more-link\" href=\"https:\/\/benjaminmarty.ch\/blog\/2016\/05\/03\/esp8266-flash-eeprom\/\">[Read more&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1,104],"tags":[],"_links":{"self":[{"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/posts\/347"}],"collection":[{"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/comments?post=347"}],"version-history":[{"count":32,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/posts\/347\/revisions"}],"predecessor-version":[{"id":381,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/posts\/347\/revisions\/381"}],"wp:attachment":[{"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/media?parent=347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/categories?post=347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benjaminmarty.ch\/blog\/wp-json\/wp\/v2\/tags?post=347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}