From 0b265dc2a71247eccf0574b3a60fcebb7f99ceee Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 18 Nov 2016 19:17:13 +0800 Subject: [PATCH] nvs, spi_flash: handle case when source data is in DROM --- components/nvs_flash/src/nvs_page.cpp | 25 +++++++++++++++++++- components/spi_flash/flash_ops.c | 6 +++++ components/spi_flash/include/esp_spi_flash.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index d2ca225352..80ccb1f6d0 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -114,7 +114,30 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size) assert(mFirstUsedEntry != INVALID_ENTRY); const uint16_t count = size / ENTRY_SIZE; - auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), data, size); + const uint8_t* buf = data; + +#ifdef ESP_PLATFORM + /* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write + * function. To work around this, we copy the data to heap if it came from DROM. + * Hopefully this won't happen very often in practice. For data from DRAM, we should + * still be able to write it to flash directly. + * TODO: figure out how to make this platform-specific check nicer (probably by introducing + * a platform-specific flash layer). + */ + if ((uint32_t) data < 0x3ff00000) { + buf = (uint8_t*) malloc(size); + if (!buf) { + return ESP_ERR_NO_MEM; + } + memcpy((void*)buf, data, size); + } +#endif //ESP_PLATFORM + auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), buf, size); +#ifdef ESP_PLATFORM + if (buf != data) { + free((void*)buf); + } +#endif //ESP_PLATFORM if (rc != ESP_OK) { mState = PageState::INVALID; return rc; diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 134e1fe65b..3358c550f2 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -135,6 +135,12 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t si if (size % 4 != 0) { return ESP_ERR_INVALID_SIZE; } + if ((uint32_t) src < 0x3ff00000) { + // if source address is in DROM, we won't be able to read it + // from within SPIWrite + // TODO: consider buffering source data using heap and writing it anyway? + return ESP_ERR_INVALID_ARG; + } // Out of bound writes are checked in ROM code, but we can give better // error code here if (dest_addr + size > g_rom_flashchip.chip_size) { diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index 5d124da6b2..f940c0ad50 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -76,6 +76,8 @@ esp_err_t spi_flash_erase_range(size_t start_address, size_t size); * * @note Address in flash, dest, has to be 4-byte aligned. * This is a temporary limitation which will be removed. + * @note If source address is in DROM, this function will return + * ESP_ERR_INVALID_ARG. * * @param dest destination address in Flash * @param src pointer to the source buffer