]> granicus.if.org Git - esp-idf/commitdiff
nvs, spi_flash: handle case when source data is in DROM
authorIvan Grokhotkov <ivan@espressif.com>
Fri, 18 Nov 2016 11:17:13 +0000 (19:17 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 18 Nov 2016 12:11:17 +0000 (20:11 +0800)
components/nvs_flash/src/nvs_page.cpp
components/spi_flash/flash_ops.c
components/spi_flash/include/esp_spi_flash.h

index d2ca225352f60ad6f5a738523ddc5e11922bd6e6..80ccb1f6d08cc5785ffa81c05501b28df7d054ea 100644 (file)
@@ -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;
index 134e1fe65b65120b4b4027e015d9180af5e75e88..3358c550f206fd174235702617bafcaf82be27b1 100644 (file)
@@ -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) {
index 5d124da6b2ea147b3bdadf85c5923fd35a8a9a02..f940c0ad50f44df0d53f09fba8c75e1f052006d8 100644 (file)
@@ -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