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();
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();
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);

View File

@ -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);

View File

@ -23,32 +23,11 @@
#include <algorithm>
#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;
}