From c1695b45334126f105a8de3f809e74be446f31a8 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 10 Feb 2026 19:09:06 +0800 Subject: [PATCH] fix(flash): flash erase operation may fail to raise PMS exception --- .../esp_hal_mspi/spi_flash_hal_common.inc | 17 +++++++++++++++++ components/spi_flash/spi_flash_chip_mxic_opi.c | 3 +++ 2 files changed, 20 insertions(+) diff --git a/components/esp_hal_mspi/spi_flash_hal_common.inc b/components/esp_hal_mspi/spi_flash_hal_common.inc index 5c6e1c81c2..a0e9ec86c0 100644 --- a/components/esp_hal_mspi/spi_flash_hal_common.inc +++ b/components/esp_hal_mspi/spi_flash_hal_common.inc @@ -188,6 +188,23 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr io_mode = trans->io_mode; } +#if SOC_IS(ESP32S3) + // On ESP32S3, PMS is enabled only if user_command = 1, user_addr = 1, and user_mosi = 1 + // While for other targets, user_command = 1, user_addr = 1, and user_miso = 0 are the conditions to enable PMS. + // While erase command doesn't have mosi data, so PMS cannot be enabled + // The workaround is to send the low 8 bits of the address in data phase, in such way, user_mosi will be set to 1 + if (command != 0x00 && trans->address_bitlen > 0 && trans->mosi_len == 0 && trans->miso_len == 0) { + uint32_t addr = trans->address; + // Split addr into two phases + trans->address_bitlen -= 8; + trans->address = addr >> 8; // the high bits of the addr + trans->mosi_len = 1; + trans->mosi_data = (uint8_t[]) { + (uint8_t)(addr & 0xFF) + }; // the low 8 bits of the addr + } +#endif + host->driver->configure_host_io_mode(host, command, trans->address_bitlen, dummy_bitlen, io_mode); spi_flash_ll_set_usr_address(dev, trans->address, trans->address_bitlen); diff --git a/components/spi_flash/spi_flash_chip_mxic_opi.c b/components/spi_flash/spi_flash_chip_mxic_opi.c index e5fb38757f..d8ba7a72a5 100644 --- a/components/spi_flash/spi_flash_chip_mxic_opi.c +++ b/components/spi_flash/spi_flash_chip_mxic_opi.c @@ -209,6 +209,7 @@ esp_err_t spi_flash_chip_mxic_opi_erase_sector(esp_flash_t *chip, uint32_t start .command = CMD_OPI_FLASH_MXIC(CMD_SECTOR_ERASE_4B), .address_bitlen = 32, .address = start_address, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; err = chip->host->driver->common_command(chip->host, &t); chip->busy = 1; @@ -238,6 +239,7 @@ esp_err_t spi_flash_chip_mxic_opi_erase_block(esp_flash_t *chip, uint32_t start_ .command = CMD_OPI_FLASH_MXIC(CMD_LARGE_BLOCK_ERASE_4B), .address_bitlen = 32, .address = start_address, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; err = chip->host->driver->common_command(chip->host, &t); chip->busy = 1; @@ -269,6 +271,7 @@ esp_err_t spi_flash_chip_mxic_opi_page_program(esp_flash_t *chip, const void *bu .address = address, .mosi_len = length, .mosi_data = buffer, + .flags = SPI_FLASH_TRANS_FLAG_PE_CMD, }; chip->host->driver->common_command(chip->host, &t); chip->busy = 1;