1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +03:00

Add flash read/write/erase APIs to ESPClass

This commit is contained in:
Ivan Grokhotkov 2015-08-18 23:38:23 +03:00
parent fac840b6a8
commit c355f626f2
4 changed files with 67 additions and 59 deletions

View File

@ -400,3 +400,26 @@ bool EspClass::updateSketch(Stream& in, uint32_t size, bool restartOnFail, bool
if(restartOnSuccess) ESP.restart(); if(restartOnSuccess) ESP.restart();
return true; 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;
}

View File

@ -117,6 +117,10 @@ class EspClass {
FlashMode_t getFlashChipMode(); FlashMode_t getFlashChipMode();
uint32_t getFlashChipSizeByChipId(); 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 getSketchSize();
uint32_t getFreeSketchSpace(); uint32_t getFreeSketchSpace();
bool updateSketch(Stream& in, uint32_t size, bool restartOnFail = false, bool restartOnSuccess = true); bool updateSketch(Stream& in, uint32_t size, bool restartOnFail = false, bool restartOnSuccess = true);

View File

@ -1,18 +1,22 @@
#include "Updater.h" #include "Updater.h"
#include "Arduino.h" #include "Arduino.h"
#include "eboot_command.h" #include "eboot_command.h"
//#define DEBUG_UPDATER Serial //#define DEBUG_UPDATER Serial
extern "C" {
#include "c_types.h"
#include "spi_flash.h"
}
extern "C" uint32_t _SPIFFS_start; extern "C" uint32_t _SPIFFS_start;
UpdaterClass::UpdaterClass() UpdaterClass::UpdaterClass()
: _error(0) : _error(0)
, _buffer(0) , _buffer(0)
, _bufferLen(0) , _bufferLen(0)
, _size(0) , _size(0)
, _startAddress(0) , _startAddress(0)
, _currentAddress(0) , _currentAddress(0)
{ {
} }
@ -33,7 +37,7 @@ bool UpdaterClass::begin(size_t size){
#endif #endif
return false; return false;
} }
if(size == 0){ if(size == 0){
_error = UPDATE_ERROR_SIZE; _error = UPDATE_ERROR_SIZE;
#ifdef DEBUG_UPDATER #ifdef DEBUG_UPDATER
@ -41,10 +45,10 @@ bool UpdaterClass::begin(size_t size){
#endif #endif
return false; return false;
} }
_reset(); _reset();
_error = 0; _error = 0;
//size of current sketch rounded to a sector //size of current sketch rounded to a sector
uint32_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); 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 //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)); uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
//address where we will start writing the update //address where we will start writing the update
uint32_t updateStartAddress = updateEndAddress - roundedSize; uint32_t updateStartAddress = updateEndAddress - roundedSize;
//make sure that the size of both sketches is less than the total space (updateEndAddress) //make sure that the size of both sketches is less than the total space (updateEndAddress)
if(updateStartAddress < currentSketchSize){ if(updateStartAddress < currentSketchSize){
_error = UPDATE_ERROR_SPACE; _error = UPDATE_ERROR_SPACE;
@ -62,13 +66,13 @@ bool UpdaterClass::begin(size_t size){
#endif #endif
return false; return false;
} }
//initialize //initialize
_startAddress = updateStartAddress; _startAddress = updateStartAddress;
_currentAddress = _startAddress; _currentAddress = _startAddress;
_size = size; _size = size;
_buffer = new uint8_t[FLASH_SECTOR_SIZE]; _buffer = new uint8_t[FLASH_SECTOR_SIZE];
return true; return true;
} }
@ -79,30 +83,30 @@ bool UpdaterClass::end(bool evenIfRemaining){
#endif #endif
return false; return false;
} }
if(hasError() || (!isFinished() && !evenIfRemaining)){ if(hasError() || (!isFinished() && !evenIfRemaining)){
#ifdef DEBUG_UPDATER #ifdef DEBUG_UPDATER
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size); DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
#endif #endif
_reset(); _reset();
return false; return false;
} }
if(evenIfRemaining){ if(evenIfRemaining){
if(_bufferLen > 0){ if(_bufferLen > 0){
_writeBuffer(); _writeBuffer();
} }
_size = progress(); _size = progress();
} }
eboot_command ebcmd; eboot_command ebcmd;
ebcmd.action = ACTION_COPY_RAW; ebcmd.action = ACTION_COPY_RAW;
ebcmd.args[0] = _startAddress; ebcmd.args[0] = _startAddress;
ebcmd.args[1] = 0x00000; ebcmd.args[1] = 0x00000;
ebcmd.args[2] = _size; ebcmd.args[2] = _size;
eboot_command_write(&ebcmd); eboot_command_write(&ebcmd);
#ifdef DEBUG_UPDATER #ifdef DEBUG_UPDATER
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size); DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
#endif #endif
@ -112,17 +116,11 @@ bool UpdaterClass::end(bool evenIfRemaining){
} }
bool UpdaterClass::_writeBuffer(){ bool UpdaterClass::_writeBuffer(){
noInterrupts();
int rc = SPIEraseSector(_currentAddress/FLASH_SECTOR_SIZE);
interrupts();
yield(); yield();
if(!rc){ bool result = ESP.flashEraseSector(_currentAddress/FLASH_SECTOR_SIZE) &&
noInterrupts(); ESP.flashWrite(_currentAddress, (uint32_t*) _buffer, _bufferLen);
rc = SPIWrite(_currentAddress, _buffer, _bufferLen);
interrupts(); if (!result) {
}
interrupts();
if (rc) {
_error = UPDATE_ERROR_WRITE; _error = UPDATE_ERROR_WRITE;
_currentAddress = (_startAddress + _size); _currentAddress = (_startAddress + _size);
#ifdef DEBUG_UPDATER #ifdef DEBUG_UPDATER
@ -139,10 +137,10 @@ size_t UpdaterClass::write(uint8_t *data, size_t len) {
size_t left = len; size_t left = len;
if(hasError() || !isRunning()) if(hasError() || !isRunning())
return 0; return 0;
if(len > remaining()) if(len > remaining())
len = remaining(); len = remaining();
while((_bufferLen + left) > FLASH_SECTOR_SIZE) { while((_bufferLen + left) > FLASH_SECTOR_SIZE) {
size_t toBuff = FLASH_SECTOR_SIZE - _bufferLen; size_t toBuff = FLASH_SECTOR_SIZE - _bufferLen;
memcpy(_buffer + _bufferLen, data + (len - left), toBuff); memcpy(_buffer + _bufferLen, data + (len - left), toBuff);
@ -170,7 +168,7 @@ size_t UpdaterClass::writeStream(Stream &data) {
size_t toRead = 0; size_t toRead = 0;
if(hasError() || !isRunning()) if(hasError() || !isRunning())
return 0; return 0;
while(remaining()) { while(remaining()) {
toRead = FLASH_SECTOR_SIZE - _bufferLen; toRead = FLASH_SECTOR_SIZE - _bufferLen;
toRead = data.readBytes(_buffer + _bufferLen, toRead); toRead = data.readBytes(_buffer + _bufferLen, toRead);

View File

@ -23,32 +23,11 @@
#include <algorithm> #include <algorithm>
#include "spiffs/spiffs.h" #include "spiffs/spiffs.h"
#include "debug.h" #include "debug.h"
#include "interrupts.h"
extern "C" { extern "C" {
#include "c_types.h" #include "c_types.h"
#include "spi_flash.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. 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 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) { int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
optimistic_yield(10000);
uint32_t result = SPIFFS_OK; uint32_t result = SPIFFS_OK;
uint32_t alignedBegin = (addr + 3) & (~3); uint32_t alignedBegin = (addr + 3) & (~3);
uint32_t alignedEnd = (addr + size) & (~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) { if (addr < alignedBegin) {
uint32_t nb = alignedBegin - addr; uint32_t nb = alignedBegin - addr;
uint32_t tmp; 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", DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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 (alignedEnd != alignedBegin) {
if (spi_flash_read_locked(alignedBegin, (uint32_t*) (dst + alignedBegin - addr), if (!ESP.flashRead(alignedBegin, (uint32_t*) (dst + alignedBegin - addr),
alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) { alignedEnd - alignedBegin)) {
DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n", DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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) { if (addr + size > alignedEnd) {
uint32_t nb = addr + size - alignedEnd; uint32_t nb = addr + size - alignedEnd;
uint32_t tmp; 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", DEBUGV("_spif_read(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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; static const int UNALIGNED_WRITE_BUFFER_SIZE = 512;
int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src) { 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 alignedBegin = (addr + 3) & (~3);
uint32_t alignedEnd = (addr + size) & (~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 nb = alignedBegin - addr;
uint32_t tmp = 0xffffffff; uint32_t tmp = 0xffffffff;
memcpy(((uint8_t* )&tmp) + 4 - nb, src, nb); 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", DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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* srcLeftover = (uint32_t*) (src + alignedBegin - addr);
uint32_t srcAlign = ((uint32_t) srcLeftover) & 3; uint32_t srcAlign = ((uint32_t) srcLeftover) & 3;
if (!srcAlign) { if (!srcAlign) {
if (spi_flash_write_locked(alignedBegin, (uint32_t*) srcLeftover, if (!ESP.flashWrite(alignedBegin, (uint32_t*) srcLeftover,
alignedEnd - alignedBegin) != SPI_FLASH_RESULT_OK) { alignedEnd - alignedBegin)) {
DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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)); size_t willCopy = std::min(sizeLeft, sizeof(buf));
memcpy(buf, srcLeftover, willCopy); memcpy(buf, srcLeftover, willCopy);
if (spi_flash_write_locked(alignedBegin, (uint32_t*) buf, if (!ESP.flashWrite(alignedBegin, (uint32_t*) buf, willCopy)) {
willCopy) != SPI_FLASH_RESULT_OK) {
DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n", DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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; uint32_t tmp = 0xffffffff;
memcpy(&tmp, src + size - nb, nb); 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", DEBUGV("_spif_write(%d) addr=%x size=%x ab=%x ae=%x\r\n",
__LINE__, addr, size, alignedBegin, alignedEnd); __LINE__, addr, size, alignedBegin, alignedEnd);
return SPIFFS_ERR_INTERNAL; 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 sector = addr / SPI_FLASH_SEC_SIZE;
const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE; const uint32_t sectorCount = size / SPI_FLASH_SEC_SIZE;
for (uint32_t i = 0; i < sectorCount; ++i) { 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); DEBUGV("_spif_erase addr=%x size=%d i=%d\r\n", addr, size, i);
return SPIFFS_ERR_INTERNAL; return SPIFFS_ERR_INTERNAL;
} }