Für ein privates Sensorprojekt habe ich über einige Jahre hinweg viele
log-Daten zu speichern und möchte dabei möglichst wenig "wear" auf
meinem flash-ROM verursachen. Daher habe ich mich entschieden, bei
meinem ESP8266 Arduino-Projekt auf fertige Dateisysteme zu verzichten
und die Daten direkt im Binärformat auf die sonst ungenutzte FS
Partition zu schreiben. Diese liegt in dem seriell angebundenen
SPI-Flash-ROM des Gerätes.
Gestern habe ich mich mal an einem Konzept versucht und es sieht
prinzipell gut aus. Ich werde Daten nur blockweise manipulieren, und
möchte die Funktionalität aus "flash_hal.h"
(https://github.com/esp8266/Arduino/blob/master/cores/esp8266/flash_hal.h)
recyclen, z.B. so:
1 | uint32_t _block_to_addr(uint32_t block_nr) {
|
2 | return block_nr * flash_block_size_bytes + FS_PHYS_ADDR;
|
3 | }
|
4 | bool _read_block(uint32_t block_nr, uint8_t* buf_8192_bytes) {
|
5 | return flash_hal_read(_block_to_addr(block_nr), flash_block_size_bytes, buf_8192_bytes) == FLASH_HAL_OK;
|
6 | }
|
Wenn ich also aus dem 4MB Flash ca. 3MB für die FS Partition vergebe,
komme ich auf ca. 380 mögliche Blöcke à 8192 Bytes. Ein entsprechender
8kB-Buffer würde schon ganz gut in dem RAM passen und nach meinem
Konzept ist auch die Geschwindigkeit spürbar besser, wenn der ganze FS
overhead wegfällt.
Jetzt stellt sich mir aber noch die Frage, ob
flash_block_size_bytes=8192 Bytes die korrekte physikalische Blockgröße
widergibt, denn nur so hält der Speicher ausfallfrei möglichst lange.
Der Wert kommt einerseits aus der flash_hal.h weil er so im define
FS_PHYS_BLOCK hinterlegt ist; und er taucht auch bei der Kompilierung
als FS_BLOCK 0x2000 in der Datei "local.eagle.flash.ld" wieder auf. Ich
hänge die mal an...
Trotzdem bin ich nicht 100% sicher, ob da nicht schon eine logische
Abstraktionsebene dazwischen hängt und die wahre SPI flash Blockgröße
doch eine andere ist. Vielleicht klappen auch meine writes gar nicht
komplett wenn ich für diese API eine zu große size wähle? Das konnte ich
noch nicht debuggen.
Es jedenfalls ist leider so, dass es im Netz die verbreitete Info gibt,
dass SPI Flash Chips eine Standard-Blocksize von 4kB/32kB/64kB haben,
siehe z.B.
https://github.com/pellepl/spiffs/wiki/Configure-spiffs#configuration-example
https://esp32.com/viewtopic.php?t=12896
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/spiffs.html
Leider sehe ich bei meinem Wemos nicht, welcher chip da verbaut ist.
Die Frage also: gibt es einen noch besseren Weg, um ohne externe
Hardware ca. 2MB-3MB Daten zu loggen, als sie blockweise und ohne
Dateisystem in den SPI-Flash zu schreiben? Ist die API von "flash_hal.h"
dafür sinnvoll? Und gibt es eine bessere Blockgröße als die 8192 Bytes
aus der besagten Datei, wenn ich vor allem die Belastung des ROMs über
die Jahre klein halten möchte?