spi_flash: fix cs line setup to make the flash driver more stable

This commit is contained in:
Cao Sen Miao 2021-05-20 20:51:38 +08:00
parent 88c2b69c68
commit 9c7d2c7595
19 changed files with 103 additions and 29 deletions

View File

@ -237,6 +237,7 @@ static void test_bus_lock(bool test_flash)
.io_mode = SPI_FLASH_DIO,
.speed = ESP_FLASH_5MHZ,
.input_delay_ns = 0,
.cs_setup = 1,
};
//Clamp the WP and HD pins to VDD to make it work in DIO mode

View File

@ -402,6 +402,12 @@ static inline void spi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void spi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->ctrl2.setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -383,6 +383,12 @@ static inline void gpspi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void gpspi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->user1.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -75,6 +75,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time)
#else
#define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev)
#define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev)
@ -101,6 +102,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time)
#endif

View File

@ -549,6 +549,12 @@ static inline void spimem_flash_ll_set_hold(spi_mem_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->ctrl2.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -370,6 +370,12 @@ static inline void gpspi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void gpspi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->ctrl2.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -75,6 +75,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time)
#else
@ -103,6 +104,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time)
#endif

View File

@ -539,6 +539,12 @@ static inline void spimem_flash_ll_set_hold(spi_mem_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->ctrl2.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}

View File

@ -382,6 +382,12 @@ static inline void gpspi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void gpspi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->user1.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -74,6 +74,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time)
#else
#define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev)
@ -101,6 +102,7 @@ typedef union {
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time)
#endif
#ifdef __cplusplus

View File

@ -539,6 +539,12 @@ static inline void spimem_flash_ll_set_hold(spi_mem_dev_t *dev, uint32_t hold_n)
dev->user.cs_hold = (hold_n > 0? 1: 0);
}
static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_setup_time)
{
dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0);
dev->ctrl2.cs_setup_time = cs_setup_time - 1;
}
#ifdef __cplusplus
}
#endif

View File

@ -42,7 +42,7 @@ typedef struct {
int cs_num; ///< Which cs pin is used, 0-2.
struct {
uint8_t extra_dummy; ///< Pre-calculated extra dummy used for compensation
uint8_t reserved1; ///< Reserved, set to 0.
uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock.
uint8_t cs_hold; ///< CS hold time config used by the host
uint8_t reserved2; ///< Reserved, set to 0.
};
@ -63,6 +63,7 @@ typedef struct {
int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation.
esp_flash_speed_t speed;///< SPI flash clock speed to work at.
uint32_t cs_hold; ///< CS hold time config used by the host
uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock
bool auto_sus_en; ///< Auto suspend feature enable bit 1: enable, 0: disable.
} spi_flash_hal_config_t;

View File

@ -90,6 +90,7 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_
.extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, APB_CLK_FREQ/clock_cfg->div),
.clock_conf = clock_cfg->clock_reg_val,
.cs_hold = cfg->cs_hold,
.cs_setup = cfg->cs_setup,
};
if (cfg->auto_sus_en) {
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND;

View File

@ -50,6 +50,8 @@ esp_err_t spi_flash_hal_device_config(spi_flash_host_inst_t *host)
spi_flash_ll_set_clock(dev, &ctx->clock_conf);
int cs_hold = ctx->cs_hold;
spi_flash_ll_set_hold(dev, cs_hold);
spi_flash_ll_set_cs_setup(dev, ctx->cs_setup);
#ifndef GPSPI_BUILD
#if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
if ((ctx->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND) != 0) {

View File

@ -71,6 +71,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.cs_num = 0, \
.iomux = false, \
.input_delay_ns = 0,\
.cs_setup = 1,\
}
#elif CONFIG_IDF_TARGET_ESP32S2
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
@ -79,6 +80,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.cs_num = 0, \
.iomux = true, \
.input_delay_ns = 0,\
.cs_setup = 1,\
}
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/efuse.h"
@ -88,6 +90,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.cs_num = 0, \
.iomux = true, \
.input_delay_ns = 0,\
.cs_setup = 1,\
}
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/efuse.h"
@ -98,6 +101,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.cs_num = 0, \
.iomux = true, \
.input_delay_ns = 0,\
.cs_setup = 1,\
}
#else
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
@ -107,6 +111,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.iomux = true, \
.input_delay_ns = 0,\
.auto_sus_en = true,\
.cs_setup = 1,\
}
#endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND
#endif

View File

