Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more idf5.1 preps: Berry flash driver #19273

Merged
merged 1 commit into from
Aug 6, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 57 additions & 43 deletions tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_flash.ino
Original file line number Diff line number Diff line change
Expand Up @@ -24,52 +24,60 @@

#include "esp_idf_version.h"
#if ESP_IDF_VERSION_MAJOR >= 5
// esp_spi_flash.h is deprecated, please use spi_flash_mmap.h instead
#include "spi_flash_mmap.h"
#include "esp_flash.h"
#else
#include "esp_spi_flash.h"
#endif

size_t FlashWriteSubSector(uint32_t address_start, const uint8_t *data, size_t size) {
#if ESP_IDF_VERSION_MAJOR < 5
uint32_t addr = address_start;
size_t size_left = size;
size_t current_offset = 0;
esp_err_t ret;
// Memory is unaligned, so we need to copy it to an aligned buffer
uint8_t buffer[SPI_FLASH_SEC_SIZE] __attribute__((aligned(4)));

while (size_left) {
uint32_t page_addr = addr & ~(SPI_FLASH_SEC_SIZE - 1);
uint32_t addr_in_page = addr & (SPI_FLASH_SEC_SIZE - 1);
uint32_t size_in_page = size_left;
if (addr_in_page + size_in_page > SPI_FLASH_SEC_SIZE) {
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);
// check if whole page?
if (addr_in_page == 0 && size_in_page == SPI_FLASH_SEC_SIZE) {
memcpy(buffer, data + current_offset, SPI_FLASH_SEC_SIZE);
} else {
ret = spi_flash_read(page_addr, buffer, SPI_FLASH_SEC_SIZE);
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not read flash %p (0x%X) ret=%i", page_addr, SPI_FLASH_SEC_SIZE, ret); return 0; }
memcpy(buffer + addr_in_page, data + current_offset, size_in_page);
}
ret = spi_flash_erase_sector(page_addr / SPI_FLASH_SEC_SIZE);
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not erase flash sector 0x%X ret=%i", page_addr / SPI_FLASH_SEC_SIZE, ret); return 0; }
spi_flash_write(page_addr, buffer, SPI_FLASH_SEC_SIZE);
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not write flash %p (0x%X) ret=%i", page_addr, SPI_FLASH_SEC_SIZE, ret); return 0; }

addr += size_in_page;
current_offset += size_in_page;
size_left -= size_in_page;
uint32_t addr = address_start;
size_t size_left = size;
size_t current_offset = 0;
esp_err_t ret;
// Memory is unaligned, so we need to copy it to an aligned buffer
uint8_t buffer[SPI_FLASH_SEC_SIZE] __attribute__((aligned(4)));

while (size_left) {
uint32_t page_addr = addr & ~(SPI_FLASH_SEC_SIZE - 1);
uint32_t addr_in_page = addr & (SPI_FLASH_SEC_SIZE - 1);
uint32_t size_in_page = size_left;
if (addr_in_page + size_in_page > SPI_FLASH_SEC_SIZE) {
size_in_page = SPI_FLASH_SEC_SIZE - addr_in_page;
}

return current_offset;
// 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?
if (addr_in_page == 0 && size_in_page == SPI_FLASH_SEC_SIZE) {
memcpy(buffer, data + current_offset, SPI_FLASH_SEC_SIZE);
} else {
#if ESP_IDF_VERSION_MAJOR < 5
ret = spi_flash_read(page_addr, buffer, SPI_FLASH_SEC_SIZE);
#else
ret = esp_flash_read(NULL, buffer, page_addr, SPI_FLASH_SEC_SIZE);
#endif
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not read flash %p (0x%X) ret=%i", page_addr, SPI_FLASH_SEC_SIZE, ret); return 0; }
memcpy(buffer + addr_in_page, data + current_offset, size_in_page);
}
#if ESP_IDF_VERSION_MAJOR < 5
ret = spi_flash_erase_sector(page_addr / SPI_FLASH_SEC_SIZE);
#else
ret = esp_flash_erase_region(NULL, page_addr, SPI_FLASH_SEC_SIZE);
#endif
if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not erase flash sector 0x%X ret=%i", page_addr / SPI_FLASH_SEC_SIZE, ret); return 0; }
#if ESP_IDF_VERSION_MAJOR < 5
spi_flash_write(page_addr, buffer, SPI_FLASH_SEC_SIZE);
#else
// TODO ESPIDF 5
esp_flash_write(NULL, buffer, page_addr, SPI_FLASH_SEC_SIZE);
#endif

if (ret) { AddLog(LOG_LEVEL_INFO, "BRY: could not write flash %p (0x%X) ret=%i", page_addr, SPI_FLASH_SEC_SIZE, ret); return 0; }

addr += size_in_page;
current_offset += size_in_page;
size_left -= size_in_page;
}

return current_offset;
}

/*********************************************************************************************\
Expand All @@ -84,7 +92,6 @@ extern "C" {
// If length is not specified, it is full block 4KB
int32_t p_flash_read(struct bvm *vm);
int32_t p_flash_read(struct bvm *vm) {
#if ESP_IDF_VERSION_MAJOR < 5
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 1 && be_isint(vm, 1) &&
(argc < 2 || be_isint(vm, 2)) ) { // optional second argument must be int
Expand All @@ -96,22 +103,24 @@ extern "C" {
}
// allocate a buffer in the heap that will be automatically freed when going out of scope
auto buf = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
#if ESP_IDF_VERSION_MAJOR < 5
esp_err_t ret = spi_flash_read(address, buf.get(), length);
#else
esp_err_t ret = esp_flash_read(NULL, buf.get(), address, length);
#endif
if (ret) {
be_raisef(vm, "internal_error", "Error calling spi_flash_read(0x%X, %i)", address, length);
}
be_pushbytes(vm, buf.get(), length);
be_return(vm);
}
#endif
be_raise(vm, kTypeError, nullptr);
}

// Berry: `flash.write(address:int, content:bytes() [, no_erase:bool]) -> nil`
// if `no_erase` is true, just call spi_flash_write
int32_t p_flash_write(struct bvm *vm);
int32_t p_flash_write(struct bvm *vm) {
#if ESP_IDF_VERSION_MAJOR < 5
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isint(vm, 1) && be_isinstance(vm, 2)) {
be_getglobal(vm, "bytes"); /* get the bytes class */ /* TODO eventually replace with be_getbuiltin */
Expand All @@ -125,7 +134,11 @@ extern "C" {
const void * bytes = be_tobytes(vm, 2, &length);
if (bytes && length > 0) {
if (no_erase) {
#if ESP_IDF_VERSION_MAJOR < 5
esp_err_t ret = spi_flash_write(address, (const uint8_t*)bytes, length);
#else
esp_err_t ret = esp_flash_write(NULL, (const uint8_t*)bytes, address, length);
#endif
if (ret) {
be_raisef(vm, "internal_error", "Error calling spi_flash_write() ret=%i", ret);
}
Expand All @@ -140,7 +153,6 @@ extern "C" {
}
}
}
#endif
be_raise(vm, kTypeError, nullptr);
}

Expand All @@ -149,7 +161,6 @@ extern "C" {
// Address and length must be 4KB aligned
int32_t p_flash_erase(struct bvm *vm);
int32_t p_flash_erase(struct bvm *vm) {
#if ESP_IDF_VERSION_MAJOR < 5
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isint(vm, 1) && be_isint(vm, 2)) {
int32_t address = be_toint(vm, 1);
Expand All @@ -160,10 +171,13 @@ extern "C" {
if ((length % 0x1000) != 0 || length < 0) {
be_raise(vm, "value_error", "Length must be a multiple of 0x1000");
}
#if ESP_IDF_VERSION_MAJOR < 5
esp_err_t ret = spi_flash_erase_range(address, length);
#else
esp_err_t ret = esp_flash_erase_region(NULL, address, length);
#endif
be_return_nil(vm);
}
#endif
be_raise(vm, kTypeError, nullptr);
}

Expand Down