From 0f91a01a460acd9eb2eb08af8a65c07ddedbaeb8 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 2 Aug 2021 17:15:07 +0800 Subject: [PATCH 1/4] mspi: support up-to-80MHz quad flash & up-to-80MHz octal psram on esp32s3 --- .../port/esp32s3/opiram_psram.c | 13 +++- components/esp_system/port/cpu_start.c | 1 + .../esp32s3/spi_flash_oct_flash_init.c | 42 ++++--------- components/spi_flash/flash_ops.c | 12 ++++ .../spi_flash/include/spi_flash_private.h | 5 ++ .../spi_flash/spi_flash_timing_tuning.c | 62 ++++++++++++++++--- 6 files changed, 95 insertions(+), 40 deletions(-) diff --git a/components/esp_hw_support/port/esp32s3/opiram_psram.c b/components/esp_hw_support/port/esp32s3/opiram_psram.c index efff2ec4d9..6c45cb4f1f 100644 --- a/components/esp_hw_support/port/esp32s3/opiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/opiram_psram.c @@ -205,10 +205,19 @@ static void IRAM_ATTR s_print_psram_info(opi_psram_mode_reg_t *reg_val) reg_val->mr0.drive_str == 0x02 ? 4 : 8); } +static void IRAM_ATTR s_init_psram_pins(void) +{ + //Set cs1 pin function + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1); + //Set mspi cs1 drive strength + PIN_SET_DRV(IO_MUX_GPIO26_REG, 3); + //Set psram clock pin drive strength + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); +} + esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) { - // enable CS signal - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1); + s_init_psram_pins(); //enter MSPI slow mode to init PSRAM device registers spi_timing_enter_mspi_low_speed_mode(); diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index e1acfebf44..83909ef4ec 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -366,6 +366,7 @@ void IRAM_ATTR call_start_cpu0(void) Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); #endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 + esp_mspi_pin_init(); #if CONFIG_ESPTOOLPY_OCT_FLASH bool efuse_opflash_en = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA3_REG, EFUSE_FLASH_TYPE); if (!efuse_opflash_en) { diff --git a/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c b/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c index 42de479acc..f689b8bbe0 100644 --- a/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c +++ b/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c @@ -12,6 +12,7 @@ #include "esp32s3/rom/opi_flash.h" #include "spi_flash_private.h" #include "soc/spi_mem_reg.h" +#include "soc/io_mux_reg.h" #if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC #include "opi_flash_cmd_format_mxic.h" #endif @@ -21,40 +22,11 @@ #define SPI_FLASH_SPI_CMD_RDCR 0x15 #define SPI_FLASH_SPI_CMD_WRSRCR 0x01 -#define SPI_FLASH_OCTCLK_IO 30 -#define SPI_FLASH_OCTDQS_IO 37 -#define SPI_FLASH_OCTD0_IO 32 -#define SPI_FLASH_OCTD1_IO 31 -#define SPI_FLASH_OCTD2_IO 28 -#define SPI_FLASH_OCTD3_IO 27 -#define SPI_FLASH_OCTD4_IO 33 -#define SPI_FLASH_OCTD5_IO 34 -#define SPI_FLASH_OCTD6_IO 35 -#define SPI_FLASH_OCTD7_IO 36 -#define SPI_FLASH_OCTCS_IO 29 -#define SPI_FLASH_OCTCS1_IO 26 - - // default value is rom_default_spiflash_legacy_flash_func extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs; extern int SPI_write_enable(void *spi); DRAM_ATTR const esp_rom_opiflash_def_t opiflash_cmd_def = OPI_CMD_FORMAT(); -void s_set_flash_pin_drive_capability(uint8_t drv) -{ - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCLK_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTDQS_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD0_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD1_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD2_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD3_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD4_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD5_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD6_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD7_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS1_IO, drv); -} static void s_register_rom_function(void) { @@ -145,6 +117,14 @@ static void s_set_flash_ouput_driver_strength(int spi_num, uint8_t strength) false); } +static void s_set_pin_drive_capability(uint8_t drv) +{ + //flash clock + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3); + //cs0 + PIN_SET_DRV(IO_MUX_GPIO29_REG, 3); +} + static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode) { esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def); @@ -156,13 +136,13 @@ static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode) // STR/DTR specific setting esp_rom_spiflash_wait_idle(&g_rom_flashchip); #if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR - s_set_flash_pin_drive_capability(1); + s_set_pin_drive_capability(3); s_set_flash_dtr_str_opi_mode(1, 0x1); esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd); esp_rom_spi_set_dtr_swap_mode(0, false, false); esp_rom_spi_set_dtr_swap_mode(1, false, false); #else //CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR - s_set_flash_pin_drive_capability(3); + s_set_pin_drive_capability(3); s_set_flash_dtr_str_opi_mode(1, 0x2); esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd); esp_rom_spi_set_dtr_swap_mode(0, true, true); diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index c928634706..53fbe269f6 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -39,6 +39,7 @@ #elif CONFIG_IDF_TARGET_ESP32S3 #include "soc/spi_mem_reg.h" #include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/opi_flash.h" #include "esp32s3/rom/cache.h" #include "esp32s3/clk.h" #include "esp32s3/clk.h" @@ -164,6 +165,17 @@ void IRAM_ATTR *spi_flash_malloc_internal(size_t size) } #endif +void IRAM_ATTR esp_mspi_pin_init(void) +{ +#if CONFIG_ESPTOOLPY_OCT_FLASH || CONFIG_SPIRAM_MODE_OCT + esp_rom_opiflash_pin_config(); + extern void spi_timing_set_pin_drive_strength(void); + spi_timing_set_pin_drive_strength(); +#else + //Set F4R4 board pin drive strength. TODO: IDF-3663 +#endif +} + void spi_flash_init(void) { spi_flash_init_lock(); diff --git a/components/spi_flash/include/spi_flash_private.h b/components/spi_flash/include/spi_flash_private.h index f792faef65..7435359f3e 100644 --- a/components/spi_flash/include/spi_flash_private.h +++ b/components/spi_flash/include/spi_flash_private.h @@ -56,6 +56,11 @@ void spi_timing_flash_tuning(void); */ void spi_timing_psram_tuning(void); +/** + * @brief To initislize the MSPI pins + */ +void esp_mspi_pin_init(void); + /** * @brief Set SPI1 registers to make ROM functions work * @note This function is used for setting SPI1 registers to the state that ROM SPI functions work diff --git a/components/spi_flash/spi_flash_timing_tuning.c b/components/spi_flash/spi_flash_timing_tuning.c index 705da2c45c..c168c35d69 100644 --- a/components/spi_flash/spi_flash_timing_tuning.c +++ b/components/spi_flash/spi_flash_timing_tuning.c @@ -12,14 +12,42 @@ #include "esp_types.h" #include "esp_log.h" #include "soc/spi_mem_reg.h" +#include "soc/io_mux_reg.h" #include "spi_flash_private.h" #if CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/spi_timing_config.h" #endif +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) + +/*------------------------------------------------------------------------------ + * Common settings + *----------------------------------------------------------------------------*/ +void spi_timing_set_pin_drive_strength(void) +{ + //For now, set them all to 3. Need to check after QVL test results are out. TODO: IDF-3663 + //Set default clk + SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3); + //Set default mspi d0 ~ d7, dqs pin drive strength + uint32_t regs[] = {IO_MUX_GPIO27_REG, IO_MUX_GPIO28_REG, + IO_MUX_GPIO31_REG, IO_MUX_GPIO32_REG, + IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG, + IO_MUX_GPIO35_REG, IO_MUX_GPIO36_REG, + IO_MUX_GPIO37_REG}; + for (int i = 0; i < ARRAY_SIZE(regs); i++) { + PIN_SET_DRV(regs[i], 3); + } +} + +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING static spi_timing_tuning_param_t s_flash_best_timing_tuning_config; static spi_timing_tuning_param_t s_psram_best_timing_tuning_config; +/*------------------------------------------------------------------------------ + * Static functions to get clock configs + *----------------------------------------------------------------------------*/ static spi_timing_config_core_clock_t get_mspi_core_clock(void) { return spi_timing_config_get_core_clock(); @@ -52,7 +80,9 @@ static uint32_t get_psram_clock_divider(void) #endif } -#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +/*------------------------------------------------------------------------------ + * Static functions to do timing tuning + *----------------------------------------------------------------------------*/ /** * Set timing tuning regs, in order to get successful sample points */ @@ -134,7 +164,6 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u while (i < size) { if (array[i]) { match_num++; - } else { if (match_num > max) { max = match_num; @@ -149,7 +178,7 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u *out_end_index = match_num == size ? size : end; } -static void select_best_tuning_config(spi_timing_config_t *config, uint32_t length, uint32_t end, bool is_flash) +static void select_best_tuning_config(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, bool is_flash) { uint32_t best_point; if (length >= 3) { @@ -185,7 +214,9 @@ static void do_tuning(uint8_t *reference_data, spi_timing_config_t *timing_confi #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -//------------------------------------------FLASH Timing Tuning----------------------------------------// +/*------------------------------------------------------------------------------ + * FLASH Timing Tuning + *----------------------------------------------------------------------------*/ #if SPI_TIMING_FLASH_NEEDS_TUNING static void get_flash_tuning_configs(spi_timing_config_t *config) { @@ -210,6 +241,7 @@ static void get_flash_tuning_configs(spi_timing_config_t *config) void spi_timing_flash_tuning(void) { + ESP_EARLY_LOGW("FLASH", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to get reference data from FLASH * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) @@ -235,7 +267,9 @@ void spi_timing_flash_tuning(void) #endif //SPI_TIMING_FLASH_NEEDS_TUNING -//------------------------------------------PSRAM Timing Tuning----------------------------------------// +/*------------------------------------------------------------------------------ + * PSRAM Timing Tuning + *----------------------------------------------------------------------------*/ #if SPI_TIMING_PSRAM_NEEDS_TUNING static void get_psram_tuning_configs(spi_timing_config_t *config) { @@ -256,6 +290,7 @@ static void get_psram_tuning_configs(spi_timing_config_t *config) void spi_timing_psram_tuning(void) { + ESP_EARLY_LOGW("PSRAM", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to write reference data to PSRAM * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) @@ -285,17 +320,21 @@ void spi_timing_psram_tuning(void) } #endif //SPI_TIMING_PSRAM_NEEDS_TUNING - -//---------------------------------------------APIs to make SPI0 and SPI1 FLASH work for high/low freq-------------------------------// +/*------------------------------------------------------------------------------ + * APIs to make SPI0 and SPI1 FLASH work for high/low freq + *----------------------------------------------------------------------------*/ +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING static void clear_timing_tuning_regs(void) { spi_timing_config_flash_set_din_mode_num(0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg spi_timing_config_flash_set_extra_dummy(0, 0); spi_timing_config_flash_set_extra_dummy(1, 0); } +#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING void spi_timing_enter_mspi_low_speed_mode(void) { +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /** * Here we are going to slow the SPI1 frequency to 20Mhz, so we need to set SPI1 din_num and din_mode regs. * @@ -311,8 +350,12 @@ void spi_timing_enter_mspi_low_speed_mode(void) spi_timing_config_set_flash_clock(0, 4); clear_timing_tuning_regs(); +#else + //Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned +#endif } +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING static void set_timing_tuning_regs_as_required(void) { //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg @@ -323,6 +366,7 @@ static void set_timing_tuning_regs_as_required(void) spi_timing_config_psram_set_din_mode_num(0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num); spi_timing_config_psram_set_extra_dummy(0, s_psram_best_timing_tuning_config.extra_dummy_len); } +#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /** * Set SPI0 and SPI1 flash module clock, din_num, din_mode and extra dummy, @@ -332,6 +376,7 @@ static void set_timing_tuning_regs_as_required(void) */ void spi_timing_enter_mspi_high_speed_mode(void) { +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING spi_timing_config_core_clock_t core_clock = get_mspi_core_clock(); uint32_t flash_div = get_flash_clock_divider(); uint32_t psram_div = get_psram_clock_divider(); @@ -345,4 +390,7 @@ void spi_timing_enter_mspi_high_speed_mode(void) spi_timing_config_set_psram_clock(0, psram_div); set_timing_tuning_regs_as_required(); +#else + //Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned +#endif } From 038b7b1fa918b8862350516f1c93b3557e75f452 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 2 Aug 2021 17:15:51 +0800 Subject: [PATCH 2/4] mspi: update 80MHz DTR tuning algorithm and Oct PSRAM 80M DTR tuning parameters --- .../esp32s3/mspi_timing_tuning_configs.h | 2 +- .../spi_flash/spi_flash_timing_tuning.c | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h b/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h index d438d58d48..ef3550c246 100644 --- a/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h +++ b/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h @@ -36,6 +36,6 @@ #define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE 4 //Octal PSRAM: core clock 160M, module clock 80M, DTR mode -#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{1, 0, 0}, {0, 0, 0}, {3, 0, 1}, {1, 0, 1}, {0, 0, 1}, {3, 0, 2}, {1, 0, 2}, {0, 0, 2}, {3, 0, 3}, {1, 0, 3}, {0, 0, 3}, {3, 0, 4}, {1, 0, 4}, {0, 0, 4}} +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{0, 0, 0}, {4, 2, 2}, {2, 1, 2}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 2, 3}, {2, 1, 3}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 2, 4}} #define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 14 #define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 1 diff --git a/components/spi_flash/spi_flash_timing_tuning.c b/components/spi_flash/spi_flash_timing_tuning.c index c168c35d69..52707d502b 100644 --- a/components/spi_flash/spi_flash_timing_tuning.c +++ b/components/spi_flash/spi_flash_timing_tuning.c @@ -180,11 +180,25 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u static void select_best_tuning_config(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, bool is_flash) { +#if (SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M) || (SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M) + //80M DTR best point scheme uint32_t best_point; - if (length >= 3) { - best_point = end - length / 2; - } else { + /** + * If the consecutive success point list is no longer than 2, or all available points are successful, + * tuning is FAIL, select default point, and generate a warning + */ + //Define these magic number in macros in `spi_timing_config.h`. TODO: IDF-3146 + if (consecutive_length <= 2 || consecutive_length >= 6) { best_point = config->default_config_id; + ESP_EARLY_LOGW("timing tuning:", "tuning fail, best point is %d\n", best_point + 1); + } else if (consecutive_length <= 4) { + //consevutive length : 3 or 4 + best_point = end - 1; + ESP_EARLY_LOGD("timing tuning:","tuning success, best point is %d\n", best_point + 1); + } else { + //consecutive point list length equals 5 + best_point = end - 2; + ESP_EARLY_LOGD("timing tuning:","tuning success, best point is %d\n", best_point + 1); } if (is_flash) { @@ -192,6 +206,10 @@ static void select_best_tuning_config(spi_timing_config_t *config, uint32_t cons } else { s_psram_best_timing_tuning_config = config->tuning_config_table[best_point]; } +#else + //won't reach here + abort(); +#endif } static void do_tuning(uint8_t *reference_data, spi_timing_config_t *timing_config, bool is_flash) From 3cbf202267b89750594702cef4952702dfe5811d Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 2 Aug 2021 17:16:16 +0800 Subject: [PATCH 3/4] mspi: cancel oct flash 40m dtr, oct flash 80m str, oct psram 40m tuning --- components/spi_flash/esp32s3/spi_timing_config.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/components/spi_flash/esp32s3/spi_timing_config.h b/components/spi_flash/esp32s3/spi_timing_config.h index 0c94b2e718..9487d31b1d 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.h +++ b/components/spi_flash/esp32s3/spi_timing_config.h @@ -30,12 +30,6 @@ extern "C" { //OCTAL FLASH #if CONFIG_ESPTOOLPY_OCT_FLASH -// OCT FLASH 40M DTR -#if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_40M -_Static_assert(!CONFIG_ESPTOOLPY_FLASHFREQ_40M, "Octal FLASH 40MHz DDR is not supported. TODO: IDF-1630"); -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 -#endif - //OCT FLASH 80M DTR #if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M #define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 @@ -46,11 +40,6 @@ _Static_assert(!CONFIG_ESPTOOLPY_FLASHFREQ_40M, "Octal FLASH 40MHz DDR is not su #define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 #endif -//OCT FLASH 80M STR -#if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 -#endif - //OCT FLASH 120M STR #if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M #define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120 @@ -67,11 +56,6 @@ _Static_assert(!CONFIG_ESPTOOLPY_FLASHFREQ_40M, "Octal FLASH 40MHz DDR is not su //OCTAL PSRAM #if CONFIG_SPIRAM_MODE_OCT -//OCT 40M PSRAM -#if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_40M -#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80 -#endif - //OCT 80M PSRAM #if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M #define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160 From 2b52f7f696e61b46c3e9b5448b2fe73bc66daded Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 2 Aug 2021 17:16:30 +0800 Subject: [PATCH 4/4] mspi: fix no buffer reset before each psram read issue In psram timing tuning driver, we rely on psram read and write functions defined in `spi_timing_config.c`. If we don't do buffer reset (clear to 0), the function may untouch the buffer, which will keep last time value (since we reuse the buffer). Therefore, if the first read is expected, but next few reads didn't modify the buffer content, we will still see the expected data. These functions relies on `esp_rom_opiflash_exec_cmd`. --- .../spi_flash/esp32s3/spi_timing_config.c | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/components/spi_flash/esp32s3/spi_timing_config.c b/components/spi_flash/esp32s3/spi_timing_config.c index ef496e68cb..a96c294045 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.c +++ b/components/spi_flash/esp32s3/spi_timing_config.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "sdkconfig.h" #include "string.h" #include "esp_attr.h" @@ -156,16 +157,13 @@ void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, #endif } -void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +static void IRAM_ATTR s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { -#if CONFIG_ESPTOOLPY_OCT_FLASH - uint32_t cmd = OPI_PSRAM_SYNC_WRITE; - int dummy = OCT_PSRAM_WR_DUMMY_NUM; - +#if CONFIG_SPIRAM_MODE_OCT esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE, - cmd, 16, + OPI_PSRAM_SYNC_WRITE, 16, addr, 32, - dummy, + OCT_PSRAM_WR_DUMMY_NUM, buf, 8 * len, NULL, 0, BIT(1), @@ -175,16 +173,16 @@ void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, #endif } -void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len) +static void IRAM_ATTR s_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { -#if CONFIG_ESPTOOLPY_OCT_FLASH - uint32_t cmd = OPI_PSRAM_SYNC_READ; - int dummy = OCT_PSRAM_RD_DUMMY_NUM; - +#if CONFIG_SPIRAM_MODE_OCT + for (int i = 0; i < 16; i++) { + REG_WRITE(SPI_MEM_W0_REG(1) + i*4, 0); + } esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE, - cmd, 16, + OPI_PSRAM_SYNC_READ, 16, addr, 32, - dummy, + OCT_PSRAM_RD_DUMMY_NUM, NULL, 0, buf, 8 * len, BIT(1), @@ -194,4 +192,29 @@ void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, u #endif } +static void IRAM_ATTR s_psram_execution(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len, bool is_read) +{ + while (len) { + uint32_t length = MIN(len, 32); + if (is_read) { + s_psram_read_data(1, buf, addr, length); + } else { + s_psram_write_data(1, buf, addr, length); + } + addr += length; + buf += length; + len -= length; + } +} + +void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(spi_num, buf, addr, len, false); +} + +void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(spi_num, buf, addr, len, true); +} + #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING