Merge branch 'bugfix/esp_flash_revert_qe_clear_4.0' into 'release/v4.0'
esp_flash: fix the regression of non-quad mode by default chip driver, bugs in add_device and deprecate cs_id (4.0) See merge request espressif/esp-idf!8879
This commit is contained in:
commit
9969ec1de5
5 changed files with 61 additions and 22 deletions
|
@ -70,17 +70,17 @@ static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_f
|
|||
int cs_io_num = config->cs_io_num;
|
||||
int spics_in = spi_periph_signal[config->host_id].spics_in;
|
||||
int spics_out = spi_periph_signal[config->host_id].spics_out[config->cs_id];
|
||||
int spics_func = spi_periph_signal[config->host_id].func;
|
||||
uint32_t iomux_reg = GPIO_PIN_MUX_REG[cs_io_num];
|
||||
|
||||
//To avoid the panic caused by flash data line conflicts during cs line
|
||||
//initialization, disable the cache temporarily
|
||||
chip->os_func->start(chip->os_func_data);
|
||||
if (use_iomux) {
|
||||
GPIO.func_in_sel_cfg[spics_in].sig_in_sel = 0;
|
||||
PIN_INPUT_ENABLE(iomux_reg);
|
||||
GPIO.func_out_sel_cfg[spics_out].oen_sel = 0;
|
||||
GPIO.func_out_sel_cfg[spics_out].oen_inv_sel = false;
|
||||
PIN_FUNC_SELECT(iomux_reg, 1);
|
||||
// This requires `gpio_iomux_in` and `gpio_iomux_out` to be in the IRAM.
|
||||
// `linker.lf` is used fulfill this requirement.
|
||||
gpio_iomux_in(cs_io_num, spics_in);
|
||||
gpio_iomux_out(cs_io_num, spics_func, false);
|
||||
} else {
|
||||
PIN_INPUT_ENABLE(iomux_reg);
|
||||
if (cs_io_num < 32) {
|
||||
|
@ -112,17 +112,28 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d
|
|||
if (config->host_id == SPI_HOST) caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT;
|
||||
|
||||
chip = (esp_flash_t*)heap_caps_malloc(sizeof(esp_flash_t), caps);
|
||||
host = (spi_flash_host_driver_t*)heap_caps_malloc(sizeof(spi_flash_host_driver_t), caps);
|
||||
host_data = (memspi_host_data_t*)heap_caps_malloc(sizeof(memspi_host_data_t), caps);
|
||||
if (!chip || !host || !host_data) {
|
||||
if (!chip) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
host = (spi_flash_host_driver_t*)heap_caps_malloc(sizeof(spi_flash_host_driver_t), caps);
|
||||
*chip = (esp_flash_t) {
|
||||
.read_mode = config->io_mode,
|
||||
.host = host,
|
||||
};
|
||||
if (!host) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
host_data = (memspi_host_data_t*)heap_caps_malloc(sizeof(memspi_host_data_t), caps);
|
||||
host->driver_data = host_data;
|
||||
if (!host_data) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_flash_init_os_functions(chip, config->host_id);
|
||||
if (err != ESP_OK) {
|
||||
ret = err;
|
||||
|
@ -147,6 +158,7 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d
|
|||
*out_chip = chip;
|
||||
return ret;
|
||||
fail:
|
||||
// The memory allocated are free'd in the `spi_bus_remove_flash_device`.
|
||||
spi_bus_remove_flash_device(chip);
|
||||
return ret;
|
||||
}
|
||||
|
@ -180,9 +192,10 @@ static DRAM_ATTR esp_flash_t default_chip = {
|
|||
.os_func = &esp_flash_noos_functions,
|
||||
};
|
||||
|
||||
esp_err_t esp_flash_init_default_chip()
|
||||
esp_err_t esp_flash_init_default_chip(void)
|
||||
{
|
||||
memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT();
|
||||
|
||||
//the host is already initialized, only do init for the data and load it to the host
|
||||
spi_flash_hal_init(&default_driver_data, &cfg);
|
||||
default_chip.host->driver_data = &default_driver_data;
|
||||
|
@ -206,7 +219,7 @@ esp_err_t esp_flash_init_default_chip()
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_flash_app_init()
|
||||
esp_err_t esp_flash_app_init(void)
|
||||
{
|
||||
return esp_flash_app_init_os_functions(&default_chip);
|
||||
}
|
||||
|
|
|
@ -7,3 +7,9 @@ entries:
|
|||
spi_flash_chip_gd(noflash)
|
||||
memspi_host_driver (noflash)
|
||||
|
||||
# `spi_bus_add_flash_device` uses these functions when the cache is disabled
|
||||
[mapping:driver_spiflash]
|
||||
archive: libdriver.a
|
||||
entries:
|
||||
gpio:gpio_iomux_out (noflash)
|
||||
gpio:gpio_iomux_in (noflash)
|
||||
|
|
|
@ -35,6 +35,8 @@ static const spi_flash_chip_t *default_registered_chips[] = {
|
|||
#ifdef CONFIG_SPI_FLASH_SUPPORT_GD_CHIP
|
||||
&esp_flash_chip_gd,
|
||||
#endif
|
||||
// Default chip drivers that will accept all chip ID.
|
||||
// FM, Winbond and XMC chips are supposed to be supported by this chip driver.
|
||||
&esp_flash_chip_generic,
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -451,12 +451,15 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t
|
|||
esp_err_t ret = ESP_OK;
|
||||
const bool is_quad_mode = esp_flash_is_quad_mode(chip);
|
||||
bool update_config = false;
|
||||
const bool force_check = true; //in case some chips doesn't support erase QE
|
||||
/*
|
||||
* By default, we don't clear the QE bit even the flash mode is not QIO or QOUT. Force clearing
|
||||
* QE bit by the generic chip driver (command 01H with 2 bytes) may cause the output of some
|
||||
* chips (MXIC) no longer valid.
|
||||
* Enable this option when testing a new flash chip for clearing of QE.
|
||||
*/
|
||||
const bool force_check = false;
|
||||
|
||||
bool need_check = is_quad_mode;
|
||||
if (force_check) {
|
||||
need_check = true;
|
||||
}
|
||||
bool need_check = is_quad_mode || force_check;
|
||||
|
||||
uint32_t sr_update;
|
||||
if (need_check) {
|
||||
|
|
|
@ -49,6 +49,9 @@ typedef void (*flash_test_func_t)(esp_flash_t* chip);
|
|||
#define FLASH_TEST_CASE(STR, FUNC_TO_RUN) \
|
||||
TEST_CASE(STR, "[esp_flash]") {flash_test_func(FUNC_TO_RUN, 1 /* first index reserved for main flash */ );}
|
||||
|
||||
#define FLASH_TEST_CASE_IGNORE(STR, FUNC_TO_RUN) \
|
||||
TEST_CASE(STR, "[esp_flash][ignore]") {flash_test_func(FUNC_TO_RUN, 1 /* first index reserved for main flash */ );}
|
||||
|
||||
/* Use FLASH_TEST_CASE_3 for tests which also run on external flash, which sits in the place of PSRAM
|
||||
(these tests are incompatible with PSRAM)
|
||||
|
||||
|
@ -56,9 +59,13 @@ typedef void (*flash_test_func_t)(esp_flash_t* chip);
|
|||
*/
|
||||
#if defined(CONFIG_SPIRAM_SUPPORT)
|
||||
#define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
|
||||
#define FLASH_TEST_CASE_3_IGNORE(STR, FUNCT_TO_RUN)
|
||||
#else
|
||||
#define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
|
||||
TEST_CASE(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, TEST_CONFIG_NUM);}
|
||||
|
||||
#define FLASH_TEST_CASE_3_IGNORE(STR, FUNC_TO_RUN) \
|
||||
TEST_CASE(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH][ignore]") {flash_test_func(FUNC_TO_RUN, TEST_CONFIG_NUM);}
|
||||
#endif
|
||||
|
||||
//currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
|
||||
|
@ -408,7 +415,7 @@ esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe);
|
|||
esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe);
|
||||
esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
|
||||
|
||||
static bool check_winbond_chip(esp_flash_t* chip)
|
||||
static bool is_winbond_chip(esp_flash_t* chip)
|
||||
{
|
||||
uint32_t flash_id;
|
||||
esp_err_t ret = esp_flash_read_chip_id(chip, &flash_id);
|
||||
|
@ -430,14 +437,15 @@ static void test_toggle_qe(esp_flash_t* chip)
|
|||
esp_err_t ret = esp_flash_get_io_mode(chip, &qe);
|
||||
TEST_ESP_OK(ret);
|
||||
|
||||
bool is_winbond_chip = check_winbond_chip(chip);
|
||||
bool allow_failure = is_winbond_chip(chip);
|
||||
|
||||
|
||||
for (int i = 0; i < 4; i ++) {
|
||||
ESP_LOGI(TAG, "write qe: %d->%d", qe, !qe);
|
||||
qe = !qe;
|
||||
chip->read_mode = qe? SPI_FLASH_QOUT: SPI_FLASH_SLOWRD;
|
||||
ret = esp_flash_set_io_mode(chip, qe);
|
||||
if (is_winbond_chip && !qe && ret == ESP_ERR_FLASH_NO_RESPONSE) {
|
||||
if (allow_failure && !qe && ret == ESP_ERR_FLASH_NO_RESPONSE) {
|
||||
//allows clear qe failure for Winbond chips
|
||||
ret = ESP_OK;
|
||||
}
|
||||
|
@ -447,8 +455,12 @@ static void test_toggle_qe(esp_flash_t* chip)
|
|||
ret = esp_flash_get_io_mode(chip, &qe_read);
|
||||
TEST_ESP_OK(ret);
|
||||
ESP_LOGD(TAG, "qe read: %d", qe_read);
|
||||
if (qe != qe_read && !qe && is_winbond_chip) {
|
||||
ESP_LOGE(TAG, "cannot clear QE bit, this may be normal for Winbond chips.");
|
||||
if (!qe && qe_read) {
|
||||
if (allow_failure) {
|
||||
ESP_LOGW(TAG, "cannot clear QE bit for known permanent QE (Winbond) chips.");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "cannot clear QE bit, please make sure force clearing QE option is enabled in `spi_flash_common_set_io_mode`, and this chip is not a permanent QE one.");
|
||||
}
|
||||
chip->read_mode = io_mode_before;
|
||||
return;
|
||||
}
|
||||
|
@ -458,8 +470,11 @@ static void test_toggle_qe(esp_flash_t* chip)
|
|||
chip->read_mode = io_mode_before;
|
||||
}
|
||||
|
||||
FLASH_TEST_CASE("Test esp_flash_write can toggle QE bit", test_toggle_qe);
|
||||
FLASH_TEST_CASE_3("Test esp_flash_write can toggle QE bit", test_toggle_qe);
|
||||
// These tests show whether the QE is permanent or not for the chip tested.
|
||||
// To test the behaviour of a new SPI flash chip, enable force_check flag in generic driver
|
||||
// `spi_flash_common_set_io_mode` and then run this test.
|
||||
FLASH_TEST_CASE_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe);
|
||||
FLASH_TEST_CASE_3_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe);
|
||||
|
||||
|
||||
void test_permutations(flashtest_config_t* config)
|
||||
|
|
Loading…
Reference in a new issue