From f968805ae932a4360414f30a4eea1eaea19774e6 Mon Sep 17 00:00:00 2001 From: Makuna Date: Thu, 14 May 2015 11:56:03 -0700 Subject: [PATCH 01/31] dtostrf fix for remainder leading zeros Fix remainder to display leading zeros --- .../esp8266com/esp8266/cores/esp8266/core_esp8266_noniso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_noniso.c b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_noniso.c index a7efef4c4..eafe4fa72 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_noniso.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_noniso.c @@ -188,10 +188,10 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { ++out; } - while(prec-- > 0) { + for (unsigned char decShift = prec; decShift > 0; decShift--) { remainder *= 10.0; } - sprintf(out, "%d", (int) remainder); + sprintf(out, "%0*d", prec, (int)remainder); return s; } From 2cf17727bf02f73a8d9bbafdb19080977ad4e61a Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 14 May 2015 21:41:43 +0200 Subject: [PATCH 02/31] fix bug when TX buffer is full and os will write. in this case we hang endless or until wtd triggers. new: now we overdrive the data in FIFO --> no hang / crash but we loss chars. only happens by extensive use of os_printf! --- .../esp8266/cores/esp8266/HardwareSerial.cpp | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp b/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp index 87fd6dfbb..bdcd45716 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp @@ -392,30 +392,34 @@ void uart_ignore_char(char c) { void uart0_write_char(char c) { if(&Serial != NULL && Serial.isTxEnabled()) { - if(c == '\n') { - Serial.write('\r'); + if(Serial.availableForWrite() > 0) { + if(c == '\n') { + Serial.write('\r'); + } + Serial.write(c); + return; } - Serial.write(c); - } else { - if(c == '\n') { - USF(0) = '\r'; - } - USF(0) = c; } + if(c == '\n') { + USF(0) = '\r'; + } + USF(0) = c; } void uart1_write_char(char c) { if(&Serial1 != NULL && Serial1.isTxEnabled()) { - if(c == '\n') { - Serial1.write('\r'); + if(Serial1.availableForWrite() > 0) { + if(c == '\n') { + Serial1.write('\r'); + } + Serial1.write(c); + return; } - Serial1.write(c); - } else { - if(c == '\n') { - USF(1) = '\r'; - } - USF(1) = c; } + if(c == '\n') { + USF(1) = '\r'; + } + USF(1) = c; } static int s_uart_debug_nr = UART0; From a372da159b3293fdc1ecba0e2fd29f3a8c0b88c6 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Fri, 15 May 2015 13:42:30 +0200 Subject: [PATCH 03/31] fix SPI speed calculation @160Mhz Clock --- hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp | 6 +++--- hardware/esp8266com/esp8266/libraries/SPI/SPI.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp index c96c4fcb8..7d52528ef 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp @@ -121,14 +121,14 @@ void SPIClass::setBitOrder(uint8_t bitOrder) { * @return */ static uint32_t ClkRegToFreq(spiClk_t * reg) { - return (F_CPU / ((reg->regPre + 1) * (reg->regN + 1))); + return (SPI_MAX_SPEED / ((reg->regPre + 1) * (reg->regN + 1))); } void SPIClass::setFrequency(uint32_t freq) { static uint32_t lastSetFrequency = 0; static uint32_t lastSetRegister = 0; - if(freq >= F_CPU) { + if(freq >= SPI_MAX_SPEED) { setClockDivider(0x80000000); return; } @@ -164,7 +164,7 @@ void SPIClass::setFrequency(uint32_t freq) { reg.regN = calN; while(calPreVari++ <= 1) { // test different variants for Pre (we calculate in int so we miss the decimals, testing is the easyest and fastest way) - calPre = (((F_CPU / (reg.regN + 1)) / freq) - 1) + calPreVari; + calPre = (((SPI_MAX_SPEED / (reg.regN + 1)) / freq) - 1) + calPreVari; if(calPre > 0x1FFF) { reg.regPre = 0x1FFF; // 8191 } else if(calPre <= 0) { diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h index e67b5b0d5..68d2a3dc6 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h @@ -45,6 +45,8 @@ #define SPI_CLOCK_DIV64 0x04fc1001 //250 KHz #endif +#define SPI_MAX_SPEED (80000000L) + const uint8_t SPI_MODE0 = 0x00; ///< CPOL: 0 CPHA: 0 const uint8_t SPI_MODE1 = 0x01; ///< CPOL: 0 CPHA: 1 const uint8_t SPI_MODE2 = 0x10; ///< CPOL: 1 CPHA: 0 From 654ebcf598838e16e240f70ce34f44c5cedaad48 Mon Sep 17 00:00:00 2001 From: ficeto Date: Fri, 15 May 2015 20:06:13 +0300 Subject: [PATCH 04/31] enhance board flash handling and eeprom location --- hardware/esp8266com/esp8266/boards.txt | 68 +++++++++++-------- .../esp8266/libraries/EEPROM/EEPROM.cpp | 3 +- .../tools/esp8266/sdk/ld/eagle.flash.1m128.ld | 17 +++++ .../tools/esp8266/sdk/ld/eagle.flash.1m256.ld | 17 +++++ ...eagle.flash.1m.ld => eagle.flash.1m512.ld} | 0 ...agle.flash.256k.ld => eagle.flash.1m64.ld} | 10 +-- 6 files changed, 82 insertions(+), 33 deletions(-) create mode 100644 hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld create mode 100644 hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld rename hardware/tools/esp8266/sdk/ld/{eagle.flash.1m.ld => eagle.flash.1m512.ld} (100%) rename hardware/tools/esp8266/sdk/ld/{eagle.flash.256k.ld => eagle.flash.1m64.ld} (72%) diff --git a/hardware/esp8266com/esp8266/boards.txt b/hardware/esp8266com/esp8266/boards.txt index 4d6c41515..77f263cc6 100644 --- a/hardware/esp8266com/esp8266/boards.txt +++ b/hardware/esp8266com/esp8266/boards.txt @@ -2,7 +2,6 @@ menu.UploadSpeed=Upload Speed menu.CpuFrequency=CPU Frequency menu.FlashSize=Flash Size menu.FlashFreq=Flash Frequency -menu.FlashMode=Flash Mode ############################################################## generic.name=Generic ESP8266 Module @@ -24,6 +23,8 @@ generic.build.flash_mode=qio generic.build.flash_size=512K generic.build.flash_freq=40 generic.build.flash_ld=eagle.flash.512k.ld +generic.build.spiffs_start=0x6B000 +generic.build.spiffs_end=0x7B000 generic.menu.CpuFrequency.80=80 MHz generic.menu.CpuFrequency.80.build.f_cpu=80000000L @@ -49,39 +50,46 @@ generic.menu.UploadSpeed.512000.upload.speed=512000 generic.menu.UploadSpeed.921600=921600 generic.menu.UploadSpeed.921600.upload.speed=921600 -generic.menu.FlashSize.512K=512K +generic.menu.FlashSize.512K=512K (64K SPIFFS) generic.menu.FlashSize.512K.build.flash_size=512K generic.menu.FlashSize.512K.build.flash_ld=eagle.flash.512k.ld -generic.menu.FlashSize.256K=256K -generic.menu.FlashSize.256K.build.flash_size=256K -generic.menu.FlashSize.256K.build.flash_ld=eagle.flash.256k.ld -generic.menu.FlashSize.1M=1M -generic.menu.FlashSize.1M.build.flash_size=1M -generic.menu.FlashSize.1M.build.flash_ld=eagle.flash.1m.ld -generic.menu.FlashSize.2M=2M +generic.menu.FlashSize.512K.build.spiffs_start=0x6B000 +generic.menu.FlashSize.512K.build.spiffs_end=0x7B000 +generic.menu.FlashSize.1M512=1M (512K SPIFFS) +generic.menu.FlashSize.1M512.build.flash_size=1M +generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld +generic.menu.FlashSize.1M512.build.spiffs_start=0x6B000 +generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000 +generic.menu.FlashSize.1M256=1M (256K SPIFFS) +generic.menu.FlashSize.1M256.build.flash_size=1M +generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld +generic.menu.FlashSize.1M256.build.spiffs_start=0xAB000 +generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000 +generic.menu.FlashSize.1M128=1M (128K SPIFFS) +generic.menu.FlashSize.1M128.build.flash_size=1M +generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld +generic.menu.FlashSize.1M128.build.spiffs_start=0xCB000 +generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000 +generic.menu.FlashSize.1M64=1M (64K SPIFFS) +generic.menu.FlashSize.1M64.build.flash_size=1M +generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld +generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000 +generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000 +generic.menu.FlashSize.2M=2M (1M SPIFFS) generic.menu.FlashSize.2M.build.flash_size=2M generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.FlashSize.4M=4M +generic.menu.FlashSize.2M.build.spiffs_start=0x100000 +generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000 +generic.menu.FlashSize.4M=4M (3M SPIFFS) generic.menu.FlashSize.4M.build.flash_size=4M generic.menu.FlashSize.4M.build.flash_ld=eagle.flash.4m.ld +generic.menu.FlashSize.4M.build.spiffs_start=0x100000 +generic.menu.FlashSize.4M.build.spiffs_end=0x3FB000 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.20=20MHz -generic.menu.FlashFreq.20.build.flash_freq=20 -generic.menu.FlashFreq.26=26.7MHz -generic.menu.FlashFreq.26.build.flash_freq=26.7 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 - -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout +# generic.menu.FlashFreq.40=40MHz +# generic.menu.FlashFreq.40.build.flash_freq=40 +# generic.menu.FlashFreq.80=80MHz +# generic.menu.FlashFreq.80.build.flash_freq=80 ############################################################## modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) @@ -104,6 +112,8 @@ modwifi.build.flash_mode=qio modwifi.build.flash_size=2M modwifi.build.flash_freq=40 modwifi.build.flash_ld=eagle.flash.2m.ld +modwifi.build.spiffs_start=0x100000 +modwifi.build.spiffs_end=0x1FB000 modwifi.menu.CpuFrequency.80=80 MHz modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L @@ -150,6 +160,8 @@ nodemcu.build.flash_mode=qio nodemcu.build.flash_size=4M nodemcu.build.flash_freq=40 nodemcu.build.flash_ld=eagle.flash.4m.ld +nodemcu.build.spiffs_start=0x100000 +nodemcu.build.spiffs_end=0x3FB000 nodemcu.menu.CpuFrequency.80=80 MHz nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L @@ -197,6 +209,8 @@ nodemcu.menu.FlashSize.4M.build.flash_size=4M # wifio.build.flash_size=512K # wifio.build.flash_freq=40 # wifio.build.flash_ld=eagle.flash.512k.ld +# wifio.build.spiffs_start=0x6B000 +# wifio.build.spiffs_end=0x7B000 # # wifio.menu.CpuFrequency.80=80MHz # wifio.menu.CpuFrequency.80.build.f_cpu=80000000L diff --git a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp index 74e7f3b0f..14c6201f5 100644 --- a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp +++ b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp @@ -28,9 +28,10 @@ #include "os_type.h" #include "osapi.h" #include "spi_flash.h" +extern uint32_t _SPIFFS_end; } -#define CONFIG_START_SECTOR 0x7b +#define CONFIG_START_SECTOR (((uint32_t)_SPIFFS_end - 0x40200000) / 4096) #define CONFIG_SECTOR (CONFIG_START_SECTOR + 0) #define CONFIG_ADDR (SPI_FLASH_SEC_SIZE * CONFIG_SECTOR) diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld new file mode 100644 index 000000000..7505b26a2 --- /dev/null +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld @@ -0,0 +1,17 @@ +/* Flash Split for 1M chips */ +/* irom0 812KB */ +/* spiffs 128KB */ +/* eeprom 20KB */ + +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40210000, len = 0xCB000 +} + +PROVIDE ( _SPIFFS_start = 0x402CB000 ); +PROVIDE ( _SPIFFS_end = 0x402FB000 ); + +INCLUDE "../ld/eagle.app.v6.common.ld" diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld new file mode 100644 index 000000000..dc646d3f6 --- /dev/null +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld @@ -0,0 +1,17 @@ +/* Flash Split for 1M chips */ +/* irom0 684KB */ +/* spiffs 256KB */ +/* eeprom 20KB */ + +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40210000, len = 0xAB000 +} + +PROVIDE ( _SPIFFS_start = 0x402AB000 ); +PROVIDE ( _SPIFFS_end = 0x402FB000 ); + +INCLUDE "../ld/eagle.app.v6.common.ld" diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m512.ld similarity index 100% rename from hardware/tools/esp8266/sdk/ld/eagle.flash.1m.ld rename to hardware/tools/esp8266/sdk/ld/eagle.flash.1m512.ld diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.256k.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld similarity index 72% rename from hardware/tools/esp8266/sdk/ld/eagle.flash.256k.ld rename to hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld index 8ecddb8b6..d98bed64d 100644 --- a/hardware/tools/esp8266/sdk/ld/eagle.flash.256k.ld +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld @@ -1,5 +1,5 @@ -/* Flash Split for 256K chips */ -/* irom0 108KB */ +/* Flash Split for 1M chips */ +/* irom0 876KB */ /* spiffs 64KB */ /* eeprom 20KB */ @@ -8,10 +8,10 @@ MEMORY dport0_0_seg : org = 0x3FF00000, len = 0x10 dram0_0_seg : org = 0x3FFE8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40210000, len = 0x1B000 + irom0_0_seg : org = 0x40210000, len = 0xEB000 } -PROVIDE ( _SPIFFS_start = 0x4022B000 ); -PROVIDE ( _SPIFFS_end = 0x4023B000 ); +PROVIDE ( _SPIFFS_start = 0x402EB000 ); +PROVIDE ( _SPIFFS_end = 0x402FB000 ); INCLUDE "../ld/eagle.app.v6.common.ld" From 1f789c920e0bf1bd3af29fb37d4623bda974d269 Mon Sep 17 00:00:00 2001 From: ficeto Date: Fri, 15 May 2015 20:07:55 +0300 Subject: [PATCH 05/31] not needed menu item --- hardware/esp8266com/esp8266/boards.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/hardware/esp8266com/esp8266/boards.txt b/hardware/esp8266com/esp8266/boards.txt index 77f263cc6..c1aad78e6 100644 --- a/hardware/esp8266com/esp8266/boards.txt +++ b/hardware/esp8266com/esp8266/boards.txt @@ -188,9 +188,6 @@ nodemcu.menu.UploadSpeed.512000.upload.speed=512000 nodemcu.menu.UploadSpeed.921600=921600 nodemcu.menu.UploadSpeed.921600.upload.speed=921600 -nodemcu.menu.FlashSize.4M=4M -nodemcu.menu.FlashSize.4M.build.flash_size=4M - ############################################################## # wifio.name=Wifio # From 6a4128695dea839f994ef3c9b3093771a583418a Mon Sep 17 00:00:00 2001 From: ficeto Date: Fri, 15 May 2015 21:13:41 +0300 Subject: [PATCH 06/31] fix size and address misscalculations --- hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld | 2 +- hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld | 2 +- hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld index 7505b26a2..ddd57a57b 100644 --- a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m128.ld @@ -11,7 +11,7 @@ MEMORY irom0_0_seg : org = 0x40210000, len = 0xCB000 } -PROVIDE ( _SPIFFS_start = 0x402CB000 ); +PROVIDE ( _SPIFFS_start = 0x402DB000 ); PROVIDE ( _SPIFFS_end = 0x402FB000 ); INCLUDE "../ld/eagle.app.v6.common.ld" diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld index dc646d3f6..57b6a33fb 100644 --- a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m256.ld @@ -11,7 +11,7 @@ MEMORY irom0_0_seg : org = 0x40210000, len = 0xAB000 } -PROVIDE ( _SPIFFS_start = 0x402AB000 ); +PROVIDE ( _SPIFFS_start = 0x402BB000 ); PROVIDE ( _SPIFFS_end = 0x402FB000 ); INCLUDE "../ld/eagle.app.v6.common.ld" diff --git a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld index d98bed64d..ca3d64c67 100644 --- a/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld +++ b/hardware/tools/esp8266/sdk/ld/eagle.flash.1m64.ld @@ -8,7 +8,7 @@ MEMORY dport0_0_seg : org = 0x3FF00000, len = 0x10 dram0_0_seg : org = 0x3FFE8000, len = 0x14000 iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40210000, len = 0xEB000 + irom0_0_seg : org = 0x40210000, len = 0xDB000 } PROVIDE ( _SPIFFS_start = 0x402EB000 ); From c4dca3bd50310222c1644076c3c5d2c4fd593351 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 02:29:26 +0300 Subject: [PATCH 07/31] add folder api for SPIFFS --- .../esp8266/cores/esp8266/FileSystem.cpp | 115 +++++++++++------- .../esp8266/cores/esp8266/FileSystem.h | 9 +- .../ESP8266WebServer/src/ESP8266WebServer.h | 14 +++ 3 files changed, 95 insertions(+), 43 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp index ce722e7ec..1abd5dc9f 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp @@ -41,6 +41,10 @@ bool FSClass::format() { return spiffs_format(); } +bool FSClass::check() { + return SPIFFS_check(&_filesystemStorageHandle) == 0; +} + bool FSClass::exists(const char *filename) { spiffs_stat stat = {0}; if (SPIFFS_stat(&_filesystemStorageHandle, filename, &stat) < 0) @@ -61,6 +65,7 @@ bool FSClass::rename(const char *filename, const char *newname) { } FSFile FSClass::open(const char *filename, uint8_t mode) { + if(String(filename) == "" || String(filename) == "/") return FSFile("/"); int repeats = 0; bool notExist; bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT; @@ -84,6 +89,14 @@ FSFile FSClass::open(const char *filename, uint8_t mode) { return FSFile(); } +FSFile FSClass::open(spiffs_dirent* entry, uint8_t mode){ + int res = SPIFFS_open_by_dirent(&_filesystemStorageHandle, entry, (spiffs_flags)mode, 0); + if(res){ + return FSFile(res); + } + return FSFile(); +} + FSClass FS; FSFile::FSFile() { @@ -91,88 +104,125 @@ FSFile::FSFile() { _stats = {0}; } +FSFile::FSFile(String path) { + if(path == "/"){ + _file = 0x1; + os_sprintf((char*)_stats.name, "%s", (char*)path.c_str()); + _stats.size = 0; + _stats.type = SPIFFS_TYPE_DIR; + SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); + } else { + _file = SPIFFS_open(&_filesystemStorageHandle, path.c_str(), (spiffs_flags)FSFILE_READ, 0); + if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){ + debugf("stats errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + } + debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); + if(_stats.type == SPIFFS_TYPE_DIR){ + SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); + } + } +} + FSFile::FSFile(file_t f) { _file = f; if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){ - debugf("mount errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + debugf("stats errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + } + debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); + if(_stats.type == SPIFFS_TYPE_DIR){ + SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); } } void FSFile::close() { if (! _file) return; - SPIFFS_close(&_filesystemStorageHandle, _file); + if(_stats.type == SPIFFS_TYPE_DIR){ + SPIFFS_closedir(&_dir); + } + if(os_strlen((char*)_stats.name) > 1) + SPIFFS_close(&_filesystemStorageHandle, _file); _file = 0; } +void FSFile::rewindDirectory() { + if (! _file || !isDirectory()) return; + SPIFFS_closedir(&_dir); + SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); +} + +FSFile FSFile::openNextFile(){ + if (! _file || !isDirectory()) return FSFile(); + struct spiffs_dirent e; + struct spiffs_dirent *pe = &e; + if ((pe = SPIFFS_readdir(&_dir, pe))){ + return FS.open((char *)pe->name); + } + return FSFile(); +} + uint32_t FSFile::size() { if(! _file) return 0; - uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); - SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END); - uint32_t size = SPIFFS_tell(&_filesystemStorageHandle, _file); - SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); - return size; + if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0) return 0; + return _stats.size; } uint32_t FSFile::seek(uint32_t pos) { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; return SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); } uint32_t FSFile::position() { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; return SPIFFS_tell(&_filesystemStorageHandle, _file); } bool FSFile::eof() { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; return SPIFFS_eof(&_filesystemStorageHandle, _file); } bool FSFile::isDirectory(void) { - return false; + return _stats.type == SPIFFS_TYPE_DIR; } int FSFile::read(void *buf, uint16_t nbyte) { - if (! _file) return -1; + if (! _file || isDirectory()) return -1; return SPIFFS_read(&_filesystemStorageHandle, _file, buf, nbyte); } int FSFile::read() { - if (! _file) return -1; + if (! _file || isDirectory()) return -1; int val; if(SPIFFS_read(&_filesystemStorageHandle, _file, &val, 1) != 1) return -1; return val; } int FSFile::peek() { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; int c = read(); SPIFFS_lseek(&_filesystemStorageHandle, _file, -1, SPIFFS_SEEK_CUR); return c; } int FSFile::available() { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); - SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END); - uint32_t size = SPIFFS_tell(&_filesystemStorageHandle, _file); - SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); - return size - pos; + return _stats.size - pos; } size_t FSFile::write(const uint8_t *buf, size_t size){ - if (! _file) return 0; + if (! _file || isDirectory()) return 0; int res = SPIFFS_write(&_filesystemStorageHandle, _file, (uint8_t *)buf, size); return (res > 0)?(size_t)res:0; } size_t FSFile::write(uint8_t val) { - if (! _file) return 0; + if (! _file || isDirectory()) return 0; return write(&val, 1); } void FSFile::flush(){ - if (! _file) return; + if (! _file || isDirectory()) return; SPIFFS_fflush(&_filesystemStorageHandle, _file); } @@ -191,24 +241,5 @@ void FSFile::clearError(){ } char * FSFile::name(){ - return 0; + return (char*)_stats.name; } - - - - - - -/* -spiffs_DIR *dirOpen(spiffs_DIR *d){ - return SPIFFS_opendir(&_filesystemStorageHandle, 0, d); -} - -int dirClose(spiffs_DIR *d){ - return SPIFFS_closedir(d); -} - -file_t dirOpenFile(spiffs_dirent* entry, uint8_t flags){ - return SPIFFS_open_by_dirent(&_filesystemStorageHandle, entry, (spiffs_flags)flags, 0); -} -*/ diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h index 460595cf3..8956300c1 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h @@ -26,14 +26,17 @@ class String; #define FSFILE_READ SPIFFS_RDONLY -#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC) +#define FSFILE_WRITE (SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_DIRECT) +#define FSFILE_OVERWRITE (SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC | SPIFFS_DIRECT) class FSFile : public Stream { private: spiffs_stat _stats; file_t _file; + spiffs_DIR _dir; public: + FSFile(String path); FSFile(file_t f); FSFile(void); virtual size_t write(uint8_t); @@ -54,6 +57,8 @@ public: operator bool() { return _file > 0; } char * name(); bool isDirectory(void); + void rewindDirectory(void); + FSFile openNextFile(void); template size_t write(T &src){ const size_t bufferSize = 64; @@ -86,12 +91,14 @@ public: bool mount(); void unmount(); bool format(); + bool check(); bool exists(const char *filename); bool create(const char *filepath); bool remove(const char *filepath); bool rename(const char *filename, const char *newname); FSFile open(const char *filename, uint8_t mode = FSFILE_READ); + FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ); private: friend class FSFile; diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 375d09600..d957e15ba 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -76,6 +76,20 @@ public: void sendHeader(String name, String value, bool first = false); void sendContent(String content); + +template size_t streamFile(T &file, String contentType){ + String head = "HTTP/1.1 200 OK\r\nContent-Type: "; + head += contentType; + head += "\r\nContent-Length: "; + head += file.size(); + head += "\r\nConnection: close"; + head += "\r\nAccess-Control-Allow-Origin: *"; + head += "\r\n\r\n"; + _currentClient.print(head); + head = String(); + return _currentClient.write(file, HTTP_DOWNLOAD_UNIT_SIZE); +} + protected: void _handleRequest(); bool _parseRequest(WiFiClient& client); From fe5c6671a8cfc17c7ef598e20dcd590573dd1f52 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 11:03:39 +0300 Subject: [PATCH 08/31] enhancements on the FS Api --- .../esp8266/cores/esp8266/FileSystem.cpp | 52 ++++++++++--------- .../esp8266/cores/esp8266/FileSystem.h | 6 +-- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp index 1abd5dc9f..802029a8d 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp @@ -144,14 +144,22 @@ void FSFile::close() { _file = 0; } +char * FSFile::name(){ + return (char*)_stats.name; +} + +bool FSFile::isDirectory(void) { + return _stats.type == SPIFFS_TYPE_DIR; +} + void FSFile::rewindDirectory() { - if (! _file || !isDirectory()) return; + if (!_file || !isDirectory()) return; SPIFFS_closedir(&_dir); SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); } FSFile FSFile::openNextFile(){ - if (! _file || !isDirectory()) return FSFile(); + if (!_file || !isDirectory()) return FSFile(); struct spiffs_dirent e; struct spiffs_dirent *pe = &e; if ((pe = SPIFFS_readdir(&_dir, pe))){ @@ -161,30 +169,36 @@ FSFile FSFile::openNextFile(){ } uint32_t FSFile::size() { - if(! _file) return 0; - if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0) return 0; + if(!_file) return 0; + if(_stats.size) return _stats.size; + uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, 0, SPIFFS_SEEK_END); + _stats.size = SPIFFS_tell(&_filesystemStorageHandle, _file); + SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); return _stats.size; } +int FSFile::available() { + if (!_file) return 0; + uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); + return size() - pos; +} + uint32_t FSFile::seek(uint32_t pos) { - if (! _file || isDirectory()) return 0; + if (!_file) return 0; return SPIFFS_lseek(&_filesystemStorageHandle, _file, pos, SPIFFS_SEEK_SET); } uint32_t FSFile::position() { - if (! _file || isDirectory()) return 0; + if (!_file) return 0; return SPIFFS_tell(&_filesystemStorageHandle, _file); } bool FSFile::eof() { - if (! _file || isDirectory()) return 0; + if (!_file) return 0; return SPIFFS_eof(&_filesystemStorageHandle, _file); } -bool FSFile::isDirectory(void) { - return _stats.type == SPIFFS_TYPE_DIR; -} - int FSFile::read(void *buf, uint16_t nbyte) { if (! _file || isDirectory()) return -1; return SPIFFS_read(&_filesystemStorageHandle, _file, buf, nbyte); @@ -204,12 +218,6 @@ int FSFile::peek() { return c; } -int FSFile::available() { - if (! _file || isDirectory()) return 0; - uint32_t pos = SPIFFS_tell(&_filesystemStorageHandle, _file); - return _stats.size - pos; -} - size_t FSFile::write(const uint8_t *buf, size_t size){ if (! _file || isDirectory()) return 0; int res = SPIFFS_write(&_filesystemStorageHandle, _file, (uint8_t *)buf, size); @@ -226,10 +234,10 @@ void FSFile::flush(){ SPIFFS_fflush(&_filesystemStorageHandle, _file); } -uint32_t FSFile::remove(){ +bool FSFile::remove(){ if (! _file) return 0; - return SPIFFS_fremove(&_filesystemStorageHandle, _file); - _file = 0; + close(); + return SPIFFS_remove(&_filesystemStorageHandle, (const char *)_stats.name) == 0; } int FSFile::lastError(){ @@ -239,7 +247,3 @@ int FSFile::lastError(){ void FSFile::clearError(){ _filesystemStorageHandle.errno = SPIFFS_OK; } - -char * FSFile::name(){ - return (char*)_stats.name; -} diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h index 8956300c1..29173cb4e 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h @@ -26,8 +26,8 @@ class String; #define FSFILE_READ SPIFFS_RDONLY -#define FSFILE_WRITE (SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_DIRECT) -#define FSFILE_OVERWRITE (SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC | SPIFFS_DIRECT) +#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_DIRECT) +#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC | SPIFFS_DIRECT) class FSFile : public Stream { private: @@ -47,11 +47,11 @@ public: virtual void flush(); int read(void *buf, uint16_t nbyte); uint32_t seek(uint32_t pos); - uint32_t remove(); uint32_t position(); uint32_t size(); bool eof(); void close(); + bool remove(); int lastError(); void clearError(); operator bool() { return _file > 0; } From bad669b91abcd0f4f38aaf5a0ec5feb1674c8693 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 13:16:38 +0300 Subject: [PATCH 09/31] add access to SPIFFS properties --- hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h index 29173cb4e..012bdc45b 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h @@ -96,6 +96,13 @@ public: bool create(const char *filepath); bool remove(const char *filepath); bool rename(const char *filename, const char *newname); + size_t size(){ return _filesystemStorageHandle.cfg.phys_size; } + size_t blockSize(){ return _filesystemStorageHandle.cfg.log_block_size; } + size_t totalBlocks(){ return _filesystemStorageHandle.block_count; } + size_t freeBlocks(){ return _filesystemStorageHandle.free_blocks; } + size_t pageSize(){ return _filesystemStorageHandle.cfg.log_page_size; } + size_t allocatedPages(){ return _filesystemStorageHandle.stats_p_allocated; } + size_t deletedPages(){ return _filesystemStorageHandle.stats_p_deleted; } FSFile open(const char *filename, uint8_t mode = FSFILE_READ); FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ); From d3aa960474bcb3e485640887b394942c02a1ae2b Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 15:09:34 +0300 Subject: [PATCH 10/31] fix IP2STR and add MAC2STR macro --- hardware/tools/esp8266/sdk/include/ip_addr.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hardware/tools/esp8266/sdk/include/ip_addr.h b/hardware/tools/esp8266/sdk/include/ip_addr.h index 728a75c46..fc488ea8f 100644 --- a/hardware/tools/esp8266/sdk/include/ip_addr.h +++ b/hardware/tools/esp8266/sdk/include/ip_addr.h @@ -59,11 +59,10 @@ struct ip_info { #define IPADDR_ANY ((uint32)0x00000000UL) uint32 ipaddr_addr(const char *cp); -#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ - ip4_addr2_16(ipaddr), \ - ip4_addr3_16(ipaddr), \ - ip4_addr4_16(ipaddr) - +#define IP2STR(addr) (uint8_t)(addr & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 24) & 0xFF) #define IPSTR "%d.%d.%d.%d" +#define MAC2STR(mac) (uint8_t)mac[0], (uint8_t)mac[1], (uint8_t)mac[2], (uint8_t)mac[3], (uint8_t)mac[4], (uint8_t)mac[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + #endif /* __IP_ADDR_H__ */ From b40ec2fc35285fb079c7582feae0c5fa30a95576 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 16:22:38 +0300 Subject: [PATCH 11/31] add info methods to SD class --- libraries/SD/src/SD.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/SD/src/SD.h b/libraries/SD/src/SD.h index 93c79138b..b0192dd2f 100644 --- a/libraries/SD/src/SD.h +++ b/libraries/SD/src/SD.h @@ -106,6 +106,14 @@ public: boolean rmdir(char *filepath); + size_t type(){ return card.type(); } + size_t fatType(){ return volume.fatType(); } + size_t blocksPerCluster(){ return volume.blocksPerCluster(); } + size_t totalClusters(){ return volume.clusterCount(); } + size_t blockSize(){ return (size_t)0x200; } + size_t totalBlocks(){ return (totalClusters() / blocksPerCluster()); } + size_t clusterSize(){ return blocksPerCluster() * blockSize(); } + size_t size(){ return (clusterSize() * totalClusters()); } private: // This is used to determine the mode used to open a file From f946821381743ceb699d7d72b614a79cfa6078f0 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 16:29:10 +0300 Subject: [PATCH 12/31] fix data types --- libraries/SD/src/SD.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/SD/src/SD.h b/libraries/SD/src/SD.h index b0192dd2f..62276b4ee 100644 --- a/libraries/SD/src/SD.h +++ b/libraries/SD/src/SD.h @@ -106,8 +106,8 @@ public: boolean rmdir(char *filepath); - size_t type(){ return card.type(); } - size_t fatType(){ return volume.fatType(); } + uint8_t type(){ return card.type(); } + uint8_t fatType(){ return volume.fatType(); } size_t blocksPerCluster(){ return volume.blocksPerCluster(); } size_t totalClusters(){ return volume.clusterCount(); } size_t blockSize(){ return (size_t)0x200; } From ca3795721e166fd7939cae414a0fa83a208dce44 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 18:25:22 +0300 Subject: [PATCH 13/31] add Print::printf --- hardware/esp8266com/esp8266/cores/esp8266/Print.cpp | 11 +++++++++++ hardware/esp8266com/esp8266/cores/esp8266/Print.h | 1 + 2 files changed, 12 insertions(+) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp b/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp index c1405c9f7..aa63cd290 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp @@ -30,6 +30,7 @@ #include "Print.h" extern "C" { #include "c_types.h" +#include "ets_sys.h" } // Public Methods ////////////////////////////////////////////////////////////// @@ -43,6 +44,16 @@ size_t ICACHE_FLASH_ATTR Print::write(const uint8_t *buffer, size_t size) { return n; } +size_t Print::printf(const char *format, ...) { + va_list arg; + va_start(arg, format); + char temp[256]; + size_t len = ets_vsnprintf(temp, 256, format, arg); + len = write((const char *)temp); + va_end(arg); + return len; +} + size_t ICACHE_FLASH_ATTR Print::print(const __FlashStringHelper *ifsh) { PGM_P p = reinterpret_cast(ifsh); diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Print.h b/hardware/esp8266com/esp8266/cores/esp8266/Print.h index 79358f157..7366174f5 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Print.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Print.h @@ -63,6 +63,7 @@ class Print { return write((const uint8_t *) buffer, size); } + size_t printf(const char * format, ...); size_t print(const __FlashStringHelper *); size_t print(const String &); size_t print(const char[]); From cd6ba47f24c2bd83cf0a2291423f11640c21a39b Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 19:00:36 +0300 Subject: [PATCH 14/31] ESP8266WiFiClass::waitForConnectResult() waitForConnectResult() waits until wifi status is not disconnected, unless STA is disabled, in which case it returns WL_DISCONNECTED --- .../esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 8 ++++++++ .../esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index caf63982c..85a7ac416 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -81,6 +81,14 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase) return status(); } +uint8_t ESP8266WiFiClass::waitForConnectResult(){ + if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled + return WL_DISCONNECTED; + while (status() == WL_DISCONNECTED) + delay(100); + return status(); +} + void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { struct ip_info info; diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h index c98f32b8b..889af27a5 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -58,6 +58,10 @@ public: */ int begin(const char* ssid, const char *passphrase); + /* Wait for Wifi connection to reach a result + * returns the status reached or disconnect if STA is off + */ + uint8_t waitForConnectResult(); /* Set up an open access point * From a496c22d44009a87c6528e596dd0852b300862a4 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 20:38:00 +0300 Subject: [PATCH 15/31] fix uart triggering reset when spi has been read/written --- .../esp8266/cores/esp8266/spiffs/spiffs_flashmem.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c index 156e2fac2..fff3c2a86 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c @@ -97,7 +97,7 @@ uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ) bool flashmem_erase_sector( uint32_t sector_id ) { - WRITE_PERI_REG(0x60000914, 0x73); + WDT_RESET(); return spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; } @@ -186,7 +186,9 @@ uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t si os_memcpy(apbuf, from, size); } WDT_RESET(); + ETS_UART_INTR_DISABLE(); r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); + ETS_UART_INTR_ENABLE(); if(apbuf) os_free(apbuf); if(SPI_FLASH_RESULT_OK == r) @@ -202,7 +204,9 @@ uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ) fromaddr -= INTERNAL_FLASH_START_ADDRESS; SpiFlashOpResult r; WDT_RESET(); + ETS_UART_INTR_DISABLE(); r = spi_flash_read(fromaddr, (uint32 *)to, size); + ETS_UART_INTR_ENABLE(); if(SPI_FLASH_RESULT_OK == r) return size; else{ From 1eb2ee6e00aebbafab0c9e1a539a49540377d467 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 20:39:23 +0300 Subject: [PATCH 16/31] printf to print instead of write --- hardware/esp8266com/esp8266/cores/esp8266/Print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp b/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp index aa63cd290..1f924248a 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/Print.cpp @@ -49,7 +49,7 @@ size_t Print::printf(const char *format, ...) { va_start(arg, format); char temp[256]; size_t len = ets_vsnprintf(temp, 256, format, arg); - len = write((const char *)temp); + len = print(temp); va_end(arg); return len; } From 1529d7086f6c10db22cc4896519bcd75ca0498e9 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 21:01:51 +0300 Subject: [PATCH 17/31] disable all interrupts when reading from spiffs this fixes any possible resets caused by interrupt routines trying to read the flash while there is an ongoing spiffs operation --- .../esp8266com/esp8266/cores/esp8266/Arduino.h | 2 +- .../esp8266/cores/esp8266/spiffs/spiffs_flashmem.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h index 1170b6f4a..4a2bd7144 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/Arduino.h @@ -135,7 +135,7 @@ void ets_intr_unlock(); extern uint32_t interruptsState; #define interrupts() xt_enable_interrupts(interruptsState) -#define noInterrupts() xt_disable_interrupts(interruptsState, 15) +#define noInterrupts() __asm__ __volatile__("rsil %0,15; esync; isync; dsync" : "=a" (interruptsState)) #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c index fff3c2a86..d7f182ee0 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c @@ -1,5 +1,6 @@ #include "flashmem.h" #include "esp8266_peri.h" +#include "Arduino.h" // Based on NodeMCU platform_flash // https://github.com/nodemcu/nodemcu-firmware @@ -98,7 +99,10 @@ uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ) bool flashmem_erase_sector( uint32_t sector_id ) { WDT_RESET(); - return spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; + noInterrupts(); + bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; + interrupts(); + return erased; } SPIFlashInfo flashmem_get_info() @@ -186,9 +190,9 @@ uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t si os_memcpy(apbuf, from, size); } WDT_RESET(); - ETS_UART_INTR_DISABLE(); + noInterrupts(); r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); - ETS_UART_INTR_ENABLE(); + interrupts(); if(apbuf) os_free(apbuf); if(SPI_FLASH_RESULT_OK == r) @@ -204,9 +208,9 @@ uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ) fromaddr -= INTERNAL_FLASH_START_ADDRESS; SpiFlashOpResult r; WDT_RESET(); - ETS_UART_INTR_DISABLE(); + noInterrupts(); r = spi_flash_read(fromaddr, (uint32 *)to, size); - ETS_UART_INTR_ENABLE(); + interrupts(); if(SPI_FLASH_RESULT_OK == r) return size; else{ From 25a540d9ddb23f94e51ccc874d70c5688bb0ac91 Mon Sep 17 00:00:00 2001 From: ficeto Date: Sat, 16 May 2015 21:40:41 +0300 Subject: [PATCH 18/31] fix start address so erase works --- hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c index c07be839a..71d00905c 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c @@ -58,7 +58,7 @@ bool spiffs_format_internal(){ } u32_t sect_first, sect_last; - sect_first = flashmem_get_first_free_block_address(); + sect_first = flashmem_get_sector_of_address((u32_t)&_SPIFFS_start); sect_last = flashmem_get_sector_of_address((u32_t)&_SPIFFS_end); debugf("sect_first: %x, sect_last: %x\n", sect_first, sect_last); while( sect_first <= sect_last ){ From 66a5832ad1acb6839ed985ca2bcb2f2b1dc09f9f Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 16 May 2015 22:40:53 +0200 Subject: [PATCH 19/31] add support for list of AP connections - auto select ssid with best signal - for debugging enable DEBUG_WIFI_MULTI macro and call Serial.setDebugOutput(true); change ESP8266WiFiClass::status() return type to wl_status_t --- .../libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 2 +- .../libraries/ESP8266WiFi/src/ESP8266WiFi.h | 2 +- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 167 ++++++++++++++++++ .../ESP8266WiFi/src/ESP8266WiFiMulti.h | 59 +++++++ .../ESP8266WiFi/src/include/wl_definitions.h | 16 +- 5 files changed, 236 insertions(+), 10 deletions(-) create mode 100644 hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp create mode 100644 hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index caf63982c..9915d1bd6 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -336,7 +336,7 @@ uint8_t ESP8266WiFiClass::encryptionType(uint8_t i) return -1; } -uint8_t ESP8266WiFiClass::status() +wl_status_t ESP8266WiFiClass::status() { int status = wifi_station_get_connect_status(); diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h index c98f32b8b..be257d152 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -195,7 +195,7 @@ public: * * return: one of the value defined in wl_status_t */ - uint8_t status(); + wl_status_t status(); /* * Resolve the given hostname to an IP address. diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp new file mode 100644 index 000000000..a284be754 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -0,0 +1,167 @@ +/** + * + * @file ESP8266WiFiMulti.cpp + * @date 16.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "ESP8266WiFi.h" +#include "ESP8266WiFiMulti.h" +#include + +ESP8266WiFiMulti::ESP8266WiFiMulti() { +} + +ESP8266WiFiMulti::~ESP8266WiFiMulti() { + APlistClean(); +} + +bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) { + return APlistAdd(ssid, passphrase); +} + +wl_status_t ESP8266WiFiMulti::run(void) { + + wl_status_t status = WiFi.status(); + if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) { + + WifiAPlist_t bestNetwork { NULL, NULL }; + int bestNetworkDb = INT_MIN; + + // WiFi.scanNetworks will return the number of networks found + int8_t n = WiFi.scanNetworks(); + + DEBUG_WIFI_MULTI("[WIFI] scan done\n"); + delay(0); + + if(n <= 0) { + DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); + } else { + DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", n); + for(int8_t i = 0; i < n; ++i) { + const char * ssid_scan = WiFi.SSID(i); + int32_t rssi_scan = WiFi.RSSI(i); + uint8_t sec_scan = WiFi.encryptionType(i); + + bool known = false; + for(uint32_t x = 0; x < APlist.size(); x++) { + WifiAPlist_t entry = APlist[x]; + + if(strcmp(entry.ssid, ssid_scan) == 0) { // SSID match + known = true; + if(rssi_scan > bestNetworkDb) { // best network + if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan + bestNetworkDb = rssi_scan; + memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); + } + } + break; + } + } + if(known) { + DEBUG_WIFI_MULTI(" ---> "); + } else { + DEBUG_WIFI_MULTI(" "); + } + + DEBUG_WIFI_MULTI(" %d: %s (%d) %c\n", i, ssid_scan, rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); + delay(0); + } + } + + DEBUG_WIFI_MULTI("\n\n"); + delay(0); + + if(bestNetwork.ssid) { + DEBUG_WIFI_MULTI("[WIFI] Connecting SSID: %s (%d)\n", bestNetwork.ssid, bestNetworkDb); + + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase); + status = WiFi.status(); + + // wait for connection or fail + while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { + delay(10); + status = WiFi.status(); + } + + switch(status) { + case WL_CONNECTED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Done.\n"); + break; + case WL_NO_SSID_AVAIL: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); + break; + case WL_CONNECT_FAILED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n"); + break; + default: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status); + break; + } + } else { + DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); + } + } + return status; +} + +// ################################################################################## + +bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { + + WifiAPlist_t newAP; + + newAP.ssid = (char*) malloc(strlen(ssid)); + + if(!newAP.ssid) { + return false; + } + + strcpy(newAP.ssid, ssid); + + if(passphrase && *passphrase != 0x00) { + newAP.passphrase = (char*) malloc(strlen(passphrase)); + } + + if(!newAP.passphrase) { + free(newAP.ssid); + return false; + } + + strcpy(newAP.passphrase, passphrase); + + APlist.push_back(newAP); + return true; +} + +void ESP8266WiFiMulti::APlistClean(void) { + for(uint32_t i = 0; i < APlist.size(); i++) { + WifiAPlist_t entry = APlist[i]; + if(entry.ssid) { + free(entry.ssid); + } + if(entry.passphrase) { + free(entry.passphrase); + } + } + APlist.clear(); +} + diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h new file mode 100644 index 000000000..285fca755 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -0,0 +1,59 @@ +/** + * + * @file ESP8266WiFiMulti.h + * @date 16.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#ifndef WIFICLIENTMULTI_H_ +#define WIFICLIENTMULTI_H_ + +#include + +//#define DEBUG_WIFI_MULTI(...) os_printf( __VA_ARGS__ ) + +#ifndef DEBUG_WIFI_MULTI +#define DEBUG_WIFI_MULTI(...) +#endif + +typedef struct { + char * ssid; + char * passphrase; +} WifiAPlist_t; + +class ESP8266WiFiMulti { + public: + ESP8266WiFiMulti(); + ~ESP8266WiFiMulti(); + + bool addAP(const char* ssid, const char *passphrase = NULL); + + wl_status_t run(void); + + private: + std::vector APlist; + bool APlistAdd(const char* ssid, const char *passphrase = NULL); + void APlistClean(void); + +}; + +#endif /* WIFICLIENTMULTI_H_ */ diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/wl_definitions.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/wl_definitions.h index a32ba45b2..45bee6764 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/wl_definitions.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/wl_definitions.h @@ -48,14 +48,14 @@ #define WL_MAX_ATTEMPT_CONNECTION 10 typedef enum { - WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library - WL_IDLE_STATUS = 0, - WL_NO_SSID_AVAIL, - WL_SCAN_COMPLETED, - WL_CONNECTED, - WL_CONNECT_FAILED, - WL_CONNECTION_LOST, - WL_DISCONNECTED + WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library + WL_IDLE_STATUS = 0, + WL_NO_SSID_AVAIL = 1, + WL_SCAN_COMPLETED = 2, + WL_CONNECTED = 3, + WL_CONNECT_FAILED = 4, + WL_CONNECTION_LOST = 5, + WL_DISCONNECTED = 6 } wl_status_t; /* Encryption modes */ From 267901ef7b757aa6bdae620e341079e5e7796369 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 16 May 2015 22:47:29 +0200 Subject: [PATCH 20/31] add examples/WiFiMulti/WiFiMulti.ino --- .../examples/WiFiMulti/WiFiMulti.ino | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino new file mode 100644 index 000000000..5a1057893 --- /dev/null +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino @@ -0,0 +1,33 @@ +/* + * This sketch trys to Connect to the best AP based on a given list + * + */ + +#include +#include + +ESP8266WiFiMulti WiFiMulti = ESP8266WiFiMulti(); + +void setup() { + Serial.begin(115200); + delay(10); + + WiFiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); + WiFiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); + WiFiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); + + Serial.println("Connecting Wifi..."); + if(wifiMulti.run() == WL_CONNECTED) { + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + } +} + +void loop() { + if(wifiMulti.run() != WL_CONNECTED) { + Serial.println("WiFi not connected!"); + delay(1000); + } +} \ No newline at end of file From ba1ddbb1cf933941a8bfaca70a3cf3f59fb55583 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 16 May 2015 22:56:15 +0200 Subject: [PATCH 21/31] improve includes add ssid and ip to debug out --- .../libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 8 ++++++-- .../esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index a284be754..3b878020f 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -23,7 +23,6 @@ * */ -#include "ESP8266WiFi.h" #include "ESP8266WiFiMulti.h" #include @@ -76,6 +75,7 @@ wl_status_t ESP8266WiFiMulti::run(void) { break; } } + if(known) { DEBUG_WIFI_MULTI(" ---> "); } else { @@ -102,9 +102,13 @@ wl_status_t ESP8266WiFiMulti::run(void) { status = WiFi.status(); } + IPAddress ip; switch(status) { case WL_CONNECTED: - DEBUG_WIFI_MULTI("[WIFI] Connecting Done.\n"); + ip = WiFi.localIP(); + DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); + DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID()); + DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); break; case WL_NO_SSID_AVAIL: DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h index 285fca755..a3926a406 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -27,6 +27,7 @@ #ifndef WIFICLIENTMULTI_H_ #define WIFICLIENTMULTI_H_ +#include "ESP8266WiFi.h" #include //#define DEBUG_WIFI_MULTI(...) os_printf( __VA_ARGS__ ) From 8d92e73e6310e2df85ea78a3b6cbd9ca57ac955b Mon Sep 17 00:00:00 2001 From: ficeto Date: Sun, 17 May 2015 00:04:39 +0300 Subject: [PATCH 22/31] spiffs fixes --- .../esp8266/cores/esp8266/FileSystem.h | 4 ++-- .../esp8266/cores/esp8266/spiffs/spiffs.c | 14 ++++++++------ .../cores/esp8266/spiffs/spiffs_flashmem.c | 18 +++++++++--------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h index 012bdc45b..9d3a52eac 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h @@ -26,8 +26,8 @@ class String; #define FSFILE_READ SPIFFS_RDONLY -#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_DIRECT) -#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC | SPIFFS_DIRECT) +#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND ) +#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC ) class FSFile : public Stream { private: diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c index 71d00905c..74a65e05d 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c @@ -21,7 +21,7 @@ static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){ static s32_t api_spiffs_erase(u32_t addr, u32_t size){ debugf("api_spiffs_erase"); u32_t sect_first = flashmem_get_sector_of_address(addr); - u32_t sect_last = sect_first; + u32_t sect_last = flashmem_get_sector_of_address(addr+size); while( sect_first <= sect_last ) if( !flashmem_erase_sector( sect_first ++ ) ) return SPIFFS_ERR_INTERNAL; @@ -68,7 +68,7 @@ bool spiffs_format_internal(){ return true; } -bool spiffs_mount(){ +bool spiffs_mount_internal(bool wipe){ spiffs_config cfg = spiffs_get_storage_config(); if (cfg.phys_addr == 0){ SYSTEM_ERROR("Can't start file system, wrong address"); @@ -85,7 +85,7 @@ bool spiffs_mount(){ bool writeFirst = false; flashmem_read(&dat, cfg.phys_addr, 4); - if (dat == UINT32_MAX){ + if (dat == UINT32_MAX || wipe){ debugf("First init file system"); if(!spiffs_format_internal()){ SYSTEM_ERROR("Can't format file system"); @@ -115,15 +115,17 @@ bool spiffs_mount(){ return true; } +bool spiffs_mount(){ + return spiffs_mount_internal(false); +} + void spiffs_unmount(){ SPIFFS_unmount(&_filesystemStorageHandle); } bool spiffs_format(){ spiffs_unmount(); - if(!spiffs_format_internal()) return false; - spiffs_mount(); - return true; + return spiffs_mount_internal(true); } void test_spiffs(){ diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c index d7f182ee0..dc875ff12 100755 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c @@ -96,15 +96,6 @@ uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ) return ssize; } -bool flashmem_erase_sector( uint32_t sector_id ) -{ - WDT_RESET(); - noInterrupts(); - bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; - interrupts(); - return erased; -} - SPIFlashInfo flashmem_get_info() { volatile SPIFlashInfo spi_flash_info STORE_ATTR; @@ -177,6 +168,15 @@ uint32_t flashmem_get_sector_of_address( uint32_t addr ) ///////////////////////////////////////////////////// +bool flashmem_erase_sector( uint32_t sector_id ) +{ + WDT_RESET(); + noInterrupts(); + bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; + interrupts(); + return erased; +} + uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ) { toaddr -= INTERNAL_FLASH_START_ADDRESS; From cdf4aa053604aa01d8be3d80a33da41cf89f3119 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 16 May 2015 23:10:06 +0200 Subject: [PATCH 23/31] fix possible problems in EEPROM regarding interrupt handling and SPI flash blocking --- hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp index 74e7f3b0f..2e1eb4fca 100644 --- a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp +++ b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp @@ -49,7 +49,9 @@ void EEPROMClass::begin(size_t size) _data = new uint8_t[size]; _size = size; + noInterrupts(); spi_flash_read(CONFIG_ADDR, reinterpret_cast(_data), _size); + interrupts(); } void EEPROMClass::end() @@ -90,19 +92,21 @@ bool EEPROMClass::commit() if(!_dirty) return true; - ETS_UART_INTR_DISABLE(); + noInterrupts(); if(spi_flash_erase_sector(CONFIG_SECTOR) == SPI_FLASH_RESULT_OK) { if(spi_flash_write(CONFIG_ADDR, reinterpret_cast(_data), _size) == SPI_FLASH_RESULT_OK) { _dirty = false; ret = true; } } - ETS_UART_INTR_ENABLE(); + interrupts(); + return ret; } uint8_t * EEPROMClass::getDataPtr() { + _dirty = true; return &_data[0]; } From 730025cefc817eb6287521fdd18995c999bb7437 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 00:11:41 +0200 Subject: [PATCH 24/31] add some __attribute__ for compiler to get better optimizations and warning handle --- hardware/tools/esp8266/sdk/include/ets_sys.h | 6 +++--- hardware/tools/esp8266/sdk/include/osapi.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hardware/tools/esp8266/sdk/include/ets_sys.h b/hardware/tools/esp8266/sdk/include/ets_sys.h index b7b79c341..7908699bb 100644 --- a/hardware/tools/esp8266/sdk/include/ets_sys.h +++ b/hardware/tools/esp8266/sdk/include/ets_sys.h @@ -91,10 +91,10 @@ typedef void (*int_handler_t)(void*); ETS_INTR_DISABLE(ETS_GPIO_INUM) -void *pvPortMalloc(size_t xWantedSize); -void *pvPortRealloc(void* ptr, size_t xWantedSize); +void *pvPortMalloc(size_t xWantedSize) __attribute__((malloc, alloc_size(1))); +void *pvPortRealloc(void* ptr, size_t xWantedSize) __attribute__((alloc_size(2))); void pvPortFree(void *ptr); -void *vPortMalloc(size_t xWantedSize); +void *vPortMalloc(size_t xWantedSize) __attribute__((malloc, alloc_size(1))); void vPortFree(void *ptr); void *ets_memcpy(void *dest, const void *src, size_t n); void *ets_memset(void *s, int c, size_t n); diff --git a/hardware/tools/esp8266/sdk/include/osapi.h b/hardware/tools/esp8266/sdk/include/osapi.h index 6935388c5..11e03803f 100644 --- a/hardware/tools/esp8266/sdk/include/osapi.h +++ b/hardware/tools/esp8266/sdk/include/osapi.h @@ -50,7 +50,7 @@ os_printf_plus(flash_str, ##__VA_ARGS__); \ } while(0) #else -extern int os_printf_plus(const char * format, ...); +extern int os_printf_plus(const char * format, ...) __attribute__ ((format (printf, 1, 2))); #define os_printf os_printf_plus #endif From 6e0853408631b2d71fa5938a12ca07057c61f6da Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 13:33:10 +0200 Subject: [PATCH 25/31] force all os_malloc calls to request a aligned size. - this fix Fatal exception (9) by unaligned class memory --- hardware/esp8266com/esp8266/cores/esp8266/abi.cpp | 2 ++ hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/abi.cpp b/hardware/esp8266com/esp8266/cores/esp8266/abi.cpp index add40bcb1..b863997a3 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/abi.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/abi.cpp @@ -26,10 +26,12 @@ extern "C" { } void *operator new(size_t size) { + size = ((size + 3) & ~((size_t)0x3)); return os_malloc(size); } void *operator new[](size_t size) { + size = ((size + 3) & ~((size_t)0x3)); return os_malloc(size); } diff --git a/hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c b/hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c index 64efd94ab..519ea233a 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/libc_replacements.c @@ -38,6 +38,7 @@ #include "user_interface.h" void* malloc(size_t size) { + size = ((size + 3) & ~((size_t)0x3)); return os_malloc(size); } @@ -46,6 +47,7 @@ void free(void* ptr) { } void* realloc(void* ptr, size_t size) { + size = ((size + 3) & ~((size_t)0x3)); return os_realloc(ptr, size); } From 6e99cccb6138e7d1d79fcaf3ff714646edb848c5 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 13:43:49 +0200 Subject: [PATCH 26/31] improve os_printf handling when buffer full. - wait for free buffer in hw fifo --- .../esp8266/cores/esp8266/HardwareSerial.cpp | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp b/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp index bdcd45716..ac56919ca 100644 --- a/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/HardwareSerial.cpp @@ -42,12 +42,12 @@ extern "C" { #define UART_TX_FIFO_SIZE 0x80 struct uart_ { - int uart_nr; + int uart_nr; int baud_rate; bool rxEnabled; bool txEnabled; - uint8_t rxPin; - uint8_t txPin; + uint8_t rxPin; + uint8_t txPin; }; static const int UART0 = 0; @@ -120,7 +120,7 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) { // -------------- UART 0 -------------- if(Serial.isRxEnabled()) { while(U0IS & (1 << UIFF)) { - Serial._rx_complete_irq((char)(U0F & 0xff)); + Serial._rx_complete_irq((char) (U0F & 0xff)); U0IC = (1 << UIFF); } } @@ -135,7 +135,7 @@ void ICACHE_RAM_ATTR uart_interrupt_handler(uart_t* uart) { if(Serial1.isRxEnabled()) { while(U1IS & (1 << UIFF)) { - Serial1._rx_complete_irq((char)(U1F & 0xff)); + Serial1._rx_complete_irq((char) (U1F & 0xff)); U1IC = (1 << UIFF); } } @@ -357,19 +357,19 @@ void uart_swap(uart_t* uart) { switch(uart->uart_nr) { case UART0: if(uart->txPin == 1 && uart->rxPin == 3) { - pinMode(15, FUNCTION_4);//TX - pinMode(13, FUNCTION_4);//RX + pinMode(15, FUNCTION_4); //TX + pinMode(13, FUNCTION_4); //RX USWAP |= (1 << USWAP0); - pinMode(1, INPUT);//TX - pinMode(3, INPUT);//RX + pinMode(1, INPUT); //TX + pinMode(3, INPUT); //RX uart->rxPin = 13; uart->txPin = 15; } else { - pinMode(1, SPECIAL);//TX - pinMode(3, SPECIAL);//RX + pinMode(1, SPECIAL); //TX + pinMode(3, SPECIAL); //RX USWAP &= ~(1 << USWAP0); - pinMode(15, INPUT);//TX - pinMode(13, INPUT);//RX + pinMode(15, INPUT); //TX + pinMode(13, INPUT); //RX uart->rxPin = 3; uart->txPin = 1; } @@ -400,6 +400,14 @@ void uart0_write_char(char c) { return; } } + + // wait for the Hardware FIFO + while(true) { + if(((USS(0) >> USTXC) & 0xff) <= (UART_TX_FIFO_SIZE - 2)) { + break; + } + } + if(c == '\n') { USF(0) = '\r'; } @@ -416,6 +424,14 @@ void uart1_write_char(char c) { return; } } + + // wait for the Hardware FIFO + while(true) { + if(((USS(1) >> USTXC) & 0xff) <= (UART_TX_FIFO_SIZE - 2)) { + break; + } + } + if(c == '\n') { USF(1) = '\r'; } @@ -469,11 +485,11 @@ void HardwareSerial::begin(unsigned long baud, byte config) { } if(_uart->rxEnabled) { - if (!_rx_buffer) + if(!_rx_buffer) _rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE); } if(_uart->txEnabled) { - if (!_tx_buffer) + if(!_tx_buffer) _tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE); } _written = false; From 5c60dcbf2d2dd455a57fd60f1e3b707d687f89b4 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 13:53:31 +0200 Subject: [PATCH 27/31] Align the start of functions to the next power-of-two greater than 4, skipping up to 3 bytes. --- hardware/esp8266com/esp8266/platform.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware/esp8266com/esp8266/platform.txt b/hardware/esp8266com/esp8266/platform.txt index cd09aff98..9c197a832 100644 --- a/hardware/esp8266com/esp8266/platform.txt +++ b/hardware/esp8266com/esp8266/platform.txt @@ -15,7 +15,7 @@ compiler.sdk.path={compiler.tools.path}sdk/ compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -MMD -std=c99 +compiler.c.flags=-c -Os -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=c99 compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD @@ -26,7 +26,7 @@ compiler.c.elf.cmd=xtensa-lx106-elf-gcc compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -std=c++11 -MMD +compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD compiler.as.cmd=xtensa-lx106-elf-as From 9b653983a2c418bfa6b3e2a69276f2b3303f0eea Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 13:54:03 +0200 Subject: [PATCH 28/31] fix possible null ptr in EEPROM.cpp --- .../esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp index 2e1eb4fca..d0699c92e 100644 --- a/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp +++ b/hardware/esp8266com/esp8266/libraries/EEPROM/EEPROM.cpp @@ -41,7 +41,7 @@ EEPROMClass::EEPROMClass() void EEPROMClass::begin(size_t size) { - if (size < 0) + if (size <= 0) return; if (size > SPI_FLASH_SEC_SIZE) size = SPI_FLASH_SEC_SIZE; @@ -60,8 +60,9 @@ void EEPROMClass::end() return; commit(); - - delete[] _data; + if(_data) { + delete[] _data; + } _data = 0; _size = 0; } @@ -71,6 +72,8 @@ uint8_t EEPROMClass::read(int address) { if (address < 0 || (size_t)address >= _size) return 0; + if(!_data) + return 0; return _data[address]; } @@ -79,6 +82,8 @@ void EEPROMClass::write(int address, uint8_t value) { if (address < 0 || (size_t)address >= _size) return; + if(!_data) + return; _data[address] = value; _dirty = true; @@ -91,6 +96,8 @@ bool EEPROMClass::commit() return false; if(!_dirty) return true; + if(!_data) + return false; noInterrupts(); if(spi_flash_erase_sector(CONFIG_SECTOR) == SPI_FLASH_RESULT_OK) { From 7ef48031dc272feffed2fbb4124d968fe782d208 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 17 May 2015 14:55:11 +0200 Subject: [PATCH 29/31] add Exception Causes (EXCCAUSE) docu --- docs/exception_causes.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/exception_causes.md diff --git a/docs/exception_causes.md b/docs/exception_causes.md new file mode 100644 index 000000000..4b11bdb13 --- /dev/null +++ b/docs/exception_causes.md @@ -0,0 +1,38 @@ +Exception Causes (EXCCAUSE) +=========================================== + +| EXC-CAUSE Code | Cause Name | Cause Description | Required Option | EXC-VADDR Loaded | +|:--------------:|:---------------------------|:------------------------------------------------------------------------------------------------------------|:-------------------------|:----------------:| +| 0 | IllegalInstructionCause | Illegal instruction | Exception | No | +| 1 | SyscallCause | SYSCALL instruction | Exception | No | +| 2 | InstructionFetchErrorCause | Processor internal physical address or data error during instruction fetch | Exception | Yes | +| 3 | LoadStoreErrorCause | Processor internal physical address or data error during load or store | Exception | Yes | +| 4 | Level1InterruptCause | Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register | Interrupt | No | +| 5 | AllocaCause | MOVSP instruction, if caller’s registers are not in the register file | Windowed Register | No | +| 6 | IntegerDivideByZeroCause | QUOS, QUOU, REMS, or REMU divisor operand is zero | 32-bit Integer Divide | No | +| 7 | Reserved for Tensilica | | | | +| 8 | PrivilegedCause | Attempt to execute a privileged operation when CRING ? 0 | MMU | No | +| 9 | LoadStoreAlignmentCause | Load or store to an unaligned address | Unaligned Exception | Yes | +| 10..11 | Reserved for Tensilica | | | | +| 12 | InstrPIFDataErrorCause | PIF data error during instruction fetch | Processor Interface | Yes | +| 13 | LoadStorePIFDataErrorCause | Synchronous PIF data error during LoadStore access | Processor Interface | Yes | +| 14 | InstrPIFAddrErrorCause | PIF address error during instruction fetch | Processor Interface | Yes | +| 15 | LoadStorePIFAddrErrorCause | Synchronous PIF address error during LoadStore access | Processor Interface | Yes | +| 16 | InstTLBMissCause | Error during Instruction TLB refill | MMU | Yes | +| 17 | InstTLBMultiHitCause | Multiple instruction TLB entries matched | MMU | Yes | +| 18 | InstFetchPrivilegeCause | An instruction fetch referenced a virtual address at a ring level less than CRING | MMU | Yes | +| 19 | Reserved for Tensilica | | | | +| 20 | InstFetchProhibitedCause | An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch | Region Protection or MMU | Yes | +| 21..23 | Reserved for Tensilica | | | | +| 24 | LoadStoreTLBMissCause | Error during TLB refill for a load or store | MMU | Yes | +| 25 | LoadStoreTLBMultiHitCause | Multiple TLB entries matched for a load or store | MMU | Yes | +| 26 | LoadStorePrivilegeCause | A load or store referenced a virtual address at a ring level less than CRING | MMU | Yes | +| 27 | Reserved for Tensilica | | | | +| 28 | LoadProhibitedCause | A load referenced a page mapped with an attribute that does not permit loads | Region Protection or MMU | Yes | +| 29 | StoreProhibitedCause | A store referenced a page mapped with an attribute that does not permit stores | Region Protection or MMU | Yes | +| 30..31 | Reserved for Tensilica | | | | +| 32..39 | CoprocessornDisabled | Coprocessor n instruction when cpn disabled. n varies 0..7 as the cause varies 32..39 | Coprocessor | No | +| 40..63 | Reserved | | | | + + +Infos from Xtensa Instruction Set Architecture (ISA) Reference Manual \ No newline at end of file From d0fe88be5a033e41186119e4360ddfae707a7ca3 Mon Sep 17 00:00:00 2001 From: ficeto Date: Mon, 18 May 2015 04:54:27 +0300 Subject: [PATCH 30/31] Update to the latest SPIFFS git and cleanup Almost unmodified spiffs from github lots of NodeMCU leftovers are removed More proper names given to platform related files Adjusting the FS class for the changes --- .../esp8266/cores/esp8266/FileSystem.cpp | 70 ++++-- .../esp8266/cores/esp8266/FileSystem.h | 13 +- .../esp8266/spiffs/{docs => }/INTEGRATION | 2 +- .../esp8266/cores/esp8266/spiffs/Makefile | 44 ---- .../esp8266/cores/esp8266/spiffs/README | 86 +++++++ .../cores/esp8266/spiffs/{docs => }/TECH_SPEC | 0 .../esp8266/cores/esp8266/spiffs/TODO | 15 ++ .../esp8266/cores/esp8266/spiffs/flashmem.h | 73 ------ .../esp8266/cores/esp8266/spiffs/spiffs.c | 148 ----------- .../esp8266/cores/esp8266/spiffs/spiffs.h | 112 ++++++--- .../cores/esp8266/spiffs/spiffs_cache.c | 0 .../cores/esp8266/spiffs/spiffs_check.c | 4 +- .../cores/esp8266/spiffs/spiffs_config.h | 44 ++-- .../cores/esp8266/spiffs/spiffs_esp8266.c | 224 +++++++++++++++++ .../cores/esp8266/spiffs/spiffs_esp8266.h | 40 +++ .../cores/esp8266/spiffs/spiffs_flashmem.c | 232 ------------------ .../esp8266/cores/esp8266/spiffs/spiffs_gc.c | 80 +++--- .../cores/esp8266/spiffs/spiffs_hydrogen.c | 166 ++++++++++--- .../cores/esp8266/spiffs/spiffs_nucleus.c | 170 ++++++++++--- .../cores/esp8266/spiffs/spiffs_nucleus.h | 49 +++- 20 files changed, 877 insertions(+), 695 deletions(-) mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h rename hardware/esp8266com/esp8266/cores/esp8266/spiffs/{docs => }/INTEGRATION (99%) mode change 100755 => 100644 delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/Makefile create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/README rename hardware/esp8266com/esp8266/cores/esp8266/spiffs/{docs => }/TECH_SPEC (100%) mode change 100755 => 100644 create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/TODO delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/flashmem.h delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.h mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_cache.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_check.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.c create mode 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.h delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_gc.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.c mode change 100755 => 100644 hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.h diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp old mode 100755 new mode 100644 index 802029a8d..735bb7d4a --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.cpp @@ -22,49 +22,71 @@ #include "Arduino.h" bool FSClass::mount() { - if (_mounted) - return true; - - _mounted = spiffs_mount(); - return _mounted; + if(SPIFFS_mounted(&_filesystemStorageHandle)) return true; + int res = spiffs_mount(); + if(res != 0){ + int formated = SPIFFS_format(&_filesystemStorageHandle); + if(formated != 0) return false; + res = spiffs_mount(); + } + return (res == 0); } void FSClass::unmount() { - if (!_mounted) - return; - - spiffs_unmount(); - _mounted = false; + if(SPIFFS_mounted(&_filesystemStorageHandle)) + SPIFFS_unmount(&_filesystemStorageHandle); } bool FSClass::format() { - return spiffs_format(); + if(!SPIFFS_mounted(&_filesystemStorageHandle)){ + spiffs_mount(); + } + SPIFFS_unmount(&_filesystemStorageHandle); + int formated = SPIFFS_format(&_filesystemStorageHandle); + if(formated != 0) return false; + return (spiffs_mount() == 0); } bool FSClass::check() { return SPIFFS_check(&_filesystemStorageHandle) == 0; } -bool FSClass::exists(const char *filename) { +bool FSClass::exists(char *filename) { spiffs_stat stat = {0}; if (SPIFFS_stat(&_filesystemStorageHandle, filename, &stat) < 0) return false; return stat.name[0] != '\0'; } -bool FSClass::create(const char *filepath){ +bool FSClass::create(char *filepath){ return SPIFFS_creat(&_filesystemStorageHandle, filepath, 0) == 0; } -bool FSClass::remove(const char *filepath){ +bool FSClass::remove(char *filepath){ return SPIFFS_remove(&_filesystemStorageHandle, filepath) == 0; } -bool FSClass::rename(const char *filename, const char *newname) { +bool FSClass::rename(char *filename, char *newname) { return SPIFFS_rename(&_filesystemStorageHandle, filename, newname) == 0; } -FSFile FSClass::open(const char *filename, uint8_t mode) { +size_t FSClass::totalBytes(){ + u32_t totalBytes; + u32_t usedBytes; + if(SPIFFS_info(&_filesystemStorageHandle, &totalBytes, &usedBytes) == 0) + return totalBytes; + return 0; +} + +size_t FSClass::usedBytes(){ + u32_t totalBytes; + u32_t usedBytes; + if(SPIFFS_info(&_filesystemStorageHandle, &totalBytes, &usedBytes) == 0) + return usedBytes; + return 0; +} + +FSFile FSClass::open(char *filename, uint8_t mode) { if(String(filename) == "" || String(filename) == "/") return FSFile("/"); int repeats = 0; bool notExist; @@ -76,7 +98,7 @@ FSFile FSClass::open(const char *filename, uint8_t mode) { res = SPIFFS_open(&_filesystemStorageHandle, filename, (spiffs_flags)mode, 0); int code = SPIFFS_errno(&_filesystemStorageHandle); if (res < 0){ - debugf("open errno %d\n", code); + SPIFFS_API_DBG_E("open errno %d\n", code); notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE); if (notExist && canRecreate) remove(filename); // fix for deleted files @@ -112,11 +134,11 @@ FSFile::FSFile(String path) { _stats.type = SPIFFS_TYPE_DIR; SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); } else { - _file = SPIFFS_open(&_filesystemStorageHandle, path.c_str(), (spiffs_flags)FSFILE_READ, 0); + _file = SPIFFS_open(&_filesystemStorageHandle, (char *)path.c_str(), (spiffs_flags)FSFILE_READ, 0); if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){ - debugf("stats errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); } - debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); + //debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); if(_stats.type == SPIFFS_TYPE_DIR){ SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); } @@ -126,9 +148,9 @@ FSFile::FSFile(String path) { FSFile::FSFile(file_t f) { _file = f; if(SPIFFS_fstat(&_filesystemStorageHandle, _file, &_stats) != 0){ - debugf("stats errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); + SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); } - debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); + //debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); if(_stats.type == SPIFFS_TYPE_DIR){ SPIFFS_opendir(&_filesystemStorageHandle, (char*)_stats.name, &_dir); } @@ -237,7 +259,7 @@ void FSFile::flush(){ bool FSFile::remove(){ if (! _file) return 0; close(); - return SPIFFS_remove(&_filesystemStorageHandle, (const char *)_stats.name) == 0; + return SPIFFS_remove(&_filesystemStorageHandle, (char *)_stats.name) == 0; } int FSFile::lastError(){ @@ -245,5 +267,5 @@ int FSFile::lastError(){ } void FSFile::clearError(){ - _filesystemStorageHandle.errno = SPIFFS_OK; + _filesystemStorageHandle.err_code = SPIFFS_OK; } diff --git a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h old mode 100755 new mode 100644 index 9d3a52eac..41659da11 --- a/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/FileSystem.h @@ -85,17 +85,18 @@ public: class FSClass { private: - bool _mounted = false; public: bool mount(); void unmount(); bool format(); bool check(); - bool exists(const char *filename); - bool create(const char *filepath); - bool remove(const char *filepath); - bool rename(const char *filename, const char *newname); + bool exists(char *filename); + bool create(char *filepath); + bool remove(char *filepath); + bool rename(char *filename, char *newname); + size_t totalBytes(); + size_t usedBytes(); size_t size(){ return _filesystemStorageHandle.cfg.phys_size; } size_t blockSize(){ return _filesystemStorageHandle.cfg.log_block_size; } size_t totalBlocks(){ return _filesystemStorageHandle.block_count; } @@ -104,7 +105,7 @@ public: size_t allocatedPages(){ return _filesystemStorageHandle.stats_p_allocated; } size_t deletedPages(){ return _filesystemStorageHandle.stats_p_deleted; } - FSFile open(const char *filename, uint8_t mode = FSFILE_READ); + FSFile open(char *filename, uint8_t mode = FSFILE_READ); FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ); private: diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/INTEGRATION b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/INTEGRATION old mode 100755 new mode 100644 similarity index 99% rename from hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/INTEGRATION rename to hardware/esp8266com/esp8266/cores/esp8266/spiffs/INTEGRATION index 085ed8fc1..20ff70d05 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/INTEGRATION +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/INTEGRATION @@ -303,4 +303,4 @@ Having these figures you can disable SPIFFS_BUFFER_HELP again to save flash. * HOW TO CONFIG -TODO \ No newline at end of file +TODO diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/Makefile b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/Makefile deleted file mode 100755 index 1c44e4ace..000000000 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/Makefile +++ /dev/null @@ -1,44 +0,0 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR -GEN_LIBS = spiffs.a -endif - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -INCLUDES += -I ../libc -INCLUDES += -I ../platform -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/README b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/README new file mode 100644 index 000000000..6efd656cb --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/README @@ -0,0 +1,86 @@ +SPIFFS (SPI Flash File System) +V0.3.0 + +Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976gmail.com) + +For legal stuff, see LICENCE in this directory. Basically, you may do whatever +you want with the source. Use, modify, sell, print it out, roll it and smoke it + - as long as I won't be held responsible. + +Love to hear feedback though! + + +* INTRODUCTION + +Spiffs is a file system intended for SPI NOR flash devices on embedded targets. + +Spiffs is designed with following characteristics in mind: + - Small (embedded) targets, sparse RAM without heap + - Only big areas of data (blocks) can be erased + - An erase will reset all bits in block to ones + - Writing pulls one to zeroes + - Zeroes can only be pulled to ones by erase + - Wear leveling + + +* FEATURES + +What spiffs does: + - Specifically designed for low ram usage + - Uses statically sized ram buffers, independent of number of files + - Posix-like api: open, close, read, write, seek, stat, etc + - It can be run on any NOR flash, not only SPI flash - theoretically also on + embedded flash of an microprocessor + - Multiple spiffs configurations can be run on same target - and even on same + SPI flash device + - Implements static wear leveling + - Built in file system consistency checks + +What spiffs does not: + - Presently, spiffs does not support directories. It produces a flat + structure. Creating a file with path "tmp/myfile.txt" will create a file + called "tmp/myfile.txt" instead of a "myfile.txt" under directory "tmp". + - It is not a realtime stack. One write operation might take much longer than + another. + - Poor scalability. Spiffs is intended for small memory devices - the normal + sizes for SPI flashes. Going beyond ~128MB is probably a bad idea. This is + a side effect of the design goal to use as little ram as possible. + - Presently, it does not detect or handle bad blocks. + + +* MORE INFO + +For integration, see the docs/INTEGRATION file. + +For use and design, see the docs/TECH_SPEC file. + +For testing and contributions, see the docs/IMPLEMENTING file. + +* HISTORY + +0.3.0 + Added existing namecheck when creating files + Lots of static analysis bugs #6 + Added rename func + Fix SPIFFS_read length when reading beyond file size + Added reading beyond file length testcase + Made build a bit more configurable + Changed name in spiffs from "errno" to "err_code" due to conflicts compiling + in mingw + Improved GC checks, fixed an append bug, more robust truncate for very special + case + GC checks preempts GC, truncate even less picky + Struct alignment needed for some targets, define in spiffs config #10 + Spiffs filesystem magic, definable in config + + New config defines: + SPIFFS_USE_MAGIC - enable or disable magic check upon mount + SPIFFS_ALIGNED_OBJECT_INDEX_TABLES - alignment for certain targets + New API functions: + SPIFFS_rename - rename files + SPIFFS_clearerr - clears last errno + SPIFFS_info - returns info on used and total bytes in fs + SPIFFS_format - formats the filesystem + SPIFFS_mounted - checks if filesystem is mounted + + diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TECH_SPEC b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/TECH_SPEC old mode 100755 new mode 100644 similarity index 100% rename from hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TECH_SPEC rename to hardware/esp8266com/esp8266/cores/esp8266/spiffs/TECH_SPEC diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/TODO b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/TODO new file mode 100644 index 000000000..c947316a8 --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/TODO @@ -0,0 +1,15 @@ +* When mending lost pages, also see if they fit into length specified in object index header + +SPIFFS2 thoughts + +* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id. + Eg. object id xor:ed with bit-reversed span index. + This should decrease number of actual pages that needs to be visited when looking thru the obj lut. + +* Logical number of each block. When moving stuff in a garbage collected page, the free + page is assigned the same number as the garbage collected. Thus, object index pages do not have to + be rewritten. + +* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit + as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a + check is automatically run. \ No newline at end of file diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/flashmem.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/flashmem.h deleted file mode 100755 index c4f4252a1..000000000 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/flashmem.h +++ /dev/null @@ -1,73 +0,0 @@ -// Based on NodeMCU platform_flash -// https://github.com/nodemcu/nodemcu-firmware - -#ifndef SYSTEM_FLASHMEM_H_ -#define SYSTEM_FLASHMEM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "spiffs.h" -#include "spi_flash.h" - -#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4 -#define INTERNAL_FLASH_READ_UNIT_SIZE 4 - -#define FLASH_TOTAL_SEC_COUNT (flashmem_get_size_sectors()) - -#define SYS_PARAM_SEC_COUNT 4 -#define FLASH_WORK_SEC_COUNT (FLASH_TOTAL_SEC_COUNT - SYS_PARAM_SEC_COUNT) - -#define INTERNAL_FLASH_SECTOR_SIZE SPI_FLASH_SEC_SIZE -#define INTERNAL_FLASH_SIZE ( (FLASH_WORK_SEC_COUNT) * INTERNAL_FLASH_SECTOR_SIZE ) -#define INTERNAL_FLASH_START_ADDRESS 0x40200000 - -typedef struct -{ - uint8_t unknown0; - uint8_t unknown1; - enum - { - MODE_QIO = 0, - MODE_QOUT = 1, - MODE_DIO = 2, - MODE_DOUT = 15, - } mode : 8; - enum - { - SPEED_40MHZ = 0, - SPEED_26MHZ = 1, - SPEED_20MHZ = 2, - SPEED_80MHZ = 15, - } speed : 4; - enum - { - SIZE_4MBIT = 0, - SIZE_2MBIT = 1, - SIZE_8MBIT = 2, - SIZE_16MBIT = 3, - SIZE_32MBIT = 4, - } size : 4; -} STORE_TYPEDEF_ATTR SPIFlashInfo; - -extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ); -extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ); -extern bool flashmem_erase_sector( uint32_t sector_id ); - -extern SPIFlashInfo flashmem_get_info(); -extern uint8_t flashmem_get_size_type(); -extern uint32_t flashmem_get_size_bytes(); -extern uint16_t flashmem_get_size_sectors(); -uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend ); -uint32_t flashmem_get_sector_of_address( uint32_t addr ); - -extern uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ); -extern uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ); -extern uint32_t flashmem_get_first_free_block_address(); - -#ifdef __cplusplus -} -#endif - -#endif /* SYSTEM_FLASHMEM_H_ */ diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c deleted file mode 100755 index 74a65e05d..000000000 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "spiffs.h" - -#define LOG_PAGE_SIZE 256 - -spiffs _filesystemStorageHandle; - -static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2]; -static u8_t spiffs_fds[32*4]; -static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*4]; - -static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){ - flashmem_read(dst, addr, size); - return SPIFFS_OK; -} - -static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){ - flashmem_write(src, addr, size); - return SPIFFS_OK; -} - -static s32_t api_spiffs_erase(u32_t addr, u32_t size){ - debugf("api_spiffs_erase"); - u32_t sect_first = flashmem_get_sector_of_address(addr); - u32_t sect_last = flashmem_get_sector_of_address(addr+size); - while( sect_first <= sect_last ) - if( !flashmem_erase_sector( sect_first ++ ) ) - return SPIFFS_ERR_INTERNAL; - return SPIFFS_OK; -} - -/******************* -The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. -Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or -the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively. -The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage. -********************/ - -extern uint32_t _SPIFFS_start; -extern uint32_t _SPIFFS_end; - -spiffs_config spiffs_get_storage_config() -{ - spiffs_config cfg = {0}; - if ((u32_t)&_SPIFFS_start == 0) return cfg; - cfg.phys_addr = (u32_t)&_SPIFFS_start; - cfg.phys_size = (u32_t)((u32_t)&_SPIFFS_end - (u32_t)&_SPIFFS_start); - cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet - cfg.log_block_size = INTERNAL_FLASH_SECTOR_SIZE * 2; // Important to make large - cfg.log_page_size = LOG_PAGE_SIZE; // as we said - return cfg; -} - -bool spiffs_format_internal(){ - spiffs_config cfg = spiffs_get_storage_config(); - if (cfg.phys_addr == 0){ - SYSTEM_ERROR("Can't format file system, wrong address"); - return false; - } - - u32_t sect_first, sect_last; - sect_first = flashmem_get_sector_of_address((u32_t)&_SPIFFS_start); - sect_last = flashmem_get_sector_of_address((u32_t)&_SPIFFS_end); - debugf("sect_first: %x, sect_last: %x\n", sect_first, sect_last); - while( sect_first <= sect_last ){ - if(!flashmem_erase_sector( sect_first ++ )) - return false; - } - return true; -} - -bool spiffs_mount_internal(bool wipe){ - spiffs_config cfg = spiffs_get_storage_config(); - if (cfg.phys_addr == 0){ - SYSTEM_ERROR("Can't start file system, wrong address"); - return false; - } - - debugf("fs.start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024); - - cfg.hal_read_f = api_spiffs_read; - cfg.hal_write_f = api_spiffs_write; - cfg.hal_erase_f = api_spiffs_erase; - - uint32_t dat; - bool writeFirst = false; - flashmem_read(&dat, cfg.phys_addr, 4); - - if (dat == UINT32_MAX || wipe){ - debugf("First init file system"); - if(!spiffs_format_internal()){ - SYSTEM_ERROR("Can't format file system"); - return false; - } - writeFirst = true; - } - - int res = SPIFFS_mount(&_filesystemStorageHandle, - &cfg, - spiffs_work_buf, - spiffs_fds, - sizeof(spiffs_fds), - spiffs_cache, - sizeof(spiffs_cache), - NULL); - debugf("mount res: %d\n", res); - - if(res != 0) return false; - - if (writeFirst){ - file_t fd = SPIFFS_open(&_filesystemStorageHandle, "initialize_fs_header.dat", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); - SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"1", 1); - SPIFFS_fremove(&_filesystemStorageHandle, fd); - SPIFFS_close(&_filesystemStorageHandle, fd); - } - return true; -} - -bool spiffs_mount(){ - return spiffs_mount_internal(false); -} - -void spiffs_unmount(){ - SPIFFS_unmount(&_filesystemStorageHandle); -} - -bool spiffs_format(){ - spiffs_unmount(); - return spiffs_mount_internal(true); -} - -void test_spiffs(){ - char buf[12] = {0}; - spiffs_file fd; - spiffs_stat st = {0}; - SPIFFS_stat(&_filesystemStorageHandle, "my_file.txt", &st); - if (st.size <= 0){ - fd = SPIFFS_open(&_filesystemStorageHandle, "my_file.txt", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); - if (SPIFFS_write(&_filesystemStorageHandle, fd, (u8_t *)"Hello world", 11) < 0) - debugf("errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); - SPIFFS_close(&_filesystemStorageHandle, fd); - debugf("file created"); - } else debugf("file %s exist :)", st.name); - - fd = SPIFFS_open(&_filesystemStorageHandle, "my_file.txt", SPIFFS_RDWR, 0); - if (SPIFFS_read(&_filesystemStorageHandle, fd, (u8_t *)buf, 11) < 0) debugf("errno %d\n", SPIFFS_errno(&_filesystemStorageHandle)); - SPIFFS_close(&_filesystemStorageHandle, fd); - debugf("--> %s <--\n", buf); -} diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.h old mode 100755 new mode 100644 index 6357b44a7..7df7ae049 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs.h @@ -5,15 +5,15 @@ * Author: petera */ + + #ifndef SPIFFS_H_ #define SPIFFS_H_ - #ifdef __cplusplus extern "C" { #endif #include "spiffs_config.h" -#include "flashmem.h" #define SPIFFS_OK 0 #define SPIFFS_ERR_NOT_MOUNTED -10000 @@ -40,6 +40,13 @@ extern "C" { #define SPIFFS_ERR_NOT_WRITABLE -10021 #define SPIFFS_ERR_NOT_READABLE -10022 #define SPIFFS_ERR_CONFLICTING_NAME -10023 +#define SPIFFS_ERR_NOT_CONFIGURED -10024 + +#define SPIFFS_ERR_NOT_A_FS -10025 +#define SPIFFS_ERR_MOUNTED -10026 +#define SPIFFS_ERR_ERASE_FAIL -10027 +#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028 + #define SPIFFS_ERR_INTERNAL -10050 @@ -81,19 +88,21 @@ typedef enum { } spiffs_check_report; /* file system check callback function */ -typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, u32_t arg1, u32_t arg2); +typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, + u32_t arg1, u32_t arg2); #ifndef SPIFFS_DBG -#define SPIFFS_DBG(...) printf(__VA_ARGS__) +#define SPIFFS_DBG(...) \ + print(__VA_ARGS__) #endif #ifndef SPIFFS_GC_DBG -#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__) +#define SPIFFS_GC_DBG(...) c_printf(__VA_ARGS__) #endif #ifndef SPIFFS_CACHE_DBG -#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__) +#define SPIFFS_CACHE_DBG(...) c_printf(__VA_ARGS__) #endif #ifndef SPIFFS_CHECK_DBG -#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__) +#define SPIFFS_CHECK_DBG(...) c_printf(__VA_ARGS__) #endif /* Any write to the filehandle is appended to end of the file */ @@ -182,7 +191,7 @@ typedef struct { u32_t fd_count; // last error - s32_t errno; + s32_t err_code; // current number of free blocks u32_t free_blocks; @@ -212,6 +221,11 @@ typedef struct { // check callback function spiffs_check_callback check_cb_f; + + // mounted flag + u8_t mounted; + // config magic + u32_t config_magic; } spiffs; /* spiffs file status struct */ @@ -239,7 +253,10 @@ typedef struct { // functions /** - * Initializes the file system dynamic parameters and mounts the filesystem + * Initializes the file system dynamic parameters and mounts the filesystem. + * If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS + * if the flash does not contain a recognizable file system. + * In this case, SPIFFS_format must be called prior to remounting. * @param fs the file system struct * @param config the physical and logical configuration of the file system * @param work a memory work buffer comprising 2*config->log_page_size @@ -268,7 +285,7 @@ void SPIFFS_unmount(spiffs *fs); * @param path the path of the new file * @param mode ignored, for posix compliance */ -s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode); +s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode); /** * Opens/creates a file. @@ -279,7 +296,8 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode); * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT * @param mode ignored, for posix compliance */ -spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode); +spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode); + /** * Opens a file by given dir entry. @@ -304,7 +322,7 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl * @param len how much to read * @returns number of bytes read, or -1 if error */ -s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len); +s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len); /** * Writes to given filehandle. @@ -314,7 +332,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len); * @param len how much to write * @returns number of bytes written, or -1 if error */ -s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len); +s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len); /** * Moves the read/write file offset @@ -332,7 +350,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence); * @param fs the file system struct * @param path the path of the file to remove */ -s32_t SPIFFS_remove(spiffs *fs, const char *path); +s32_t SPIFFS_remove(spiffs *fs, char *path); /** * Removes a file by filehandle @@ -347,7 +365,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh); * @param path the path of the file to stat * @param s the stat struct to populate */ -s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s); +s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s); /** * Gets file status by filehandle @@ -375,9 +393,9 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh); * Renames a file * @param fs the file system struct * @param old path of file to rename - * @param new new path of file + * @param newPath new path of file */ -s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname); +s32_t SPIFFS_rename(spiffs *fs, char *old, char *newPath); /** * Returns last error of last file operation. @@ -385,6 +403,12 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname); */ s32_t SPIFFS_errno(spiffs *fs); +/** + * Clears last error. + * @param fs the file system struct + */ +void SPIFFS_clearerr(spiffs *fs); + /** * Opens a directory stream corresponding to the given name. * The stream is positioned at the first entry in the directory. @@ -394,7 +418,7 @@ s32_t SPIFFS_errno(spiffs *fs); * @param name the name of the directory * @param d pointer the directory stream to be populated */ -spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d); +spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d); /** * Closes a directory stream @@ -416,12 +440,51 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e); */ s32_t SPIFFS_check(spiffs *fs); + +/** + * Returns number of total bytes available and number of used bytes. + * This is an estimation, and depends on if there a many files with little + * data or few files with much data. + * NB: If used number of bytes exceeds total bytes, a SPIFFS_check should + * run. This indicates a power loss in midst of things. In worst case + * (repeated powerlosses in mending or gc) you might have to delete some files. + * + * @param fs the file system struct + * @param total total number of bytes in filesystem + * @param used used number of bytes in filesystem + */ +s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used); + +/** + * Formats the entire file system. All data will be lost. + * The filesystem must not be mounted when calling this. + * + * NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount + * MUST be called prior to formatting in order to configure the filesystem. + * If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling + * SPIFFS_format. + * If SPIFFS_mount fails, SPIFFS_format can be called directly without calling + * SPIFFS_unmount first. + */ +s32_t SPIFFS_format(spiffs *fs); + +/** + * Returns nonzero if spiffs is mounted, or zero if unmounted. + */ +u8_t SPIFFS_mounted(spiffs *fs); + /** * Check if EOF reached. * @param fs the file system struct * @param fh the filehandle of the file to check */ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh); + +/** + * Get the current position of the data pointer. + * @param fs the file system struct + * @param fh the filehandle of the open file + */ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh); #if SPIFFS_TEST_VISUALISATION @@ -448,19 +511,10 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages); #endif #endif -#if SPIFFS_CACHE -#endif - - -bool spiffs_mount(); -void spiffs_unmount(); -bool spiffs_format(); -spiffs_config spiffs_get_storage_config(); -extern void test_spiffs(); - -extern spiffs _filesystemStorageHandle; +#include "spiffs_esp8266.h" #ifdef __cplusplus } #endif + #endif /* SPIFFS_H_ */ diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_cache.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_cache.c old mode 100755 new mode 100644 diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_check.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_check.c old mode 100755 new mode 100644 index aad355122..50bbb5c89 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_check.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_check.c @@ -597,7 +597,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) { data_spix_offset + i, data_pix, cur_pix); if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("PA: FIXUP: index bad %u, cannot mend - delete object\n", res); + SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend - delete object\n", res); if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0); // delete file res = spiffs_page_delete(fs, cur_pix); @@ -763,7 +763,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) { res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix); if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("PA: FIXUP: index bad %u, cannot mend!\n", res); + SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend!\n", res); if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); res = spiffs_page_delete(fs, cur_pix); SPIFFS_CHECK_RES(res); diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h old mode 100755 new mode 100644 index 095bef900..d59ac80b1 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_config.h @@ -8,24 +8,11 @@ #ifndef SPIFFS_CONFIG_H_ #define SPIFFS_CONFIG_H_ -// ----------- 8< ------------ -// Following includes are for the linux test build of spiffs -// These may/should/must be removed/altered/replaced in your target -// #include "params_test.h" -//#include "c_stdio.h" -//#include "c_stdlib.h" -//#include "c_string.h" #include "mem.h" #include "c_types.h" #include "stddef.h" #include "osapi.h" #include "ets_sys.h" -// ----------- >8 ------------ -#define IRAM_ATTR __attribute__((section(".iram.text"))) -#define STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed)) -#define STORE_ATTR __attribute__((aligned(4))) - -#define SPIFFS_CHACHE 0 #define c_memcpy os_memcpy #define c_printf os_printf @@ -56,24 +43,22 @@ typedef uint8_t u8_t; #endif // compile time switches -#define debugf(fmt, ...) //os_printf(fmt"\r\n", ##__VA_ARGS__) -#define SYSTEM_ERROR(fmt, ...) //os_printf("ERROR: " fmt "\r\n", ##__VA_ARGS__) // Set generic spiffs debug output call. #ifndef SPIFFS_DGB -#define SPIFFS_DBG(...) //os_printf(__VA_ARGS__) +#define SPIFFS_DBG(...) //c_printf(__VA_ARGS__) #endif // Set spiffs debug output call for garbage collecting. #ifndef SPIFFS_GC_DGB -#define SPIFFS_GC_DBG(...) //os_printf(__VA_ARGS__) +#define SPIFFS_GC_DBG(...) //c_printf(__VA_ARGS__) #endif // Set spiffs debug output call for caching. #ifndef SPIFFS_CACHE_DGB -#define SPIFFS_CACHE_DBG(...) //os_printf(__VA_ARGS__) +#define SPIFFS_CACHE_DBG(...) //c_printf(__VA_ARGS__) #endif // Set spiffs debug output call for system consistency checks. #ifndef SPIFFS_CHECK_DGB -#define SPIFFS_CHECK_DBG(...) //os_printf(__VA_ARGS__) +#define SPIFFS_CHECK_DBG(...) //c_printf(__VA_ARGS__) #endif // Enable/disable API functions to determine exact number of bytes @@ -108,7 +93,7 @@ typedef uint8_t u8_t; // Define maximum number of gc runs to perform to reach desired free pages. #ifndef SPIFFS_GC_MAX_RUNS -#define SPIFFS_GC_MAX_RUNS 3 +#define SPIFFS_GC_MAX_RUNS 5 #endif // Enable/disable statistics on gc. Debug/test purpose only. @@ -150,14 +135,22 @@ typedef uint8_t u8_t; #define SPIFFS_COPY_BUFFER_STACK (64) #endif +// Enable this to have an identifiable spiffs filesystem. This will look for +// a magic in all sectors to determine if this is a valid spiffs system or +// not on mount point. If not, SPIFFS_format must be called prior to mounting +// again. +#ifndef SPIFFS_USE_MAGIC +#define SPIFFS_USE_MAGIC (0) +#endif + // SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level // These should be defined on a multithreaded system -// define this to entering a mutex if you're running on a multithreaded system +// define this to enter a mutex if you're running on a multithreaded system #ifndef SPIFFS_LOCK #define SPIFFS_LOCK(fs) #endif -// define this to exiting a mutex if you're running on a multithreaded system +// define this to exit a mutex if you're running on a multithreaded system #ifndef SPIFFS_UNLOCK #define SPIFFS_UNLOCK(fs) #endif @@ -190,7 +183,12 @@ typedef uint8_t u8_t; #endif #endif -// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function +// Enable this if your target needs aligned data for index tables +#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES +#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1 +#endif + +// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function // in the api. This function will visualize all filesystem using given printf // function. #ifndef SPIFFS_TEST_VISUALISATION diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.c new file mode 100644 index 000000000..56cf3813c --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.c @@ -0,0 +1,224 @@ +#include "spiffs_esp8266.h" +#include "spi_flash.h" +#include "esp8266_peri.h" +#include "Arduino.h" + +/* + FLASH ACCESS FUNCTIONS +*/ + +//lowest level sector erase method +bool flashmem_erase_sector( uint32_t sector_id ){ + WDT_RESET(); + noInterrupts(); + bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; + interrupts(); + return erased; +} + +//lowest level data write method +uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ){ + toaddr -= INTERNAL_FLASH_START_ADDRESS; + SpiFlashOpResult r; + const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; + uint32_t *apbuf = NULL; + if(((uint32_t)from) & blkmask){ + apbuf = (uint32_t *)os_malloc(size); + if(!apbuf) + return 0; + os_memcpy(apbuf, from, size); + } + WDT_RESET(); + noInterrupts(); + r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); + interrupts(); + if(apbuf) + os_free(apbuf); + if(SPI_FLASH_RESULT_OK == r) + return size; + else{ + SPIFFS_API_DBG_E( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS ); + return 0; + } +} + +//lowest level data read method +uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ){ + fromaddr -= INTERNAL_FLASH_START_ADDRESS; + SpiFlashOpResult r; + WDT_RESET(); + noInterrupts(); + r = spi_flash_read(fromaddr, (uint32 *)to, size); + interrupts(); + if(SPI_FLASH_RESULT_OK == r) + return size; + else{ + SPIFFS_API_DBG_E( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS ); + return 0; + } +} + +//mid level data write method +uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ){ + uint32_t temp, rest, ssize = size; + unsigned i; + char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ]; + const uint8_t *pfrom = ( const uint8_t* )from; + const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE; + const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; + + // Align the start + if(toaddr & blkmask){ + rest = toaddr & blkmask; + temp = toaddr & ~blkmask; // this is the actual aligned address + // c_memcpy( tmpdata, ( const void* )temp, blksize ); + flashmem_read_internal( tmpdata, temp, blksize ); + for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ ) + tmpdata[ i ] = *pfrom; + flashmem_write_internal( tmpdata, temp, blksize ); + if( size == 0 ) + return ssize; + toaddr = temp + blksize; + } + // The start address is now a multiple of blksize + // Compute how many bytes we can write as multiples of blksize + rest = size & blkmask; + temp = size & ~blkmask; + // Program the blocks now + if(temp){ + flashmem_write_internal( pfrom, toaddr, temp ); + toaddr += temp; + pfrom += temp; + } + // And the final part of a block if needed + if(rest){ + // c_memcpy( tmpdata, ( const void* )toaddr, blksize ); + flashmem_read_internal( tmpdata, toaddr, blksize ); + for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ ) + tmpdata[ i ] = *pfrom; + flashmem_write_internal( tmpdata, toaddr, blksize ); + } + return ssize; +} + +//mid level data write method +uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){ + uint32_t temp, rest, ssize = size; + unsigned i; + char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ]; + uint8_t *pto = ( uint8_t* )to; + const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE; + const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1; + + // Align the start + if(fromaddr & blkmask){ + rest = fromaddr & blkmask; + temp = fromaddr & ~blkmask; // this is the actual aligned address + flashmem_read_internal( tmpdata, temp, blksize ); + for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ ) + *pto = tmpdata[ i ]; + + if( size == 0 ) + return ssize; + fromaddr = temp + blksize; + } + // The start address is now a multiple of blksize + // Compute how many bytes we can read as multiples of blksize + rest = size & blkmask; + temp = size & ~blkmask; + // Program the blocks now + if(temp){ + flashmem_read_internal( pto, fromaddr, temp ); + fromaddr += temp; + pto += temp; + } + // And the final part of a block if needed + if(rest){ + flashmem_read_internal( tmpdata, fromaddr, blksize ); + for( i = 0; size && ( i < rest ); i ++, size --, pto ++ ) + *pto = tmpdata[ i ]; + } + return ssize; +} + +//shorthand when start and end addresses of the sector are not needed +uint32_t flashmem_get_sector_of_address( uint32_t addr ){ + return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;; +} + +/* + SPIFFS BOOTSTRAP +*/ + +//SPIFFS Address Range (defined in eagle ld) +extern uint32_t _SPIFFS_start; +extern uint32_t _SPIFFS_end; + +//SPIFFS Storage Handle +spiffs _filesystemStorageHandle; + +//SPIFFS Buffers (INTERNAL_FLASH_PAGE_SIZE = 256) Total 1792 bytes +static u8_t spiffs_work_buf[INTERNAL_FLASH_PAGE_SIZE*2]; //512 bytes +static u8_t spiffs_fds[32*4]; //128 bytes +static u8_t spiffs_cache[(INTERNAL_FLASH_PAGE_SIZE+32)*4]; //1152 bytes + +//SPIFFS API Read CallBack +static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){ + SPIFFS_API_DBG_V("api_spiffs_read: 0x%08x len: %u\n", addr, size); + flashmem_read(dst, addr, size); + return SPIFFS_OK; +} + +//SPIFFS API Write CallBack +static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){ + SPIFFS_API_DBG_V("api_spiffs_write: 0x%08x len: %u\n", addr, size); + flashmem_write(src, addr, size); + return SPIFFS_OK; +} + +//SPIFFS API Erase CallBack +static s32_t api_spiffs_erase(u32_t addr, u32_t size){ + SPIFFS_API_DBG_V("api_spiffs_erase: 0x%08x len: %u\n", addr, size); + u32_t sect_first = flashmem_get_sector_of_address(addr); + u32_t sect_last = flashmem_get_sector_of_address(addr+size); + while( sect_first <= sect_last ) + if( !flashmem_erase_sector( sect_first ++ ) ) + return SPIFFS_ERR_INTERNAL; + return SPIFFS_OK; +} + +// Our own SPIFFS Setup Method +// All of the above gets put in the configuration +// and a mount attempt is made, initializing the storage handle +// that is used in all further api calls +s32_t spiffs_mount(){ + u32_t start_address = (u32_t)&_SPIFFS_start; + u32_t end_address = (u32_t)&_SPIFFS_end; + if (start_address == 0 || start_address >= end_address){ + SPIFFS_API_DBG_E("Can't start file system, wrong address"); + return SPIFFS_ERR_NOT_CONFIGURED; + } + + spiffs_config cfg = {0}; + cfg.phys_addr = start_address; + cfg.phys_size = end_address - start_address; + cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; // according to datasheet + cfg.log_block_size = INTERNAL_FLASH_SECTOR_SIZE * 2; // Important to make large + cfg.log_page_size = INTERNAL_FLASH_PAGE_SIZE; // according to datasheet + cfg.hal_read_f = api_spiffs_read; + cfg.hal_write_f = api_spiffs_write; + cfg.hal_erase_f = api_spiffs_erase; + + SPIFFS_API_DBG_V("spiffs_mount: start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024); + + s32_t res = SPIFFS_mount(&_filesystemStorageHandle, + &cfg, + spiffs_work_buf, + spiffs_fds, + sizeof(spiffs_fds), + spiffs_cache, + sizeof(spiffs_cache), + NULL); + SPIFFS_API_DBG_V("spiffs_mount: %d\n", res); + return res; +} diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.h new file mode 100644 index 000000000..f36fbfbfe --- /dev/null +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.h @@ -0,0 +1,40 @@ +#ifndef SYSTEM_FLASHMEM_H_ +#define SYSTEM_FLASHMEM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "spiffs.h" + +/******************* +The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. +Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or +the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively. +The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage. +********************/ + +#define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__) +#define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__) + +#define INTERNAL_FLASH_PAGE_SIZE 256 +#define INTERNAL_FLASH_SECTOR_SIZE 4096 +#define INTERNAL_FLASH_START_ADDRESS 0x40200000 + +#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4 +#define INTERNAL_FLASH_READ_UNIT_SIZE 4 + +extern spiffs _filesystemStorageHandle; + +extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ); +extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ); +extern bool flashmem_erase_sector( uint32_t sector_id ); +uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend ); +uint32_t flashmem_get_sector_of_address( uint32_t addr ); +s32_t spiffs_mount(); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_FLASHMEM_H_ */ diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c deleted file mode 100755 index dc875ff12..000000000 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_flashmem.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "flashmem.h" -#include "esp8266_peri.h" -#include "Arduino.h" - -// Based on NodeMCU platform_flash -// https://github.com/nodemcu/nodemcu-firmware - -extern uint32_t _SPIFFS_start; - -uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ) -{ - uint32_t temp, rest, ssize = size; - unsigned i; - char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ]; - const uint8_t *pfrom = ( const uint8_t* )from; - const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE; - const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; - - // Align the start - if( toaddr & blkmask ) - { - rest = toaddr & blkmask; - temp = toaddr & ~blkmask; // this is the actual aligned address - // c_memcpy( tmpdata, ( const void* )temp, blksize ); - flashmem_read_internal( tmpdata, temp, blksize ); - for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ ) - tmpdata[ i ] = *pfrom; - flashmem_write_internal( tmpdata, temp, blksize ); - if( size == 0 ) - return ssize; - toaddr = temp + blksize; - } - // The start address is now a multiple of blksize - // Compute how many bytes we can write as multiples of blksize - rest = size & blkmask; - temp = size & ~blkmask; - // Program the blocks now - if( temp ) - { - flashmem_write_internal( pfrom, toaddr, temp ); - toaddr += temp; - pfrom += temp; - } - // And the final part of a block if needed - if( rest ) - { - // c_memcpy( tmpdata, ( const void* )toaddr, blksize ); - flashmem_read_internal( tmpdata, toaddr, blksize ); - for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ ) - tmpdata[ i ] = *pfrom; - flashmem_write_internal( tmpdata, toaddr, blksize ); - } - return ssize; -} - -uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ) -{ - uint32_t temp, rest, ssize = size; - unsigned i; - char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ]; - uint8_t *pto = ( uint8_t* )to; - const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE; - const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1; - - // Align the start - if( fromaddr & blkmask ) - { - rest = fromaddr & blkmask; - temp = fromaddr & ~blkmask; // this is the actual aligned address - flashmem_read_internal( tmpdata, temp, blksize ); - for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ ) - *pto = tmpdata[ i ]; - - if( size == 0 ) - return ssize; - fromaddr = temp + blksize; - } - // The start address is now a multiple of blksize - // Compute how many bytes we can read as multiples of blksize - rest = size & blkmask; - temp = size & ~blkmask; - // Program the blocks now - if( temp ) - { - flashmem_read_internal( pto, fromaddr, temp ); - fromaddr += temp; - pto += temp; - } - // And the final part of a block if needed - if( rest ) - { - flashmem_read_internal( tmpdata, fromaddr, blksize ); - for( i = 0; size && ( i < rest ); i ++, size --, pto ++ ) - *pto = tmpdata[ i ]; - } - return ssize; -} - -SPIFlashInfo flashmem_get_info() -{ - volatile SPIFlashInfo spi_flash_info STORE_ATTR; - spi_flash_info = *((SPIFlashInfo *)(INTERNAL_FLASH_START_ADDRESS)); - return spi_flash_info; -} - -uint8_t flashmem_get_size_type() -{ - return flashmem_get_info().size; -} - -uint32_t flashmem_get_size_bytes() -{ - uint32_t flash_size = 0; - switch (flashmem_get_info().size) - { - case SIZE_2MBIT: - // 2Mbit, 256kByte - flash_size = 256 * 1024; - break; - case SIZE_4MBIT: - // 4Mbit, 512kByte - flash_size = 512 * 1024; - break; - case SIZE_8MBIT: - // 8Mbit, 1MByte - flash_size = 1 * 1024 * 1024; - break; - case SIZE_16MBIT: - // 16Mbit, 2MByte - flash_size = 2 * 1024 * 1024; - break; - case SIZE_32MBIT: - // 32Mbit, 4MByte - flash_size = 4 * 1024 * 1024; - break; - default: - // Unknown flash size, fall back mode. - flash_size = 512 * 1024; - break; - } - return flash_size; -} - -uint16_t flashmem_get_size_sectors() -{ - return flashmem_get_size_bytes() / SPI_FLASH_SEC_SIZE; -} - -// Helper function: find the flash sector in which an address resides -// Return the sector number, as well as the start and end address of the sector -uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend ) -{ - address -= INTERNAL_FLASH_START_ADDRESS; - // All the sectors in the flash have the same size, so just align the address - uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE; - - if( pstart ) - *pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS; - if( pend ) - *pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS - 1; - return sect_id; -} - -uint32_t flashmem_get_sector_of_address( uint32_t addr ) -{ - return flashmem_find_sector( addr, NULL, NULL ); -} - -///////////////////////////////////////////////////// - -bool flashmem_erase_sector( uint32_t sector_id ) -{ - WDT_RESET(); - noInterrupts(); - bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; - interrupts(); - return erased; -} - -uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ) -{ - toaddr -= INTERNAL_FLASH_START_ADDRESS; - SpiFlashOpResult r; - const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; - uint32_t *apbuf = NULL; - if( ((uint32_t)from) & blkmask ){ - apbuf = (uint32_t *)os_malloc(size); - if(!apbuf) - return 0; - os_memcpy(apbuf, from, size); - } - WDT_RESET(); - noInterrupts(); - r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); - interrupts(); - if(apbuf) - os_free(apbuf); - if(SPI_FLASH_RESULT_OK == r) - return size; - else{ - SYSTEM_ERROR( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS ); - return 0; - } -} - -uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ) -{ - fromaddr -= INTERNAL_FLASH_START_ADDRESS; - SpiFlashOpResult r; - WDT_RESET(); - noInterrupts(); - r = spi_flash_read(fromaddr, (uint32 *)to, size); - interrupts(); - if(SPI_FLASH_RESULT_OK == r) - return size; - else{ - SYSTEM_ERROR( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS ); - return 0; - } -} - -uint32_t flashmem_get_first_free_block_address(){ - if ((uint32_t)&_SPIFFS_start == 0){ - return 0; - } - debugf("_SPIFFS_start:%08x\n", (uint32_t)&_SPIFFS_start); - - // Round the total used flash size to the closest flash block address - uint32_t end; - flashmem_find_sector( (uint32_t)&_SPIFFS_start - 1, NULL, &end); - return end + 1; -} diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_gc.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_gc.c old mode 100755 new mode 100644 index 6145084dc..87e4faf90 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_gc.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_gc.c @@ -8,31 +8,11 @@ static s32_t spiffs_gc_erase_block( spiffs *fs, spiffs_block_ix bix) { s32_t res; - u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix); - s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs); SPIFFS_GC_DBG("gc: erase block %d\n", bix); - - // here we ignore res, just try erasing the block - while (size > 0) { - SPIFFS_GC_DBG("gc: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); - (void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); - addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs); - size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs); - } - fs->free_blocks++; - - // register erase count for this block - res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0, - SPIFFS_ERASE_COUNT_PADDR(fs, bix), - sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count); + res = spiffs_erase_block(fs, bix); SPIFFS_CHECK_RES(res); - fs->max_erase_count++; - if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) { - fs->max_erase_count = 0; - } - #if SPIFFS_CACHE { u32_t i; @@ -119,17 +99,25 @@ s32_t spiffs_gc_check( spiffs *fs, u32_t len) { s32_t res; - u32_t free_pages = - (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count + s32_t free_pages = + (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count-2) - fs->stats_p_allocated - fs->stats_p_deleted; int tries = 0; if (fs->free_blocks > 3 && - len < free_pages * SPIFFS_DATA_PAGE_SIZE(fs)) { + (s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) { return SPIFFS_OK; } - //printf("gcing started %d dirty, blocks %d free, want %d bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len); + u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs); +// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) { +// SPIFFS_GC_DBG("gc: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); +// return SPIFFS_ERR_FULL; +// } + if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) { + SPIFFS_GC_DBG("gc_check: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); + return SPIFFS_ERR_FULL; + } do { SPIFFS_GC_DBG("\ngc_check #%d: run gc free_blocks:%d pfree:%d pallo:%d pdele:%d [%d] len:%d of %d\n", @@ -140,18 +128,20 @@ s32_t spiffs_gc_check( spiffs_block_ix *cands; int count; spiffs_block_ix cand; - res = spiffs_gc_find_candidate(fs, &cands, &count); + s32_t prev_free_pages = free_pages; + // if the fs is crammed, ignore block age when selecting candidate - kind of a bad state + res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0); SPIFFS_CHECK_RES(res); if (count == 0) { SPIFFS_GC_DBG("gc_check: no candidates, return\n"); - return res; + return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL; } #if SPIFFS_GC_STATS fs->stats_gc_runs++; #endif cand = cands[0]; fs->cleaning = 1; - //printf("gcing: cleaning block %d\n", cand); + //c_printf("gcing: cleaning block %d\n", cand); res = spiffs_gc_clean(fs, cand); fs->cleaning = 0; if (res < 0) { @@ -168,16 +158,28 @@ s32_t spiffs_gc_check( SPIFFS_CHECK_RES(res); free_pages = - (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count + (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2) - fs->stats_p_allocated - fs->stats_p_deleted; - } while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 || - len > free_pages*SPIFFS_DATA_PAGE_SIZE(fs))); - SPIFFS_GC_DBG("gc_check: finished\n"); + if (prev_free_pages <= 0 && prev_free_pages == free_pages) { + // abort early to reduce wear, at least tried once + SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n"); + break; + } - //printf("gcing finished %d dirty, blocks %d free, %d pages free, %d tries, res %d\n", - // fs->stats_p_allocated + fs->stats_p_deleted, - // fs->free_blocks, free_pages, tries, res); + } while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 || + (s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs))); + + free_pages = + (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2) + - fs->stats_p_allocated - fs->stats_p_deleted; + if ((s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) { + res = SPIFFS_ERR_FULL; + } + + SPIFFS_GC_DBG("gc_check: finished, %d dirty, blocks %d free, %d pages free, %d tries, res %d\n", + fs->stats_p_allocated + fs->stats_p_deleted, + fs->free_blocks, free_pages, tries, res); return res; } @@ -223,7 +225,8 @@ s32_t spiffs_gc_erase_page_stats( s32_t spiffs_gc_find_candidate( spiffs *fs, spiffs_block_ix **block_candidates, - int *candidate_count) { + int *candidate_count, + char fs_crammed) { s32_t res = SPIFFS_OK; u32_t blocks = fs->block_count; spiffs_block_ix cur_block = 0; @@ -249,6 +252,7 @@ s32_t spiffs_gc_find_candidate( while (res == SPIFFS_OK && blocks--) { u16_t deleted_pages_in_block = 0; u16_t used_pages_in_block = 0; + int obj_lookup_page = 0; // check each object lookup page while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) { @@ -295,9 +299,9 @@ s32_t spiffs_gc_find_candidate( s32_t score = deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET + used_pages_in_block * SPIFFS_GC_HEUR_W_USED + - erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE; + erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE); int cand_ix = 0; - SPIFFS_GC_DBG("\ngc_check: bix:%d del:%d use:%d score:%d\n", cur_block, deleted_pages_in_block, used_pages_in_block, score); + SPIFFS_GC_DBG("gc_check: bix:%d del:%d use:%d score:%d\n", cur_block, deleted_pages_in_block, used_pages_in_block, score); while (cand_ix < max_candidates) { if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) { cand_blocks[cand_ix] = cur_block; diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c old mode 100755 new mode 100644 index 36bdcd274..6601b61ad --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c @@ -21,6 +21,36 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) { #endif #endif +u8_t SPIFFS_mounted(spiffs *fs) { + return SPIFFS_CHECK_MOUNT(fs); +} + +s32_t SPIFFS_format(spiffs *fs) { + SPIFFS_API_CHECK_CFG(fs); + if (SPIFFS_CHECK_MOUNT(fs)) { + fs->err_code = SPIFFS_ERR_MOUNTED; + return -1; + } + + s32_t res; + SPIFFS_LOCK(fs); + + spiffs_block_ix bix = 0; + while (bix < fs->block_count) { + fs->max_erase_count = 0; + res = spiffs_erase_block(fs, bix); + if (res != SPIFFS_OK) { + res = SPIFFS_ERR_ERASE_FAIL; + } + SPIFFS_API_CHECK_RES_UNLOCK(fs, res); + bix++; + } + + SPIFFS_UNLOCK(fs); + + return 0; +} + s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, u8_t *fd_space, u32_t fd_space_size, void *cache, u32_t cache_size, @@ -34,10 +64,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, c_memset(fd_space, 0, fd_space_size); // align fd_space pointer to pointer size byte boundary, below is safe u8_t ptr_size = sizeof(void*); -// #pragma GCC diagnostic push -// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast" - u8_t addr_lsb = (u8_t)(((u32_t)fd_space) & (ptr_size-1)); -// #pragma GCC diagnostic pop +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" + u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1); +#pragma GCC diagnostic pop if (addr_lsb) { fd_space += (ptr_size-addr_lsb); fd_space_size -= (ptr_size-addr_lsb); @@ -46,10 +76,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, fs->fd_count = (fd_space_size/sizeof(spiffs_fd)); // align cache pointer to 4 byte boundary, below is safe -// #pragma GCC diagnostic push -// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast" - addr_lsb = (u8_t)(((u32_t)cache) & (ptr_size-1)); -// #pragma GCC diagnostic pop +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" + addr_lsb = ((u8_t)cache) & (ptr_size-1); +#pragma GCC diagnostic pop if (addr_lsb) { u8_t *cache_8 = (u8_t *)cache; cache_8 += (ptr_size-addr_lsb); @@ -65,7 +95,16 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, spiffs_cache_init(fs); #endif - s32_t res = spiffs_obj_lu_scan(fs); + s32_t res; + +#if SPIFFS_USE_MAGIC + res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE; + SPIFFS_API_CHECK_RES_UNLOCK(fs, res); +#endif + + fs->config_magic = SPIFFS_CONFIG_MAGIC; + + res = spiffs_obj_lu_scan(fs); SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_DBG("page index byte len: %d\n", SPIFFS_CFG_LOG_PAGE_SZ(fs)); @@ -79,13 +118,15 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, fs->check_cb_f = check_cb_f; + fs->mounted = 1; + SPIFFS_UNLOCK(fs); return 0; } void SPIFFS_unmount(spiffs *fs) { - if (!SPIFFS_CHECK_MOUNT(fs)) return; + if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return; SPIFFS_LOCK(fs); u32_t i; spiffs_fd *fds = (spiffs_fd *)fs->fd_space; @@ -98,16 +139,22 @@ void SPIFFS_unmount(spiffs *fs) { spiffs_fd_return(fs, cur_fd->file_nbr); } } - fs->block_count = 0; + fs->mounted = 0; + SPIFFS_UNLOCK(fs); } s32_t SPIFFS_errno(spiffs *fs) { - return fs->errno; + return fs->err_code; } -s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) { +void SPIFFS_clearerr(spiffs *fs) { + fs->err_code = SPIFFS_OK; +} + +s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) { (void)mode; + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); spiffs_obj_id obj_id; @@ -121,8 +168,9 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) { return 0; } -spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) { +spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) { (void)mode; + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -181,6 +229,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs } spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -209,7 +258,8 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl return fd->file_nbr; } -s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { +s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -277,7 +327,8 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs } -s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { +s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -314,8 +365,6 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { #endif } - SPIFFS_DBG("SPIFFS_write %d %04x offs:%d len %d\n", fh, fd->obj_id, offset, len); - #if SPIFFS_CACHE_WR if ((fd->flags & SPIFFS_DIRECT) == 0) { if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) { @@ -328,12 +377,13 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page { // boundary violation, write back cache first and allocate new - SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:&04x, boundary viol, offs:%d size:%d\n", + SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:%04x, boundary viol, offs:%d size:%d\n", fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size); res = spiffs_hydro_write(fs, fd, spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size); spiffs_cache_fd_release(fs, fd->cache_page); + SPIFFS_API_CHECK_RES(fs, res); } else { // writing within cache alloc_cpage = 0; @@ -379,6 +429,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size); spiffs_cache_fd_release(fs, fd->cache_page); + SPIFFS_API_CHECK_RES(fs, res); res = spiffs_hydro_write(fs, fd, buf, offset, len); SPIFFS_API_CHECK_RES(fs, res); } @@ -396,6 +447,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) { } s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -439,7 +491,8 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { return 0; } -s32_t SPIFFS_remove(spiffs *fs, const char *path) { +s32_t SPIFFS_remove(spiffs *fs, char *path) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -473,6 +526,7 @@ s32_t SPIFFS_remove(spiffs *fs, const char *path) { } s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -520,7 +574,8 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi return res; } -s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) { +s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -538,6 +593,7 @@ s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) { } s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -580,7 +636,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size); if (res < SPIFFS_OK) { - fs->errno = res; + fs->err_code = res; } spiffs_cache_fd_release(fs, fd->cache_page); } @@ -591,6 +647,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { } s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); s32_t res = SPIFFS_OK; #if SPIFFS_CACHE_WR @@ -604,8 +661,13 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { } void SPIFFS_close(spiffs *fs, spiffs_file fh) { + if (!SPIFFS_CHECK_CFG((fs))) { + (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; + return; + } + if (!SPIFFS_CHECK_MOUNT(fs)) { - fs->errno = SPIFFS_ERR_NOT_MOUNTED; + fs->err_code = SPIFFS_ERR_NOT_MOUNTED; return; } SPIFFS_LOCK(fs); @@ -618,7 +680,8 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh) { SPIFFS_UNLOCK(fs); } -s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) { +s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -628,7 +691,7 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) { s32_t res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)old, &pix_old); SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)newname, &pix_dummy); + res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)new, &pix_dummy); if (res == SPIFFS_ERR_NOT_FOUND) { res = SPIFFS_OK; } else if (res == SPIFFS_OK) { @@ -645,7 +708,7 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) { } SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)newname, + res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new, 0, &pix_dummy); if (res != SPIFFS_OK) { @@ -658,12 +721,19 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newname) { return res; } -spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) { +spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) { (void)name; - if (!SPIFFS_CHECK_MOUNT(fs)) { - fs->errno = SPIFFS_ERR_NOT_MOUNTED; + + if (!SPIFFS_CHECK_CFG((fs))) { + (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; return 0; } + + if (!SPIFFS_CHECK_MOUNT(fs)) { + fs->err_code = SPIFFS_ERR_NOT_MOUNTED; + return 0; + } + d->fs = fs; d->block = 0; d->entry = 0; @@ -707,7 +777,7 @@ static s32_t spiffs_read_dir_v( struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) { if (!SPIFFS_CHECK_MOUNT(d->fs)) { - d->fs->errno = SPIFFS_ERR_NOT_MOUNTED; + d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED; return 0; } SPIFFS_LOCK(fs); @@ -732,19 +802,21 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) { d->entry = entry + 1; ret = e; } else { - d->fs->errno = res; + d->fs->err_code = res; } SPIFFS_UNLOCK(fs); return ret; } s32_t SPIFFS_closedir(spiffs_DIR *d) { + SPIFFS_API_CHECK_CFG(d->fs); SPIFFS_API_CHECK_MOUNT(d->fs); return 0; } s32_t SPIFFS_check(spiffs *fs) { s32_t res; + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -760,7 +832,32 @@ s32_t SPIFFS_check(spiffs *fs) { return res; } +s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) { + s32_t res = SPIFFS_OK; + SPIFFS_API_CHECK_CFG(fs); + SPIFFS_API_CHECK_MOUNT(fs); + SPIFFS_LOCK(fs); + + u32_t pages_per_block = SPIFFS_PAGES_PER_BLOCK(fs); + u32_t blocks = fs->block_count; + u32_t obj_lu_pages = SPIFFS_OBJ_LOOKUP_PAGES(fs); + u32_t data_page_size = SPIFFS_DATA_PAGE_SIZE(fs); + u32_t total_data_pages = (blocks - 2) * (pages_per_block - obj_lu_pages) + 1; // -2 for spare blocks, +1 for emergency page + + if (total) { + *total = total_data_pages * data_page_size; + } + + if (used) { + *used = fs->stats_p_allocated * data_page_size; + } + + SPIFFS_UNLOCK(fs); + return res; +} + s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -780,6 +877,7 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) { } s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) { + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -801,6 +899,7 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) { #if SPIFFS_TEST_VISUALISATION s32_t SPIFFS_vis(spiffs *fs) { s32_t res = SPIFFS_OK; + SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_LOCK(fs); @@ -859,11 +958,14 @@ s32_t SPIFFS_vis(spiffs *fs) { } // per block spiffs_printf("era_cnt_max: %d\n", fs->max_erase_count); - spiffs_printf("last_errno: %d\n", fs->errno); + spiffs_printf("last_errno: %d\n", fs->err_code); spiffs_printf("blocks: %d\n", fs->block_count); spiffs_printf("free_blocks: %d\n", fs->free_blocks); spiffs_printf("page_alloc: %d\n", fs->stats_p_allocated); spiffs_printf("page_delet: %d\n", fs->stats_p_deleted); + u32_t total, used; + SPIFFS_info(fs, &total, &used); + spiffs_printf("used: %d of %d\n", used, total); SPIFFS_UNLOCK(fs); return res; diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.c b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.c old mode 100755 new mode 100644 index e58a9775e..fa75fd8e9 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.c +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.c @@ -142,9 +142,13 @@ s32_t spiffs_obj_lu_find_entry_visitor( cur_block++; cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs); if (cur_block >= fs->block_count) { - // block wrap - cur_block = 0; - cur_block_addr = 0; + if (flags & SPIFFS_VIS_NO_WRAP) { + return SPIFFS_VIS_END; + } else { + // block wrap + cur_block = 0; + cur_block_addr = 0; + } } } @@ -213,6 +217,45 @@ s32_t spiffs_obj_lu_find_entry_visitor( return SPIFFS_VIS_END; } +s32_t spiffs_erase_block( + spiffs *fs, + spiffs_block_ix bix) { + s32_t res; + u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix); + s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs); + + // here we ignore res, just try erasing the block + while (size > 0) { + SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); + (void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); + addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs); + size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs); + } + fs->free_blocks++; + + // register erase count for this block + res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0, + SPIFFS_ERASE_COUNT_PADDR(fs, bix), + sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count); + SPIFFS_CHECK_RES(res); + +#if SPIFFS_USE_MAGIC + // finally, write magic + spiffs_obj_id magic = SPIFFS_MAGIC(fs); + res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0, + SPIFFS_MAGIC_PADDR(fs, bix), + sizeof(spiffs_obj_id), (u8_t *)&magic); + SPIFFS_CHECK_RES(res); +#endif + + fs->max_erase_count++; + if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) { + fs->max_erase_count = 0; + } + + return res; +} + static s32_t spiffs_obj_lu_scan_v( spiffs *fs, @@ -238,40 +281,44 @@ static s32_t spiffs_obj_lu_scan_v( return SPIFFS_VIS_COUNTINUE; } + // Scans thru all obj lu and counts free, deleted and used pages // Find the maximum block erase count +// Checks magic if enabled s32_t spiffs_obj_lu_scan( spiffs *fs) { s32_t res; spiffs_block_ix bix; int entry; +#if SPIFFS_USE_MAGIC + spiffs_block_ix unerased_bix = (spiffs_block_ix)-1; +#endif - fs->free_blocks = 0; - fs->stats_p_allocated = 0; - fs->stats_p_deleted = 0; - - res = spiffs_obj_lu_find_entry_visitor(fs, - 0, - 0, - 0, - 0, - spiffs_obj_lu_scan_v, - 0, - 0, - &bix, - &entry); - - if (res == SPIFFS_VIS_END) { - res = SPIFFS_OK; - } - - SPIFFS_CHECK_RES(res); - + // find out erase count + // if enabled, check magic bix = 0; spiffs_obj_id erase_count_final; spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE; spiffs_obj_id erase_count_max = 0; while (bix < fs->block_count) { +#if SPIFFS_USE_MAGIC + spiffs_obj_id magic; + res = _spiffs_rd(fs, + SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, + 0, SPIFFS_MAGIC_PADDR(fs, bix) , + sizeof(spiffs_obj_id), (u8_t *)&magic); + + SPIFFS_CHECK_RES(res); + if (magic != SPIFFS_MAGIC(fs)) { + if (unerased_bix == (spiffs_block_ix)-1) { + // allow one unerased block as it might be powered down during an erase + unerased_bix = bix; + } else { + // more than one unerased block, bail out + SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS); + } + } +#endif spiffs_obj_id erase_count; res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, @@ -297,6 +344,38 @@ s32_t spiffs_obj_lu_scan( fs->max_erase_count = erase_count_final; +#if SPIFFS_USE_MAGIC + if (unerased_bix != (spiffs_block_ix)-1) { + // found one unerased block, remedy + SPIFFS_DBG("mount: erase block %d\n", bix); + res = spiffs_erase_block(fs, unerased_bix); + SPIFFS_CHECK_RES(res); + } +#endif + + // count blocks + + fs->free_blocks = 0; + fs->stats_p_allocated = 0; + fs->stats_p_deleted = 0; + + res = spiffs_obj_lu_find_entry_visitor(fs, + 0, + 0, + 0, + 0, + spiffs_obj_lu_scan_v, + 0, + 0, + &bix, + &entry); + + if (res == SPIFFS_VIS_END) { + res = SPIFFS_OK; + } + + SPIFFS_CHECK_RES(res); + return res; } @@ -614,7 +693,7 @@ s32_t spiffs_object_create( spiffs_page_object_ix_header oix_hdr; int entry; - res = spiffs_gc_check(fs, 0); + res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs)); SPIFFS_CHECK_RES(res); obj_id |= SPIFFS_OBJ_ID_IX_FLAG; @@ -811,7 +890,17 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { s32_t res = SPIFFS_OK; u32_t written = 0; - res = spiffs_gc_check(fs, len); + SPIFFS_DBG("append: %d bytes @ offs %d of size %d\n", len, offset, fd->size); + + if (offset > fd->size) { + SPIFFS_DBG("append: offset reversed to size\n"); + offset = fd->size; + } + + res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta + if (res != SPIFFS_OK) { + SPIFFS_DBG("append: gc check fail %d\n", res); + } SPIFFS_CHECK_RES(res); spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work; @@ -912,7 +1001,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix); SPIFFS_CHECK_RES(res); } - SPIFFS_DBG("append: %04x found object index at page %04x\n", fd->obj_id, pix); + SPIFFS_DBG("append: %04x found object index at page %04x [fd size %d]\n", fd->obj_id, pix, fd->size); res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work); SPIFFS_CHECK_RES(res); @@ -1003,8 +1092,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { // update size in object header index page res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page); - SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d\n", fd->obj_id - , offset+written, new_objix_hdr_page, 0, written); + SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d, res %d\n", fd->obj_id + , offset+written, new_objix_hdr_page, 0, written, res2); SPIFFS_CHECK_RES(res2); } else { // wrote within object index header page @@ -1042,7 +1131,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) { s32_t res = SPIFFS_OK; u32_t written = 0; - res = spiffs_gc_check(fs, len); + res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); SPIFFS_CHECK_RES(res); spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work; @@ -1308,7 +1397,7 @@ s32_t spiffs_object_truncate( s32_t res = SPIFFS_OK; spiffs *fs = fd->fs; - res = spiffs_gc_check(fs, 0); + res = spiffs_gc_check(fs, remove ? 0 : SPIFFS_DATA_PAGE_SIZE(fs)); SPIFFS_CHECK_RES(res); spiffs_page_ix objix_pix = fd->objix_hdr_pix; @@ -1386,13 +1475,26 @@ s32_t spiffs_object_truncate( ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE; } + SPIFFS_DBG("truncate: got data pix %04x\n", data_pix); + if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) { // delete full data page res = spiffs_page_data_check(fs, fd, data_pix, data_spix); - if (res != SPIFFS_OK) break; + if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) { + SPIFFS_DBG("truncate: err validating data pix %d\n", res); + break; + } + + if (res == SPIFFS_OK) { + res = spiffs_page_delete(fs, data_pix); + if (res != SPIFFS_OK) { + SPIFFS_DBG("truncate: err deleting data pix %d\n", res); + break; + } + } else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) { + res = SPIFFS_OK; + } - res = spiffs_page_delete(fs, data_pix); - if (res != SPIFFS_OK) break; // update current size if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) { cur_size -= SPIFFS_DATA_PAGE_SIZE(fs); diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.h b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.h old mode 100755 new mode 100644 index 9b10d9181..5d905fe90 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.h +++ b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_nucleus.h @@ -131,6 +131,10 @@ #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0) #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1) +#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs))) + +#define SPIFFS_CONFIG_MAGIC (0x20090315) + #if SPIFFS_SINGLETON == 0 #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \ ((fs)->cfg.log_page_size) @@ -189,9 +193,18 @@ // returns data size in a data page #define SPIFFS_DATA_PAGE_SIZE(fs) \ ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) ) -// returns physical address for block's erase count +// returns physical address for block's erase count, +// always in the physical last entry of the last object lookup page #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \ ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) ) +// returns physical address for block's magic, +// always in the physical second last entry of the last object lookup page +#define SPIFFS_MAGIC_PADDR(fs, bix) \ + ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 ) +// checks if there is any room for magic in the object luts +#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \ + ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \ + <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) ) // define helpers object @@ -238,7 +251,10 @@ #define SPIFFS_CHECK_MOUNT(fs) \ - ((fs)->block_count > 0) + ((fs)->mounted != 0) + +#define SPIFFS_CHECK_CFG(fs) \ + ((fs)->config_magic == SPIFFS_CONFIG_MAGIC) #define SPIFFS_CHECK_RES(res) \ do { \ @@ -247,19 +263,25 @@ #define SPIFFS_API_CHECK_MOUNT(fs) \ if (!SPIFFS_CHECK_MOUNT((fs))) { \ - (fs)->errno = SPIFFS_ERR_NOT_MOUNTED; \ + (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \ + return -1; \ + } + +#define SPIFFS_API_CHECK_CFG(fs) \ + if (!SPIFFS_CHECK_CFG((fs))) { \ + (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \ return -1; \ } #define SPIFFS_API_CHECK_RES(fs, res) \ if ((res) < SPIFFS_OK) { \ - (fs)->errno = (res); \ + (fs)->err_code = (res); \ return -1; \ } #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \ if ((res) < SPIFFS_OK) { \ - (fs)->errno = (res); \ + (fs)->err_code = (res); \ SPIFFS_UNLOCK(fs); \ return -1; \ } @@ -381,6 +403,8 @@ typedef struct { // object structs // page header, part of each page except object lookup pages +// NB: this is always aligned when the data page is an object index, +// as in this case struct spiffs_page_object_ix is used typedef struct __attribute(( packed )) { // object id spiffs_obj_id obj_id; @@ -391,7 +415,11 @@ typedef struct __attribute(( packed )) { } spiffs_page_header; // object index header page header -typedef struct __attribute(( packed )) { +typedef struct __attribute(( packed )) +#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES + __attribute(( aligned(sizeof(spiffs_page_ix)) )) +#endif +{ // common page header spiffs_page_header p_hdr; // alignment @@ -400,8 +428,6 @@ typedef struct __attribute(( packed )) { u32_t size; // type of object spiffs_obj_type type; - // alignment2 - u8_t _align2[4 - (sizeof(spiffs_obj_type)&3)==0 ? 4 : (sizeof(spiffs_obj_type)&3)]; // name of object u8_t name[SPIFFS_OBJ_NAME_LEN]; } spiffs_page_object_ix_header; @@ -480,6 +506,10 @@ s32_t spiffs_obj_lu_find_entry_visitor( spiffs_block_ix *block_ix, int *lu_entry); +s32_t spiffs_erase_block( + spiffs *fs, + spiffs_block_ix bix); + // --------------- s32_t spiffs_obj_lu_scan( @@ -627,7 +657,8 @@ s32_t spiffs_gc_erase_page_stats( s32_t spiffs_gc_find_candidate( spiffs *fs, spiffs_block_ix **block_candidate, - int *candidate_count); + int *candidate_count, + char fs_crammed); s32_t spiffs_gc_clean( spiffs *fs, From 049fe1d4a726d6a6e84bd3a5e7484fef5e0a6540 Mon Sep 17 00:00:00 2001 From: ficeto Date: Mon, 18 May 2015 04:57:34 +0300 Subject: [PATCH 31/31] leftovers --- .../esp8266com/esp8266/cores/esp8266/spiffs/docs/IMPLEMENTING | 0 hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TODO | 1 - 2 files changed, 1 deletion(-) delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/IMPLEMENTING delete mode 100755 hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TODO diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/IMPLEMENTING b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/IMPLEMENTING deleted file mode 100755 index e69de29bb..000000000 diff --git a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TODO b/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TODO deleted file mode 100755 index 88709f022..000000000 --- a/hardware/esp8266com/esp8266/cores/esp8266/spiffs/docs/TODO +++ /dev/null @@ -1 +0,0 @@ -* When mending lost pages, also see if they fit into length specified in object index header \ No newline at end of file