forked from espressif/esp-idf
spi_flash: Support select flash mode automatically at run time(Quad flash or Octal flash)
This commit is contained in:
@@ -57,6 +57,13 @@ esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t bootloader_flash_reset_chip(void);
|
esp_err_t bootloader_flash_reset_chip(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if octal flash mode is enabled in eFuse
|
||||||
|
*
|
||||||
|
* @return True if flash is in octal mode, false else
|
||||||
|
*/
|
||||||
|
bool bootloader_flash_is_octal_mode_enabled(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <esp_flash_encrypt.h>
|
#include <esp_flash_encrypt.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "hal/efuse_ll.h"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
# include "soc/spi_struct.h"
|
# include "soc/spi_struct.h"
|
||||||
@@ -780,3 +781,12 @@ esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
|
|||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool bootloader_flash_is_octal_mode_enabled(void)
|
||||||
|
{
|
||||||
|
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
|
return efuse_ll_get_flash_type();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include "flash_qio_mode.h"
|
#include "flash_qio_mode.h"
|
||||||
#include "bootloader_flash_config.h"
|
#include "bootloader_flash_config.h"
|
||||||
#include "bootloader_common.h"
|
#include "bootloader_common.h"
|
||||||
|
#include "bootloader_flash.h"
|
||||||
|
|
||||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||||
@@ -34,17 +35,18 @@ void bootloader_flash_update_id()
|
|||||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||||
{
|
{
|
||||||
//SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here
|
//SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S);
|
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_CS_SETUP_TIME_S);
|
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S);
|
||||||
//CS high time
|
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_CS_SETUP_TIME_S);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_CS_HOLD_DELAY_S);
|
//CS high time
|
||||||
#else
|
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_CS_HOLD_DELAY_S);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
} else {
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
||||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||||
#endif
|
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
|
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
|
||||||
|
@@ -218,7 +218,9 @@ static esp_err_t bootloader_init_spi_flash(void)
|
|||||||
bootloader_flash_unlock();
|
bootloader_flash_unlock();
|
||||||
|
|
||||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||||
bootloader_enable_qio_mode();
|
if (!bootloader_flash_is_octal_mode_enabled()) {
|
||||||
|
bootloader_enable_qio_mode();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
print_flash_info(&bootloader_image_hdr);
|
print_flash_info(&bootloader_image_hdr);
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include "esp_private/gpio.h"
|
#include "esp_private/gpio.h"
|
||||||
#include "esp_private/sleep_gpio.h"
|
#include "esp_private/sleep_gpio.h"
|
||||||
#include "esp_private/spi_flash_os.h"
|
#include "esp_private/spi_flash_os.h"
|
||||||
|
#include "bootloader_flash.h"
|
||||||
|
|
||||||
static const char *TAG = "sleep";
|
static const char *TAG = "sleep";
|
||||||
|
|
||||||
@@ -71,13 +72,19 @@ void esp_sleep_config_gpio_isolate(void)
|
|||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D), GPIO_PULLUP_ONLY);
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D), GPIO_PULLUP_ONLY);
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_HD), GPIO_PULLUP_ONLY);
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_HD), GPIO_PULLUP_ONLY);
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_WP), GPIO_PULLUP_ONLY);
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_WP), GPIO_PULLUP_ONLY);
|
||||||
#if CONFIG_SPIRAM_MODE_OCT || CONFIG_ESPTOOLPY_FLASHMODE_OPI
|
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_DQS), GPIO_PULLUP_ONLY);
|
bool octal_mspi_required = bootloader_flash_is_octal_mode_enabled();
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D4), GPIO_PULLUP_ONLY);
|
#if CONFIG_SPIRAM_MODE_OCT
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D5), GPIO_PULLUP_ONLY);
|
octal_mspi_required |= true;
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D6), GPIO_PULLUP_ONLY);
|
#endif // CONFIG_SPIRAM_MODE_OCT
|
||||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D7), GPIO_PULLUP_ONLY);
|
if (octal_mspi_required) {
|
||||||
#endif // CONFIG_SPIRAM_MODE_OCT || CONFIG_ESPTOOLPY_FLASHMODE_OPI
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_DQS), GPIO_PULLUP_ONLY);
|
||||||
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D4), GPIO_PULLUP_ONLY);
|
||||||
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D5), GPIO_PULLUP_ONLY);
|
||||||
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D6), GPIO_PULLUP_ONLY);
|
||||||
|
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_D7), GPIO_PULLUP_ONLY);
|
||||||
|
}
|
||||||
|
#endif // SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
#endif // CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
|
#endif // CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -364,7 +364,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);
|
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 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
|
#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
#if CONFIG_ESPTOOLPY_OCT_FLASH && !CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT
|
||||||
bool efuse_opflash_en = efuse_ll_get_flash_type();
|
bool efuse_opflash_en = efuse_ll_get_flash_type();
|
||||||
if (!efuse_opflash_en) {
|
if (!efuse_opflash_en) {
|
||||||
ESP_EARLY_LOGE(TAG, "Octal Flash option selected, but EFUSE not configured!");
|
ESP_EARLY_LOGE(TAG, "Octal Flash option selected, but EFUSE not configured!");
|
||||||
|
@@ -14,6 +14,25 @@ menu "Serial flasher config"
|
|||||||
bool "Enable Octal Flash"
|
bool "Enable Octal Flash"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config ESPTOOLPY_FLASH_MODE_AUTO_DETECT
|
||||||
|
depends on IDF_TARGET_ESP32S3
|
||||||
|
bool "Choose flash mode automatically (please read help)"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This config option helps decide whether flash is Quad or Octal, but please note some limitations:
|
||||||
|
|
||||||
|
1. If the flash chip is an Octal one, even if one of "QIO", "QOUT", "DIO", "DOUT" options is
|
||||||
|
selected in `ESPTOOLPY_FLASHMODE`, our code will automatically change the
|
||||||
|
mode to "OPI" and the sample mode will be STR.
|
||||||
|
2. If the flash chip is a Quad one, even if "OPI" is selected in `ESPTOOLPY_FLASHMODE`, our code will
|
||||||
|
automatically change the mode to "DIO".
|
||||||
|
3. Please do not rely on this option when you are pretty sure that you are using Octal flash,
|
||||||
|
please enable `ESPTOOLPY_OCT_FLASH` option, then you can choose `DTR` sample mode
|
||||||
|
in `ESPTOOLPY_FLASH_SAMPLE_MODE`. Otherwise, only `STR` mode is available.
|
||||||
|
4. Enabling this feature reduces available internal RAM size (around 900 bytes).
|
||||||
|
If your IRAM space is insufficient and you're aware of your flash type,
|
||||||
|
disable this option and select corresponding flash type options.
|
||||||
|
|
||||||
choice ESPTOOLPY_FLASHMODE
|
choice ESPTOOLPY_FLASHMODE
|
||||||
prompt "Flash SPI mode"
|
prompt "Flash SPI mode"
|
||||||
default ESPTOOLPY_FLASHMODE_DIO
|
default ESPTOOLPY_FLASHMODE_DIO
|
||||||
|
@@ -29,7 +29,7 @@ else()
|
|||||||
"flash_brownout_hook.c"
|
"flash_brownout_hook.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CONFIG_ESPTOOLPY_OCT_FLASH)
|
if(CONFIG_SOC_SPI_MEM_SUPPORT_OPI_MODE)
|
||||||
list(APPEND srcs "${target}/spi_flash_oct_flash_init.c")
|
list(APPEND srcs "${target}/spi_flash_oct_flash_init.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "soc/spi_mem_reg.h"
|
#include "soc/spi_mem_reg.h"
|
||||||
#include "spi_timing_config.h"
|
#include "spi_timing_config.h"
|
||||||
#include "esp_private/spi_flash_os.h"
|
#include "esp_private/spi_flash_os.h"
|
||||||
|
#include "bootloader_flash.h"
|
||||||
|
|
||||||
#define OPI_PSRAM_SYNC_READ 0x0000
|
#define OPI_PSRAM_SYNC_READ 0x0000
|
||||||
#define OPI_PSRAM_SYNC_WRITE 0x8080
|
#define OPI_PSRAM_SYNC_WRITE 0x8080
|
||||||
@@ -106,9 +107,7 @@ typedef enum {
|
|||||||
PSRAM_CMD_SPI,
|
PSRAM_CMD_SPI,
|
||||||
} psram_cmd_mode_t;
|
} psram_cmd_mode_t;
|
||||||
|
|
||||||
#if !CONFIG_ESPTOOLPY_OCT_FLASH
|
|
||||||
static uint8_t s_rom_flash_extra_dummy[2] = {NOT_INIT_INT, NOT_INIT_INT};
|
static uint8_t s_rom_flash_extra_dummy[2] = {NOT_INIT_INT, NOT_INIT_INT};
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_MODE_QUAD
|
#if CONFIG_SPIRAM_MODE_QUAD
|
||||||
static uint8_t s_psram_extra_dummy;
|
static uint8_t s_psram_extra_dummy;
|
||||||
@@ -137,7 +136,6 @@ void spi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode,
|
|||||||
REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
|
REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_ESPTOOLPY_OCT_FLASH
|
|
||||||
static uint32_t spi_timing_config_get_dummy(void)
|
static uint32_t spi_timing_config_get_dummy(void)
|
||||||
{
|
{
|
||||||
uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
|
uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
|
||||||
@@ -185,21 +183,21 @@ static uint32_t spi_timing_config_get_dummy(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
|
void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
if (extra_dummy > 0) {
|
if (extra_dummy > 0) {
|
||||||
SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
|
SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy,
|
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy,
|
||||||
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
|
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
|
||||||
} else {
|
} else {
|
||||||
CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
|
CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0,
|
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0,
|
||||||
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
|
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/**
|
/**
|
||||||
* The `SPI_MEM_TIMING_CALI_REG` register is only used for OPI on 728
|
* The `SPI_MEM_TIMING_CALI_REG` register is only used for OPI on 728
|
||||||
* Here we only need to update this global variable for extra dummy. Since we use the ROM Flash API, which will set the dummy based on this.
|
* Here we only need to update this global variable for extra dummy. Since we use the ROM Flash API, which will set the dummy based on this.
|
||||||
@@ -213,7 +211,6 @@ void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm
|
|||||||
// Only Quad Flash will run into this branch.
|
// Only Quad Flash will run into this branch.
|
||||||
uint32_t dummy = spi_timing_config_get_dummy();
|
uint32_t dummy = spi_timing_config_get_dummy();
|
||||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, dummy + g_rom_spiflash_dummy_len_plus[spi_num], SPI_MEM_USR_DUMMY_CYCLELEN_S);
|
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, dummy + g_rom_spiflash_dummy_len_plus[spi_num], SPI_MEM_USR_DUMMY_CYCLELEN_S);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------PSRAM timing tuning register config-------------------------------------//
|
//-------------------------------------PSRAM timing tuning register config-------------------------------------//
|
||||||
@@ -252,17 +249,17 @@ void spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm
|
|||||||
//-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------//
|
//-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------//
|
||||||
void spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
|
void spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
// note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
|
// note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
|
||||||
// but after we change the timing settings, we might not read correct idle status via RDSR.
|
// but after we change the timing settings, we might not read correct idle status via RDSR.
|
||||||
// so, here we should use a read API that won't check idle status.
|
// so, here we should use a read API that won't check idle status.
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
REG_WRITE(SPI_MEM_W0_REG(1) + i*4, 0);
|
REG_WRITE(SPI_MEM_W0_REG(1) + i*4, 0);
|
||||||
|
}
|
||||||
|
esp_rom_opiflash_read_raw(addr, buf, len);
|
||||||
|
} else {
|
||||||
|
esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
|
||||||
}
|
}
|
||||||
esp_rom_opiflash_read_raw(addr, buf, len);
|
|
||||||
#else
|
|
||||||
esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
|
static void s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "esp_private/cache_utils.h"
|
#include "esp_private/cache_utils.h"
|
||||||
#include "esp_spi_flash_counters.h"
|
#include "esp_spi_flash_counters.h"
|
||||||
#include "esp_rom_spiflash.h"
|
#include "esp_rom_spiflash.h"
|
||||||
|
#include "bootloader_flash.h"
|
||||||
|
|
||||||
__attribute__((unused)) static const char TAG[] = "spi_flash";
|
__attribute__((unused)) static const char TAG[] = "spi_flash";
|
||||||
|
|
||||||
@@ -61,18 +62,25 @@ esp_flash_t *esp_flash_default_chip = NULL;
|
|||||||
|
|
||||||
#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO)
|
#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_QIO
|
#define DEFAULT_FLASH_MODE SPI_FLASH_QIO
|
||||||
|
#define FLASH_MODE_STRING "qio"
|
||||||
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT)
|
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_QOUT
|
#define DEFAULT_FLASH_MODE SPI_FLASH_QOUT
|
||||||
|
#define FLASH_MODE_STRING "qout"
|
||||||
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO)
|
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_DIO
|
#define DEFAULT_FLASH_MODE SPI_FLASH_DIO
|
||||||
|
#define FLASH_MODE_STRING "dio"
|
||||||
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
|
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_DOUT
|
#define DEFAULT_FLASH_MODE SPI_FLASH_DOUT
|
||||||
|
#define FLASH_MODE_STRING "dout"
|
||||||
#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR)
|
#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_STR
|
#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_STR
|
||||||
|
#define FLASH_MODE_STRING "opi_str"
|
||||||
#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR)
|
#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR)
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_DTR
|
#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_DTR
|
||||||
|
#define FLASH_MODE_STRING "opi_dtr"
|
||||||
#else
|
#else
|
||||||
#define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD
|
#define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD
|
||||||
|
#define FLASH_MODE_STRING "fast_rd"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//TODO: modify cs hold to meet requirements of all chips!!!
|
//TODO: modify cs hold to meet requirements of all chips!!!
|
||||||
@@ -326,6 +334,29 @@ static DRAM_ATTR esp_flash_t default_chip = {
|
|||||||
.os_func = &esp_flash_noos_functions,
|
.os_func = &esp_flash_noos_functions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT
|
||||||
|
/* This function is used to correct flash mode if config option is not consistent with efuse information */
|
||||||
|
static void s_esp_flash_choose_correct_mode(memspi_host_config_t *cfg)
|
||||||
|
{
|
||||||
|
static const char *mode = FLASH_MODE_STRING;
|
||||||
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
|
#if !CONFIG_ESPTOOLPY_FLASHMODE_OPI
|
||||||
|
ESP_EARLY_LOGW(TAG, "Octal flash chip is using but %s mode is selected, will automatically swich to Octal mode", mode);
|
||||||
|
cfg->octal_mode_en = 1;
|
||||||
|
cfg->default_io_mode = SPI_FLASH_OPI_STR;
|
||||||
|
default_chip.read_mode = SPI_FLASH_OPI_STR;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if CONFIG_ESPTOOLPY_FLASHMODE_OPI
|
||||||
|
ESP_EARLY_LOGW(TAG, "Quad flash chip is using but %s flash mode is selected, will automatically swich to DIO mode", mode);
|
||||||
|
cfg->octal_mode_en = 0;
|
||||||
|
cfg->default_io_mode = SPI_FLASH_DIO;
|
||||||
|
default_chip.read_mode = SPI_FLASH_DIO;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT
|
||||||
|
|
||||||
extern esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip);
|
extern esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip);
|
||||||
esp_err_t esp_flash_init_default_chip(void)
|
esp_err_t esp_flash_init_default_chip(void)
|
||||||
{
|
{
|
||||||
@@ -342,6 +373,12 @@ esp_err_t esp_flash_init_default_chip(void)
|
|||||||
cfg.default_io_mode = DEFAULT_FLASH_MODE;
|
cfg.default_io_mode = DEFAULT_FLASH_MODE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT
|
||||||
|
// Automatically detect flash mode in run time
|
||||||
|
s_esp_flash_choose_correct_mode(&cfg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// For chips need time tuning, get value directely from system here.
|
// For chips need time tuning, get value directely from system here.
|
||||||
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
|
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
|
||||||
if (spi_timing_is_tuned()) {
|
if (spi_timing_is_tuned()) {
|
||||||
|
@@ -155,27 +155,36 @@ void IRAM_ATTR spi_flash_rom_impl_init(void)
|
|||||||
|
|
||||||
void IRAM_ATTR esp_mspi_pin_init(void)
|
void IRAM_ATTR esp_mspi_pin_init(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH || CONFIG_SPIRAM_MODE_OCT
|
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
esp_rom_opiflash_pin_config();
|
bool octal_mspi_required = bootloader_flash_is_octal_mode_enabled();
|
||||||
extern void spi_timing_set_pin_drive_strength(void);
|
#if CONFIG_SPIRAM_MODE_OCT
|
||||||
spi_timing_set_pin_drive_strength();
|
octal_mspi_required |= true;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
if (octal_mspi_required) {
|
||||||
|
esp_rom_opiflash_pin_config();
|
||||||
|
extern void spi_timing_set_pin_drive_strength(void);
|
||||||
|
spi_timing_set_pin_drive_strength();
|
||||||
|
}
|
||||||
//Set F4R4 board pin drive strength. TODO: IDF-3663
|
//Set F4R4 board pin drive strength. TODO: IDF-3663
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
|
esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
return esp_opiflash_init(rom_spiflash_legacy_data->chip.device_id);
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
#else
|
return esp_opiflash_init(rom_spiflash_legacy_data->chip.device_id);
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3
|
} else
|
||||||
// Currently, only esp32s3 allows high performance mode.
|
#endif
|
||||||
return spi_flash_enable_high_performance_mode();
|
{
|
||||||
#else
|
#if CONFIG_IDF_TARGET_ESP32S3
|
||||||
return ESP_OK;
|
// Currently, only esp32s3 allows high performance mode.
|
||||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
return spi_flash_enable_high_performance_mode();
|
||||||
#endif // CONFIG_ESPTOOLPY_OCT_FLASH
|
#else
|
||||||
|
return ESP_OK;
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||||
@@ -207,14 +216,16 @@ void spi_flash_dump_counters(void)
|
|||||||
|
|
||||||
void IRAM_ATTR spi_flash_set_rom_required_regs(void)
|
void IRAM_ATTR spi_flash_set_rom_required_regs(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||||
//Disable the variable dummy mode when doing timing tuning
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
|
//Disable the variable dummy mode when doing timing tuning
|
||||||
/**
|
CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
|
||||||
* STR /DTR mode setting is done every time when `esp_rom_opiflash_exec_cmd` is called
|
/**
|
||||||
*
|
* STR /DTR mode setting is done every time when `esp_rom_opiflash_exec_cmd` is called
|
||||||
* Add any registers that are not set in ROM SPI flash functions here in the future
|
*
|
||||||
*/
|
* Add any registers that are not set in ROM SPI flash functions here in the future
|
||||||
|
*/
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,14 +233,14 @@ void IRAM_ATTR spi_flash_set_rom_required_regs(void)
|
|||||||
// This function will only be called when Octal PSRAM enabled.
|
// This function will only be called when Octal PSRAM enabled.
|
||||||
void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
|
void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
if (bootloader_flash_is_octal_mode_enabled()) {
|
||||||
//Flash chip requires MSPI specifically, call this function to set them
|
esp_opiflash_set_required_regs();
|
||||||
esp_opiflash_set_required_regs();
|
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 1, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 1, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
|
} else {
|
||||||
#else
|
//Flash chip requires MSPI specifically, call this function to set them
|
||||||
// Set back MSPI registers after Octal PSRAM initialization.
|
// Set back MSPI registers after Octal PSRAM initialization.
|
||||||
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 0, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
|
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 0, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
|
||||||
#endif // CONFIG_ESPTOOLPY_OCT_FLASH
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -17,5 +17,5 @@ entries:
|
|||||||
spi_flash_chip_mxic_opi (noflash)
|
spi_flash_chip_mxic_opi (noflash)
|
||||||
spi_flash_hpm_enable (noflash)
|
spi_flash_hpm_enable (noflash)
|
||||||
|
|
||||||
if IDF_TARGET_ESP32S3 = y && ESPTOOLPY_OCT_FLASH = y:
|
if ESPTOOLPY_OCT_FLASH = y || ESPTOOLPY_FLASH_MODE_AUTO_DETECT = y:
|
||||||
spi_flash_oct_flash_init (noflash)
|
spi_flash_oct_flash_init (noflash)
|
||||||
|
Reference in New Issue
Block a user