Merge pull request #15554 from s-hadinger/berry_flash_faster

Berry improve flash.write for faster writes
This commit is contained in:
s-hadinger 2022-05-05 20:16:14 +02:00 committed by GitHub
commit ebadc63abc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 10 deletions

View File

@ -39,7 +39,7 @@ size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t s
size_in_page = SPI_FLASH_SEC_SIZE - addr_in_page; size_in_page = SPI_FLASH_SEC_SIZE - addr_in_page;
} }
AddLog(LOG_LEVEL_DEBUG, ">>>: flash_write addr=%p size=%i -- page_addr=%p addr_in_page=%p size_in_page=%i size_left=%i", address_start, size, page_addr, addr_in_page, size_in_page, size_left); // AddLog(LOG_LEVEL_DEBUG, ">>>: flash_write addr=%p size=%i -- page_addr=%p addr_in_page=%p size_in_page=%i size_left=%i", address_start, size, page_addr, addr_in_page, size_in_page, size_left);
// check if whole page? // check if whole page?
if (addr_in_page == 0 && size_in_page == SPI_FLASH_SEC_SIZE) { if (addr_in_page == 0 && size_in_page == SPI_FLASH_SEC_SIZE) {
memcpy(buffer, data + current_offset, SPI_FLASH_SEC_SIZE); memcpy(buffer, data + current_offset, SPI_FLASH_SEC_SIZE);
@ -94,9 +94,8 @@ extern "C" {
be_raise(vm, kTypeError, nullptr); be_raise(vm, kTypeError, nullptr);
} }
// Berry: `flash.write(address:int, content:bytes()) -> nil` // Berry: `flash.write(address:int, content:bytes() [, no_erase:bool]) -> nil`
// // if `no_erase` is true, just call spi_flash_write
// If length is not specified, it is full block 4KB
int32_t p_flash_write(struct bvm *vm); int32_t p_flash_write(struct bvm *vm);
int32_t p_flash_write(struct bvm *vm) { int32_t p_flash_write(struct bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments int32_t argc = be_top(vm); // Get the number of arguments

View File

@ -458,17 +458,25 @@ extern "C" {
extern size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t size); extern size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t size);
const uint32_t STREAM_FLASH_PROGRESS_THRESHOLD_KB = 100; // display log entry every 100kB
const uint32_t STREAM_FLASH_PROGRESS_THRESHOLD = STREAM_FLASH_PROGRESS_THRESHOLD_KB * 1024;
class StreamFlash: public Stream class StreamFlash: public Stream
{ {
public: public:
StreamFlash(uint32_t addr) : addr_start(addr), offset(0) {}; StreamFlash(uint32_t addr) : addr_start(addr), offset(0) {};
size_t write(const uint8_t *buffer, size_t size) override { size_t write(const uint8_t *buffer, size_t size) override {
AddLog(LOG_LEVEL_INFO, "FLASH: addr=%p hex=%*_H size=%i", addr_start + offset, 32, buffer, size); // AddLog(LOG_LEVEL_INFO, "FLASH: addr=%p hex=%*_H size=%i", addr_start + offset, 32, buffer, size);
if (size > 0) { if (size > 0) {
size_t ret = FlashWriteSubSector(addr_start + offset, buffer, size); esp_err_t ret = spi_flash_write(addr_start + offset, buffer, size);
if (ret == 0) { return 0; } // error if (ret != ESP_OK) { return 0; } // error
offset += size; offset += size;
// shall we display a progress indicator?
if (((offset - size) / STREAM_FLASH_PROGRESS_THRESHOLD) != (offset / STREAM_FLASH_PROGRESS_THRESHOLD)) {
AddLog(LOG_LEVEL_DEBUG, D_LOG_UPLOAD "Progress %d kB", offset / 1024);
}
} }
return size; return size;
} }
@ -495,13 +503,38 @@ extern "C" {
HTTPClientLight * cl = wc_getclient(vm); HTTPClientLight * cl = wc_getclient(vm);
uint32_t addr = be_toint(vm, 2); uint32_t addr = be_toint(vm, 2);
if (addr < 0x10000 || addr >= 0x400000) { if (addr < 0x10000 || addr >= 0x400000) {
be_raise(vm, "value_error", "invalid flash address"); be_raisef(vm, "value_error", "invalid flash address 0x04X", addr);
}
if (addr & (SPI_FLASH_SEC_SIZE-1) != 0) {
be_raisef(vm, "value_error", "invalid flash address, must be at %iKB boundary 0x%04X", SPI_FLASH_SEC_SIZE/1024, addr);
}
int32_t size = cl->getSize();
if (size <= 0 || addr+size >= 0x400000) {
be_raisef(vm, "value_error", "invalid flash size 0x%04X", size);
}
int32_t size_rounded_4k = (size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
// erase region
esp_err_t ret;
AddLog(LOG_LEVEL_DEBUG, D_LOG_UPLOAD "erasing flash at 0x%04X length 0x%04X", addr, size_rounded_4k);
ret = spi_flash_erase_range(addr, size_rounded_4k);
if (ret != ESP_OK) {
be_raisef(vm, "internal_error", "unable to erase flash region (%i)", ret);
} }
StreamFlash flash_writer(addr); StreamFlash flash_writer(addr);
cl->writeToStream(&flash_writer); AddLog(LOG_LEVEL_DEBUG, D_LOG_UPLOAD "writing flash at 0x%04X size 0x%04X", addr, size);
int32_t written = cl->writeToStream(&flash_writer);
if (written <= 0) {
be_raisef(vm, "internal_error", "unable to write flash (%i)", written);
}
if (written != size) {
be_raisef(vm, "internal_error", "failed, written %i bytes vs %i", written, size);
}
AddLog(LOG_LEVEL_DEBUG, D_LOG_UPLOAD "flash writing succesful");
be_pushbool(vm, btrue); be_pushint(vm, written);
be_return(vm); /* return code */ be_return(vm); /* return code */
} }
be_raise(vm, kTypeError, nullptr); be_raise(vm, kTypeError, nullptr);