@ -34,6 +34,7 @@ typedef struct {
* automatically assigned by the SPI bus lock.
*/
int cs_id;
uint32_t cs_setup; ///< (cycles-1) of prepare phase by spi clock
} esp_flash_spi_device_config_t;
/**

View File

@ -177,6 +177,7 @@ static const char TAG[] = "test_esp_flash";
/* the pin which is usually used by the PSRAM */ \
.cs_io_num = SPI1_CS_IO, \
.input_delay_ns = 0, \
.cs_setup = 1,\
}
#if CONFIG_IDF_TARGET_ESP32
@ -199,6 +200,7 @@ flashtest_config_t config_list[] = {
.cs_id = 0,
.cs_io_num = VSPI_PIN_NUM_CS,
.input_delay_ns = 0,
.cs_setup = 1,\
},
};
#elif CONFIG_IDF_TARGET_ESP32S2
@ -211,6 +213,7 @@ flashtest_config_t config_list[] = {
.cs_id = 0,
.cs_io_num = FSPI_PIN_NUM_CS,
.input_delay_ns = 0,
.cs_setup = 1,\
},
{
.io_mode = TEST_SPI_READ_MODE,
@ -220,6 +223,7 @@ flashtest_config_t config_list[] = {
// uses GPIO matrix on esp32s2 regardless of FORCE_GPIO_MATRIX
.cs_io_num = HSPI_PIN_NUM_CS,
.input_delay_ns = 0,
.cs_setup = 1,\
},
};
#elif CONFIG_IDF_TARGET_ESP32S3
@ -233,6 +237,7 @@ flashtest_config_t config_list[] = {
.cs_id = 0,
.cs_io_num = FSPI_PIN_NUM_CS,
.input_delay_ns = 0,
.cs_setup = 1,\
},
};
#elif CONFIG_IDF_TARGET_ESP32C3
@ -249,6 +254,7 @@ flashtest_config_t config_list[] = {
.cs_id = 0,
.cs_io_num = FSPI_PIN_NUM_CS,
.input_delay_ns = 0,
.cs_setup = 1,\
},
};
#endif
@ -385,6 +391,7 @@ static void setup_new_chip(const flashtest_config_t* test_cfg, esp_flash_t** out
.cs_id = test_cfg->cs_id,
.cs_io_num = test_cfg->cs_io_num,
.input_delay_ns = test_cfg->input_delay_ns,
.cs_setup = test_cfg->cs_setup,
};
esp_flash_t* init_chip;
esp_err_t err = spi_bus_add_flash_device(&init_chip, &dev_cfg);

View File

@ -141,48 +141,55 @@ TEST_CASE("Test spi_flash_read", "[spi_flash][esp_flash]")
#endif
}
#if CONFIG_IDF_TARGET_ESP32
static void IRAM_ATTR fix_rom_func(void)
{
return; // ESP32 ROM has no compatible issue for now
}
# else
extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode);
extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
static void IRAM_ATTR fix_rom_func(void)
{
esp_rom_spiflash_read_mode_t read_mode;
uint8_t freqdiv;
#if defined CONFIG_ESPTOOLPY_FLASHMODE_QIO
read_mode = ESP_ROM_SPIFLASH_QIO_MODE;
#elif defined CONFIG_ESPTOOLPY_FLASHMODE_QOUT
read_mode = ESP_ROM_SPIFLASH_QOUT_MODE;
#elif defined CONFIG_ESPTOOLPY_FLASHMODE_DIO
read_mode = ESP_ROM_SPIFLASH_DIO_MODE;
#elif defined CONFIG_ESPTOOLPY_FLASHMODE_DOUT
read_mode = ESP_ROM_SPIFLASH_DOUT_MODE;
#endif
uint32_t freqdiv = 0;
# if defined CONFIG_ESPTOOLPY_FLASHFREQ_80M
#if CONFIG_ESPTOOLPY_FLASHFREQ_80M
freqdiv = 1;
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_40M
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
freqdiv = 2;
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_26M
#elif CONFIG_ESPTOOLPY_FLASHFREQ_26M
freqdiv = 3;
# elif defined CONFIG_ESPTOOLPY_FLASHFREQ_20M
#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
freqdiv = 4;
#endif
spi_flash_disable_interrupts_caches_and_other_cpu();
esp_rom_spiflash_config_clk(freqdiv, 1);
#if CONFIG_IDF_TARGET_ESP32
uint32_t dummy_bit = 0;
#if CONFIG_ESPTOOLPY_FLASHFREQ_80M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_26M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_26M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
#endif
g_rom_spiflash_dummy_len_plus[1] = dummy_bit;
#else
spi_dummy_len_fix(1, freqdiv);
esp_rom_spiflash_config_readmode(read_mode);
#if !CONFIG_IDF_TARGET_ESP32S2
#endif//CONFIG_IDF_TARGET_ESP32
esp_rom_spiflash_read_mode_t read_mode;
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO
read_mode = ESP_ROM_SPIFLASH_QIO_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_QOUT
read_mode = ESP_ROM_SPIFLASH_QOUT_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_DIO
read_mode = ESP_ROM_SPIFLASH_DIO_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT
read_mode = ESP_ROM_SPIFLASH_DOUT_MODE;
#endif
#if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32
spi_common_set_dummy_output(read_mode);
#endif //!CONFIG_IDF_TARGET_ESP32S2
spi_flash_enable_interrupts_caches_and_other_cpu();
esp_rom_spiflash_config_clk(freqdiv, 1);
esp_rom_spiflash_config_readmode(read_mode);
}
#endif
static void IRAM_ATTR test_write(int dst_off, int src_off, int len)
{

View File

@ -103,7 +103,8 @@ static esp_flash_t* example_init_ext_flash(void)
.cs_id = 0,
.cs_io_num = VSPI_IOMUX_PIN_NUM_CS,
.io_mode = SPI_FLASH_DIO,
.speed = ESP_FLASH_40MHZ
.speed = ESP_FLASH_40MHZ,
.cs_setup = 1,
};
ESP_LOGI(TAG, "Initializing external SPI Flash");