From c355f626f24645415b508d7823dbe638ca1dd3e4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 18 Aug 2015 23:38:23 +0300 Subject: [PATCH] Add flash read/write/erase APIs to ESPClass --- cores/esp8266/Esp.cpp | 23 ++++++++++++++++ cores/esp8266/Esp.h | 4 +++ cores/esp8266/Updater.cpp | 52 +++++++++++++++++------------------- cores/esp8266/spiffs_hal.cpp | 47 +++++++++++--------------------- 4 files changed, 67 insertions(+), 59 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index ec7f469da..4b34762af 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -400,3 +400,26 @@ bool EspClass::updateSketch(Stream& in, uint32_t size, bool restartOnFail, bool if(restartOnSuccess) ESP.restart(); return true; } + +static const int FLASH_INT_MASK = ((B10 << 8) | B00111010); + +bool EspClass::flashEraseSector(uint32_t sector) { + ets_isr_mask(FLASH_INT_MASK); + int rc = spi_flash_erase_sector(sector); + ets_isr_unmask(FLASH_INT_MASK); + return rc == 0; +} + +bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size) { + ets_isr_mask(FLASH_INT_MASK); + int rc = spi_flash_write(offset, (uint32_t*) data, size); + ets_isr_unmask(FLASH_INT_MASK); + return rc == 0; +} + +bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size) { + ets_isr_mask(FLASH_INT_MASK); + int rc = spi_flash_read(offset, (uint32_t*) data, size); + ets_isr_unmask(FLASH_INT_MASK); + return rc == 0; +} diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index c7c44aaf0..07e1c093b 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -117,6 +117,10 @@ class EspClass { FlashMode_t getFlashChipMode(); uint32_t getFlashChipSizeByChipId(); + bool flashEraseSector(uint32_t sector); + bool flashWrite(uint32_t offset, uint32_t *data, size_t size); + bool flashRead(uint32_t offset, uint32_t *data, size_t size); + uint32_t getSketchSize(); uint32_t getFreeSketchSpace(); bool updateSketch(Stream& in, uint32_t size, bool restartOnFail = false, bool restartOnSuccess = true); diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index cfce272a8..edd72766b 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -1,18 +1,22 @@ #include "Updater.h" #include "Arduino.h" #include "eboot_command.h" - //#define DEBUG_UPDATER Serial +extern "C" { + #include "c_types.h" + #include "spi_flash.h" +} + extern "C" uint32_t _SPIFFS_start; -UpdaterClass::UpdaterClass() +UpdaterClass::UpdaterClass() : _error(0) , _buffer(0) , _bufferLen(0) , _size(0) , _startAddress(0) -, _currentAddress(0) +, _currentAddress(0) { } @@ -33,7 +37,7 @@ bool UpdaterClass::begin(size_t size){ #endif return false; } - + if(size == 0){ _error = UPDATE_ERROR_SIZE; #ifdef DEBUG_UPDATER @@ -41,10 +45,10 @@ bool UpdaterClass::begin(size_t size){ #endif return false; } - + _reset(); _error = 0; - + //size of current sketch rounded to a sector uint32_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); //address of the end of the space available for sketch and update @@ -53,7 +57,7 @@ bool UpdaterClass::begin(size_t size){ uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); //address where we will start writing the update uint32_t updateStartAddress = updateEndAddress - roundedSize; - + //make sure that the size of both sketches is less than the total space (updateEndAddress) if(updateStartAddress < currentSketchSize){ _error = UPDATE_ERROR_SPACE; @@ -62,13 +66,13 @@ bool UpdaterClass::begin(size_t size){ #endif return false; } - + //initialize _startAddress = updateStartAddress; _currentAddress = _startAddress; _size = size; _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - + return true; } @@ -79,30 +83,30 @@ bool UpdaterClass::end(bool evenIfRemaining){ #endif return false; } - + if(hasError() || (!isFinished() && !evenIfRemaining)){ #ifdef DEBUG_UPDATER DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size); #endif - + _reset(); return false; } - + if(evenIfRemaining){ if(_bufferLen > 0){ _writeBuffer(); } _size = progress(); } - + eboot_command ebcmd; ebcmd.action = ACTION_COPY_RAW; ebcmd.args[0] = _startAddress; ebcmd.args[1] = 0x00000; ebcmd.args[2] = _size; eboot_command_write(&ebcmd); - + #ifdef DEBUG_UPDATER DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size); #endif @@ -112,17 +116,11 @@ bool UpdaterClass::end(bool evenIfRemaining){ } bool UpdaterClass::_writeBuffer(){ - noInterrupts(); - int rc = SPIEraseSector(_currentAddress/FLASH_SECTOR_SIZE); - interrupts(); yield(); - if(!rc){ - noInterrupts(); - rc = SPIWrite(_currentAddress, _buffer, _bufferLen); - interrupts(); - } - interrupts(); - if (rc) { + bool result = ESP.flashEraseSector(_currentAddress/FLASH_SECTOR_SIZE) && + ESP.flashWrite(_currentAddress, (uint32_t*) _buffer, _bufferLen); + + if (!result) { _error = UPDATE_ERROR_WRITE; _currentAddress = (_startAddress + _size); #ifdef DEBUG_UPDATER @@ -139,10 +137,10 @@ size_t UpdaterClass::write(uint8_t *data, size_t len) { size_t left = len; if(hasError() || !isRunning()) return 0; - + if(len > remaining()) len = remaining(); - + while((_bufferLen + left) > FLASH_SECTOR_SIZE) { size_t toBuff = FLASH_SECTOR_SIZE - _bufferLen; memcpy(_buffer + _bufferLen, data + (len - left), toBuff); @@ -170,7 +168,7 @@ size_t UpdaterClass::writeStream(Stream &data) { size_t toRead = 0; if(hasError() || !isRunning()) return 0; - + while(remaining()) { toRead = FLASH_SECTOR_SIZE - _bufferLen; toRead = data.readBytes(_buffer + _bufferLen, toRead); diff --git a/cores/esp8266/spiffs_hal.cpp b/cores/esp8266/spiffs_hal.cpp index 6fab52266..da8828586 100644 --- a/cores/esp8266/spiffs_hal.cpp +++ b/cores/esp8266/spiffs_hal.cpp @@ -23,32 +23,11 @@ #include #include "spiffs/spiffs.h" #include "debug.h" -#include "interrupts.h" extern "C" { #include "c_types.h" #include "spi_flash.h" } - -static int spi_flash_read_locked(uint32_t addr, uint32_t* dst, uint32_t size) { - optimistic_yield(10000); - AutoInterruptLock(5); - return spi_flash_read(addr, dst, size); -} - -static int spi_flash_write_locked(uint32_t addr, const uint32_t* src, uint32_t size) { - optimistic_yield(10000); - AutoInterruptLock(5); - return spi_flash_write(addr, (uint32_t*) src, size); -} - -static int spi_flash_erase_sector_locked(uint32_t sector) { - optimistic_yield(10000); - AutoInterruptLock(5); - return spi_flash_erase_sector(sector); -} - - /* spi_flash_read function requires flash address to be aligned on word boundary. We take care of this by reading first and last words separately and memcpy @@ -64,6 +43,8 @@ alignedEnd: ^ */ int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { + optimistic_yield(10000); + uint32_t result = SPIFFS_OK; uint32_t alignedBegin = (addr + 3) & (~3); uint32_t alignedEnd = (addr + size) & (~3); @@ -71,7 +52,7 @@ int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { if (addr < alignedBegin) { uint32_t nb = alignedBegin - addr; uint32_t tmp; - if (spi_flash_read_locked(alignedBegin - 4, &tmp, 4) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashRead(alignedBegin - 4, &tmp, 4)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -80,8 +61,8 @@ int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { } if (alignedEnd != alignedBegin) { - if (spi_flash_read_locked(alignedBegin, (uint32_t*) (dst + alignedBegin - addr), - alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashRead(alignedBegin, (uint32_t*) (dst + alignedBegin - addr), + alignedEnd - alignedBegin)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -91,7 +72,7 @@ int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { if (addr + size > alignedEnd) { uint32_t nb = addr + size - alignedEnd; uint32_t tmp; - if (spi_flash_read_locked(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashRead(alignedEnd, &tmp, 4)) { DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -116,6 +97,8 @@ int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { static const int UNALIGNED_WRITE_BUFFER_SIZE = 512; int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { + optimistic_yield(10000); + uint32_t alignedBegin = (addr + 3) & (~3); uint32_t alignedEnd = (addr + size) & (~3); @@ -123,7 +106,7 @@ int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { uint32_t nb = alignedBegin - addr; uint32_t tmp = 0xffffffff; memcpy(((uint8_t* )&tmp) + 4 - nb, src, nb); - if (spi_flash_write_locked(alignedBegin - 4, &tmp, 4) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashWrite(alignedBegin - 4, &tmp, 4)) { DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -134,8 +117,8 @@ int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { uint32_t* srcLeftover = (uint32_t*) (src + alignedBegin - addr); uint32_t srcAlign = ((uint32_t) srcLeftover) & 3; if (!srcAlign) { - if (spi_flash_write_locked(alignedBegin, (uint32_t*) srcLeftover, - alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashWrite(alignedBegin, (uint32_t*) srcLeftover, + alignedEnd - alignedBegin)) { DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -147,8 +130,7 @@ int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { size_t willCopy = std::min(sizeLeft, sizeof(buf)); memcpy(buf, srcLeftover, willCopy); - if (spi_flash_write_locked(alignedBegin, (uint32_t*) buf, - willCopy) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashWrite(alignedBegin, (uint32_t*) buf, willCopy)) { DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -166,7 +148,7 @@ int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { uint32_t tmp = 0xffffffff; memcpy(&tmp, src + size - nb, nb); - if (spi_flash_write_locked(alignedEnd, &tmp, 4) != SPI_FLASH_RESULT_OK) { + if (!ESP.flashWrite(alignedEnd, &tmp, 4)) { DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", __LINE__, addr, size, alignedBegin, alignedEnd); return SPIFFS_ERR_INTERNAL; @@ -185,7 +167,8 @@ int32_t spiffs_hal_erase(uint32_t addr, uint32_t size) { const uint32_t sector = addr / SPI_FLASH_SEC_SIZE; const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE; for (uint32_t i = 0; i < sectorCount; ++i) { - if (spi_flash_erase_sector_locked(sector + i) != 0) { + optimistic_yield(10000); + if (!ESP.flashEraseSector(sector + i)) { DEBUGV("_spif_erase addr=%x size=%d i=%d\r\n", addr, size, i); return SPIFFS_ERR_INTERNAL; }