diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index 4281105faa5..3145d93ed64 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -178,6 +178,23 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr io_mode = trans->io_mode; } +#if CONFIG_IDF_TARGET_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 d19488fa533..0fb789f4b21 100644 --- a/components/spi_flash/spi_flash_chip_mxic_opi.c +++ b/components/spi_flash/spi_flash_chip_mxic_opi.c @@ -88,7 +88,7 @@ esp_err_t spi_flash_chip_mxic_opi_set_write_protect(esp_flash_t *chip, bool writ static void spi_flash_chip_mxic_opi_get_data_length_zoom(esp_flash_io_mode_t io_mode, uint32_t *length_zoom) { /* Under STR mode, one byte occupies one single clock. While under DTR mode, one byte occupies half clock. - For exmaple, if an operation needs 3 clock dummy, host send 3 dummy bytes under STR mode, while 6 dummy bytes under DTR mode. + For example, if an operation needs 3 clock dummy, host send 3 dummy bytes under STR mode, while 6 dummy bytes under DTR mode. Therefore, we need to adjust data zoom to fit the clock here. */ assert((io_mode == SPI_FLASH_OPI_STR) || (io_mode == SPI_FLASH_OPI_DTR)); *length_zoom = (io_mode == SPI_FLASH_OPI_STR) ? 1 : 2; @@ -208,6 +208,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; @@ -237,6 +238,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; @@ -268,6 +270,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; @@ -358,7 +361,7 @@ esp_err_t spi_flash_chip_xmic_opi_set_io_mode(esp_flash_t *chip) } // This function should only be called after opi mode initialization. So, only configure for OPI-STR/OPI-DTR mode -// not support other mode in this file, return `ESP_ERR_FLASH_NOT_INITIALISED` directely. +// not support other mode in this file, return `ESP_ERR_FLASH_NOT_INITIALISED` directly. esp_err_t spi_flash_chip_xmic_opi_config_host_io_mode(esp_flash_t *chip, uint32_t flags) { uint32_t dummy_cyclelen_base;