#define MAX_WRITE_CHUNK 8192
#define MAX_READ_CHUNK 16384
+static const char *TAG __attribute__((unused)) = "spi_flash";
+
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
-static const char *TAG = "spi_flash";
static spi_flash_counters_t s_flash_stats;
#define COUNTER_START() uint32_t ts_begin = xthal_get_ccount()
s_flash_guard_ops = funcs;
}
+const spi_flash_guard_funcs_t *IRAM_ATTR spi_flash_guard_get()
+{
+ return s_flash_guard_ops;
+}
+
size_t IRAM_ATTR spi_flash_get_chip_size()
{
return g_rom_flashchip.chip_size;
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
spi_flash_guard_start();
- if (sector % sectors_per_block == 0 && end - sector > sectors_per_block) {
+ if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
sector += sectors_per_block;
COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
return spi_flash_translate_rc(rc);
}
+/* Wrapper around esp_rom_spiflash_write() that verifies data as written if CONFIG_SPI_FLASH_VERIFY_WRITE is set.
+
+ If CONFIG_SPI_FLASH_VERIFY_WRITE is not set, this is esp_rom_spiflash_write().
+*/
+static IRAM_ATTR esp_rom_spiflash_result_t spi_flash_write_inner(uint32_t target, const uint32_t *src_addr, int32_t len)
+{
+#ifndef CONFIG_SPI_FLASH_VERIFY_WRITE
+ return esp_rom_spiflash_write(target, src_addr, len);
+#else // CONFIG_SPI_FLASH_VERIFY_WRITE
+ esp_rom_spiflash_result_t res = ESP_ROM_SPIFLASH_RESULT_OK;
+ assert(len % sizeof(uint32_t) == 0);
+
+ uint32_t before_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM / sizeof(uint32_t)];
+ uint32_t after_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM / sizeof(uint32_t)];
+ int32_t remaining = len;
+ for(int i = 0; i < len; i += sizeof(before_buf)) {
+ int i_w = i / sizeof(uint32_t); // index in words (i is an index in bytes)
+
+ int32_t read_len = MIN(sizeof(before_buf), remaining);
+
+ // Read "before" contents from flash
+ res = esp_rom_spiflash_read(target + i, before_buf, read_len);
+ if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
+ break;
+ }
+
+#ifdef CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
+ for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
+ int r_w = r / sizeof(uint32_t); // index in words (r is index in bytes)
+
+ uint32_t write = src_addr[i_w + r_w];
+ uint32_t before = before_buf[r_w];
+ if ((before & write) != write) {
+ spi_flash_guard_end();
+ ESP_LOGW(TAG, "Write at offset 0x%x requests 0x%08x but will write 0x%08x -> 0x%08x",
+ target + i + r, write, before, before & write);
+ spi_flash_guard_start();
+ }
+ }
+#endif
+
+ res = esp_rom_spiflash_write(target + i, &src_addr[i_w], read_len);
+ if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
+ break;
+ }
+
+ res = esp_rom_spiflash_read(target + i, after_buf, read_len);
+ if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
+ break;
+ }
+
+ for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
+ int r_w = r / sizeof(uint32_t); // index in words (r is index in bytes)
+
+ uint32_t expected = src_addr[i_w + r_w] & before_buf[r_w];
+ uint32_t actual = after_buf[r_w];
+ if (expected != actual) {
+#ifdef CONFIG_SPI_FLASH_LOG_FAILED_WRITE
+ spi_flash_guard_end();
+ ESP_LOGE(TAG, "Bad write at offset 0x%x expected 0x%08x readback 0x%08x", target + i + r, expected, actual);
+ spi_flash_guard_start();
+#endif
+ res = ESP_ROM_SPIFLASH_RESULT_ERR;
+ }
+ }
+ if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
+ break;
+ }
+ remaining -= read_len;
+ }
+ return res;
+#endif // CONFIG_SPI_FLASH_VERIFY_WRITE
+}
+
+
esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
{
CHECK_WRITE_ADDRESS(dst, size);
uint32_t t = 0xffffffff;
memcpy(((uint8_t *) &t) + (dst - left_off), srcc, left_size);
spi_flash_guard_start();
- rc = esp_rom_spiflash_write(left_off, &t, 4);
+ rc = spi_flash_write_inner(left_off, &t, 4);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
write_src = (const uint8_t *)write_buf;
}
spi_flash_guard_start();
- rc = esp_rom_spiflash_write(dst + mid_off, (const uint32_t *) write_src, write_size);
+ rc = spi_flash_write_inner(dst + mid_off, (const uint32_t *) write_src, write_size);
spi_flash_guard_end();
COUNTER_ADD_BYTES(write, write_size);
mid_size -= write_size;
uint32_t t = 0xffffffff;
memcpy(&t, srcc + right_off, right_size);
spi_flash_guard_start();
- rc = esp_rom_spiflash_write(dst + right_off, &t, 4);
+ rc = spi_flash_write_inner(dst + right_off, &t, 4);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;