mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 12:53:29 +00:00
esp_flash: fix set qe bit and write command issues
There used to be dummy phase before out phase in common command transactions. This corrupts the data. The code before never actually operate (clear) the QE bit, once it finds the QE bit is set. It's hard to check whether the QE set/disable functions work well. This commit: 1. Cancel the dummy phase 2. Set and clear the QE bit according to chip settings, allowing tests for QE bits. However for some chips (Winbond for example), it's not forced to clear the QE bit if not able to. 3. Also refactor to allow chip_generic and other chips to share the same code to read and write qe bit; let common command and read command share configure_host_io_mode. 4. Rename read mode to io mode since maybe we will write data with quad mode one day.
This commit is contained in:
@@ -60,7 +60,7 @@ static const char io_mode_str[][IO_STR_LEN] = {
|
||||
"qio",
|
||||
};
|
||||
|
||||
_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_read_mode_t defined in spi_flash_ll.h");
|
||||
_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_ll.h");
|
||||
|
||||
|
||||
/* Static function to notify OS of a new SPI flash operation.
|
||||
@@ -139,38 +139,51 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip)
|
||||
|
||||
if (err == ESP_OK) {
|
||||
// Try to set the flash mode to whatever default mode was chosen
|
||||
err = chip->chip_drv->set_read_mode(chip);
|
||||
err = chip->chip_drv->set_io_mode(chip);
|
||||
if (err == ESP_ERR_FLASH_NO_RESPONSE && !esp_flash_is_quad_mode(chip)) {
|
||||
//some chips (e.g. Winbond) don't support to clear QE, treat as success
|
||||
err = ESP_OK;
|
||||
}
|
||||
}
|
||||
// Done: all fields on 'chip' are initialised
|
||||
return spiflash_end(chip, err);
|
||||
}
|
||||
|
||||
//this is not public, but useful in unit tests
|
||||
esp_err_t IRAM_ATTR esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id)
|
||||
{
|
||||
esp_err_t err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Send generic RDID command twice, check for a matching result and retry in case we just powered on (inner
|
||||
// function fails if it sees all-ones or all-zeroes.)
|
||||
err = chip->host->read_id(chip->host, flash_id);
|
||||
|
||||
if (err == ESP_OK) { // check we see the same ID twice, in case of transient power-on errors
|
||||
uint32_t new_id;
|
||||
err = chip->host->read_id(chip->host, &new_id);
|
||||
if (err == ESP_OK && (new_id != *flash_id)) {
|
||||
err = ESP_ERR_FLASH_NOT_INITIALISED;
|
||||
}
|
||||
}
|
||||
|
||||
return spiflash_end(chip, err);
|
||||
}
|
||||
|
||||
static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t flash_id;
|
||||
int retries = 10;
|
||||
do {
|
||||
err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Send generic RDID command twice, check for a matching result and retry in case we just powered on (inner
|
||||
// function fails if it sees all-ones or all-zeroes.)
|
||||
err = chip->host->read_id(chip->host, &flash_id);
|
||||
|
||||
if (err == ESP_OK) { // check we see the same ID twice, in case of transient power-on errors
|
||||
uint32_t new_id;
|
||||
err = chip->host->read_id(chip->host, &new_id);
|
||||
if (err == ESP_OK && (new_id != flash_id)) {
|
||||
err = ESP_ERR_FLASH_NOT_INITIALISED;
|
||||
}
|
||||
}
|
||||
|
||||
err = spiflash_end(chip, err);
|
||||
} while (err != ESP_OK && retries-- > 0);
|
||||
err = esp_flash_read_chip_id(chip, &flash_id);
|
||||
} while (err == ESP_ERR_FLASH_NOT_INITIALISED && retries-- > 0);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Detect the chip and set the chip_drv structure for it
|
||||
const spi_flash_chip_t **drivers = esp_flash_registered_chips;
|
||||
@@ -617,6 +630,36 @@ esp_err_t IRAM_ATTR esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address
|
||||
return spi_flash_read_encrypted(address, out_buffer, length);
|
||||
}
|
||||
|
||||
// test only, non-public
|
||||
IRAM_ATTR esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe)
|
||||
{
|
||||
VERIFY_OP(get_io_mode);
|
||||
esp_flash_io_mode_t io_mode;
|
||||
|
||||
esp_err_t err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
err = chip->chip_drv->get_io_mode(chip, &io_mode);
|
||||
err = spiflash_end(chip, err);
|
||||
if (err == ESP_OK) {
|
||||
*qe = (io_mode == SPI_FLASH_QOUT);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe)
|
||||
{
|
||||
VERIFY_OP(set_io_mode);
|
||||
chip->read_mode = (qe? SPI_FLASH_QOUT: SPI_FLASH_SLOWRD);
|
||||
esp_err_t err = spiflash_start(chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
err = chip->chip_drv->set_io_mode(chip);
|
||||
return spiflash_end(chip, err);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
esp_err_t esp_flash_app_disable_protect(bool disable)
|
||||
{
|
||||
|
Reference in New Issue
Block a user