diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 5a05d859b..f5e3c7ecd 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -17,6 +17,20 @@ config SPI_FLASH_LOG_FAILED_WRITE will be written with the address, expected & actual values. This can be useful when debugging hardware SPI flash problems. +config SPI_FLASH_WARN_SETTING_ZERO_TO_ONE + bool "Log warning if writing zero bits to ones" + depends on SPI_FLASH_VERIFY_WRITE + default n + help + If this option is enabled, any SPI flash write which tries to set zero bits in the flash to + ones will log a warning. Such writes will not result in the requested data appearing identically + in flash once written, as SPI NOR flash can only set bits to one when an entire sector is erased. + After erasing, individual bits can only be written from one to zero. + + Note that some software (such as SPIFFS) which is aware of SPI NOR flash may write one bits as an + optimisation, relying on the data in flash becoming a bitwise AND of the new data and any existing data. + Such software will log spurious warnings if this option is enabled. + config SPI_FLASH_ENABLE_COUNTERS bool "Enable operation counters" default 0 diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index eb2b23cf4..aab0c1210 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -260,6 +260,21 @@ static IRAM_ATTR esp_rom_spiflash_result_t spi_flash_write_inner(uint32_t target 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;