mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
Merge branch 'feature/support_hpm_on_flash_4.4' into 'release/v4.4'
spi_flash: Building a framework to enable HPM when flash works under high speed mode, take GD as an example.(backport v4.4) See merge request espressif/esp-idf!17758
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -24,10 +24,13 @@
|
||||
#define CMD_RDID 0x9F
|
||||
#define CMD_WRSR 0x01
|
||||
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
|
||||
#define CMD_WRSR3 0x11 /* Not all SPI flash uses this command */
|
||||
#define CMD_WREN 0x06
|
||||
#define CMD_WRENVSR 0x50 /* Flash write enable for volatile SR bits */
|
||||
#define CMD_WRDI 0x04
|
||||
#define CMD_RDSR 0x05
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_RDSR3 0x15 /* Not all SPI flash uses this command */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
||||
#define CMD_WRAP 0x77 /* Set burst with wrap command */
|
||||
@ -171,4 +174,12 @@ uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_n
|
||||
*/
|
||||
void bootloader_enable_wp(void);
|
||||
|
||||
/**
|
||||
* @brief Once this function is called,
|
||||
* any on-going internal operations will be terminated and the device will return to its default power-on
|
||||
* state and lose all the current volatile settings, such as Volatile Status Register bits, Write Enable Latch
|
||||
* (WEL) status, Program/Erase Suspend status, etc.
|
||||
*/
|
||||
void bootloader_spi_flash_reset(void);
|
||||
|
||||
#endif
|
||||
|
@ -573,7 +573,7 @@ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||
#ifndef g_rom_spiflash_dummy_len_plus // ESP32-C3 uses a macro to access ROM data here
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
#endif
|
||||
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
|
||||
IRAM_ATTR uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t command,
|
||||
uint32_t addr_len, uint32_t address,
|
||||
uint8_t dummy_len,
|
||||
@ -603,14 +603,12 @@ IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
|
||||
SPIFLASH.addr = address;
|
||||
#endif
|
||||
//dummy phase
|
||||
uint32_t total_dummy = dummy_len;
|
||||
if (miso_len > 0) {
|
||||
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
|
||||
SPIFLASH.user.usr_dummy = total_dummy > 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
|
||||
} else {
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = 0;
|
||||
total_dummy += g_rom_spiflash_dummy_len_plus[1];
|
||||
}
|
||||
SPIFLASH.user.usr_dummy = total_dummy > 0;
|
||||
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
|
||||
//output data
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -679,6 +677,12 @@ uint32_t IRAM_ATTR bootloader_read_flash_id(void)
|
||||
return id;
|
||||
}
|
||||
|
||||
void bootloader_spi_flash_reset(void)
|
||||
{
|
||||
bootloader_execute_flash_command(0x66, 0, 0, 0);
|
||||
bootloader_execute_flash_command(0x99, 0, 0, 0);
|
||||
}
|
||||
|
||||
#if SOC_CACHE_SUPPORT_WRAP
|
||||
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
|
@ -218,6 +218,11 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPI_FLASH_HPM_ENABLE
|
||||
// Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.
|
||||
bootloader_spi_flash_reset();
|
||||
#endif
|
||||
|
||||
bootloader_flash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
|
@ -168,6 +168,11 @@ unsigned bootloader_read_status_8b_rdsr2(void)
|
||||
return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
}
|
||||
|
||||
unsigned bootloader_read_status_8b_rdsr3(void)
|
||||
{
|
||||
return bootloader_execute_flash_command(CMD_RDSR3, 0, 0, 8);
|
||||
}
|
||||
|
||||
unsigned bootloader_read_status_16b_rdsr_rdsr2(void)
|
||||
{
|
||||
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
@ -183,6 +188,11 @@ void bootloader_write_status_8b_wrsr2(unsigned new_status)
|
||||
bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0);
|
||||
}
|
||||
|
||||
void bootloader_write_status_8b_wrsr3(unsigned new_status)
|
||||
{
|
||||
bootloader_execute_flash_command(CMD_WRSR3, new_status, 8, 0);
|
||||
}
|
||||
|
||||
void bootloader_write_status_16b_wrsr(unsigned new_status)
|
||||
{
|
||||
bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
|
@ -128,6 +128,7 @@ menu "Serial flasher config"
|
||||
config ESPTOOLPY_FLASHFREQ_120M
|
||||
depends on IDF_TARGET_ESP32S3 && ESPTOOLPY_FLASH_SAMPLE_MODE_STR
|
||||
bool "120 MHz"
|
||||
select SPI_FLASH_HPM_ENABLE
|
||||
config ESPTOOLPY_FLASHFREQ_80M
|
||||
bool "80 MHz"
|
||||
config ESPTOOLPY_FLASHFREQ_40M
|
||||
|
@ -15,7 +15,17 @@ set(ESPSECUREPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py")
|
||||
set(ESPEFUSEPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py")
|
||||
set(ESPMONITOR ${python} "${idf_path}/tools/idf_monitor.py")
|
||||
|
||||
set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE})
|
||||
if(CONFIG_SPI_FLASH_HPM_ENABLE)
|
||||
# When set flash frequency to 120M, must keep 1st bootloader work under ``DOUT`` mode
|
||||
# because on some flash chips, 120M will modify the status register,
|
||||
# which will make ROM won't work.
|
||||
# This change intends to be for esptool only and the bootloader should keep use
|
||||
# ``DOUT`` mode.
|
||||
set(ESPFLASHMODE "dout")
|
||||
message("Note: HPM is enabled for the flash, force the ROM bootloader into DOUT mode for stable boot on")
|
||||
else()
|
||||
set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE})
|
||||
endif()
|
||||
set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ})
|
||||
set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE})
|
||||
|
||||
|
@ -22,7 +22,8 @@ else()
|
||||
if(CONFIG_IDF_TARGET_ESP32S3)
|
||||
list(APPEND srcs
|
||||
"esp32s3/spi_timing_config.c"
|
||||
"spi_flash_timing_tuning.c")
|
||||
"spi_flash_timing_tuning.c"
|
||||
"spi_flash_hpm_enable.c")
|
||||
endif()
|
||||
|
||||
# New implementation after IDF v4.0
|
||||
|
@ -279,4 +279,11 @@ menu "SPI Flash driver"
|
||||
application is not using flash encryption feature and is in need of some additional
|
||||
memory from IRAM region (~1KB) then this config can be disabled.
|
||||
|
||||
config SPI_FLASH_HPM_ENABLE
|
||||
bool
|
||||
default n
|
||||
help
|
||||
This option is invisible, and will be selected automatically
|
||||
when ``ESPTOOLPY_FLASHFREQ_120M`` is selected.
|
||||
|
||||
endmenu
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "spi_timing_config.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
#include "spi_flash_override.h"
|
||||
|
||||
#define OPI_PSRAM_SYNC_READ 0x0000
|
||||
#define OPI_PSRAM_SYNC_WRITE 0x8080
|
||||
@ -136,6 +138,56 @@ 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);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
static uint32_t spi_timing_config_get_dummy(void)
|
||||
{
|
||||
uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
|
||||
if (ctrl_reg & MULTI_LINE_MASK_OCT_FLASH) {
|
||||
abort();
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_HPM_ENABLE
|
||||
if (spi_flash_hpm_dummy_adjust()) { // HPM is enabled
|
||||
const spi_flash_hpm_dummy_conf_t *hpm_dummy = spi_flash_hpm_get_dummy();
|
||||
switch (ctrl_reg & MULTI_LINE_MASK_QUAD_FLASH) {
|
||||
case SPI_FLASH_QIO_MODE:
|
||||
return hpm_dummy->qio_dummy - 1;
|
||||
case SPI_FLASH_QUAD_MODE:
|
||||
return hpm_dummy->qout_dummy - 1;
|
||||
case SPI_FLASH_DIO_MODE:
|
||||
return hpm_dummy->dio_dummy - 1;
|
||||
case SPI_FLASH_DUAL_MODE:
|
||||
return hpm_dummy->dout_dummy - 1;
|
||||
case SPI_FLASH_FAST_MODE:
|
||||
return hpm_dummy->fastrd_dummy - 1;
|
||||
case SPI_FLASH_SLOW_MODE:
|
||||
return 0;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{ // HPM is not enabled
|
||||
switch (ctrl_reg & MULTI_LINE_MASK_QUAD_FLASH) {
|
||||
case SPI_FLASH_QIO_MODE:
|
||||
return SPI1_R_QIO_DUMMY_CYCLELEN;
|
||||
case SPI_FLASH_QUAD_MODE:
|
||||
return SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
case SPI_FLASH_DIO_MODE:
|
||||
return SPI1_R_DIO_DUMMY_CYCLELEN;
|
||||
case SPI_FLASH_DUAL_MODE:
|
||||
return SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
case SPI_FLASH_FAST_MODE:
|
||||
return SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
case SPI_FLASH_SLOW_MODE:
|
||||
return 0;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
|
||||
{
|
||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
@ -159,33 +211,7 @@ void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm
|
||||
}
|
||||
g_rom_spiflash_dummy_len_plus[spi_num] = s_rom_flash_extra_dummy[spi_num] + extra_dummy;
|
||||
|
||||
uint32_t dummy;
|
||||
uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_CTRL_REG(0));
|
||||
if (ctrl_reg & MULTI_LINE_MASK_OCT_FLASH) {
|
||||
abort();
|
||||
}
|
||||
switch (ctrl_reg & MULTI_LINE_MASK_QUAD_FLASH) {
|
||||
case SPI_FLASH_QIO_MODE:
|
||||
dummy = SPI1_R_QIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case SPI_FLASH_QUAD_MODE:
|
||||
dummy = SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case SPI_FLASH_DIO_MODE:
|
||||
dummy = SPI1_R_DIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case SPI_FLASH_DUAL_MODE:
|
||||
dummy = SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case SPI_FLASH_FAST_MODE:
|
||||
dummy = SPI1_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case SPI_FLASH_SLOW_MODE:
|
||||
dummy = 0;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
@ -331,6 +331,13 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPI_FLASH_HPM_ENABLE
|
||||
if (spi_flash_hpm_dummy_adjust()) {
|
||||
default_chip.hpm_dummy_ena = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -187,9 +187,13 @@ esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
|
||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
return esp_opiflash_init(rom_spiflash_legacy_data->chip.device_id);
|
||||
#else
|
||||
//currently we don't need other setup for initialising Quad Flash
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
// Currently, only esp32s3 allows high performance mode.
|
||||
return spi_flash_enable_high_performance_mode();
|
||||
#else
|
||||
return ESP_OK;
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||
#endif // CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
}
|
||||
|
||||
void spi_flash_init(void)
|
||||
|
@ -103,7 +103,8 @@ struct esp_flash_t {
|
||||
uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation.
|
||||
uint32_t chip_id; ///< Detected chip id.
|
||||
uint32_t busy :1; ///< This flag is used to verify chip's status.
|
||||
uint32_t reserved_flags :31; ///< reserved.
|
||||
uint32_t hpm_dummy_ena :1; ///< This flag is used to verify whether flash works under HPM status.
|
||||
uint32_t reserved_flags :30; ///< reserved.
|
||||
};
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "esp_flash.h"
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "spi_flash_override.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -138,6 +139,28 @@ bool spi_timing_is_tuned(void);
|
||||
*/
|
||||
void spi_flash_set_vendor_required_regs(void);
|
||||
|
||||
/**
|
||||
* @brief Enable SPI flash high performance mode.
|
||||
*
|
||||
* @return ESP_OK if success.
|
||||
*/
|
||||
esp_err_t spi_flash_enable_high_performance_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Get the flash dummy through this function
|
||||
* This can be used when one flash has several dummy configurations to enable the high performance mode.
|
||||
* @note Don't forget to subtract one when assign to the register of mspi e.g. if the value you get is 4, (4-1=3) should be assigned to the register.
|
||||
*
|
||||
* @return Pointer to spi_flash_hpm_dummy_conf_t.
|
||||
*/
|
||||
const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void);
|
||||
|
||||
/**
|
||||
* @brief Used to judge whether flash works under HPM mode with dummy adjustment.
|
||||
*
|
||||
* @return true Yes, and work under HPM with adjusting dummy. Otherwise, false.
|
||||
*/
|
||||
bool spi_flash_hpm_dummy_adjust(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -52,6 +44,7 @@
|
||||
#define CMD_PROGRAM_PAGE_4B 0x12
|
||||
#define CMD_SUSPEND 0x75
|
||||
#define CMD_RESUME 0x7A
|
||||
#define CMD_HPMEN 0xA3 /* Enable High Performance mode on flash */
|
||||
|
||||
#define CMD_RST_EN 0x66
|
||||
#define CMD_RST_DEV 0x99
|
||||
@ -72,3 +65,5 @@
|
||||
#define SPI_FLASH_OPISTR_DUMMY_BITLEN 20
|
||||
#define SPI_FLASH_OPIDTR_ADDR_BITLEN 32
|
||||
#define SPI_FLASH_OPIDTR_DUMMY_BITLEN 40
|
||||
#define SPI_FLASH_QIO_HPM_DUMMY_BITLEN 10
|
||||
#define SPI_FLASH_DIO_HPM_DUMMY_BITLEN 8
|
||||
|
62
components/spi_flash/include/spi_flash_override.h
Normal file
62
components/spi_flash/include/spi_flash_override.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Structure for flash dummy bits.
|
||||
* For some flash chips, dummy bits are configurable under different conditions.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t dio_dummy;
|
||||
uint8_t dout_dummy;
|
||||
uint8_t qio_dummy;
|
||||
uint8_t qout_dummy;
|
||||
uint8_t fastrd_dummy;
|
||||
} spi_flash_hpm_dummy_conf_t;
|
||||
|
||||
typedef enum {
|
||||
SPI_FLASH_HPM_CMD_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by command.
|
||||
SPI_FLASH_HPM_DUMMY_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by adjusting dummy.
|
||||
SPI_FLASH_HPM_WRITE_SR_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode by writing status register.
|
||||
SPI_FLASH_HPM_UNNEEDED, // Means that flash doesn't need to enter the high performance mode.
|
||||
SPI_FLASH_HPM_BEYOND_LIMIT, // Means that flash has no capability to meet that condition.
|
||||
} spi_flash_requirement_t;
|
||||
|
||||
typedef void (*spi_flash_hpm_enable_fn_t)(void);
|
||||
typedef esp_err_t (*spi_flash_hpf_check_fn_t)(void);
|
||||
typedef void (*spi_flash_get_chip_dummy_fn_t)(spi_flash_hpm_dummy_conf_t *dummy_conf);
|
||||
typedef esp_err_t (*spi_flash_hpm_probe_fn_t)(uint32_t flash_id);
|
||||
typedef spi_flash_requirement_t (*spi_flash_hpm_chip_requirement_check_t)(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperature);
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
const char *method; /* Flash HPM method */
|
||||
spi_flash_hpm_probe_fn_t probe;
|
||||
spi_flash_hpm_chip_requirement_check_t chip_hpm_requirement_check;
|
||||
spi_flash_hpm_enable_fn_t flash_hpm_enable;
|
||||
spi_flash_hpf_check_fn_t flash_hpf_check;
|
||||
spi_flash_get_chip_dummy_fn_t flash_get_dummy;
|
||||
} spi_flash_hpm_info_t;
|
||||
|
||||
/**
|
||||
* Array of known flash chips and method to enable flash high performance mode.
|
||||
*
|
||||
* Users can override this array.
|
||||
*/
|
||||
extern const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -14,9 +14,8 @@ entries:
|
||||
if IDF_TARGET_ESP32S3 = y:
|
||||
spi_flash_timing_tuning (noflash)
|
||||
spi_timing_config (noflash)
|
||||
spi_flash_chip_mxic_opi (noflash)
|
||||
spi_flash_hpm_enable (noflash)
|
||||
|
||||
if IDF_TARGET_ESP32S3 = y && ESPTOOLPY_OCT_FLASH = y:
|
||||
spi_flash_oct_flash_init (noflash)
|
||||
|
||||
if IDF_TARGET_ESP32S3 = y :
|
||||
spi_flash_chip_mxic_opi (noflash)
|
||||
|
@ -40,6 +40,16 @@ DRAM_ATTR const static flash_chip_dummy_t default_flash_chip_dummy = {
|
||||
.slowrd_dummy_bitlen = SPI_FLASH_SLOWRD_DUMMY_BITLEN,
|
||||
};
|
||||
|
||||
DRAM_ATTR const static flash_chip_dummy_t hpm_flash_chip_dummy = {
|
||||
.dio_dummy_bitlen = SPI_FLASH_DIO_HPM_DUMMY_BITLEN,
|
||||
.qio_dummy_bitlen = SPI_FLASH_QIO_HPM_DUMMY_BITLEN,
|
||||
.qout_dummy_bitlen = SPI_FLASH_QOUT_DUMMY_BITLEN,
|
||||
.dout_dummy_bitlen = SPI_FLASH_DOUT_DUMMY_BITLEN,
|
||||
.fastrd_dummy_bitlen = SPI_FLASH_FASTRD_DUMMY_BITLEN,
|
||||
.slowrd_dummy_bitlen = SPI_FLASH_SLOWRD_DUMMY_BITLEN,
|
||||
};
|
||||
|
||||
|
||||
// These are the pointer to HW flash encryption. Default using hardware encryption.
|
||||
DRAM_ATTR static spi_flash_encryption_t esp_flash_encryption_default __attribute__((__unused__)) = {
|
||||
.flash_encryption_enable = spi_flash_encryption_hal_enable,
|
||||
@ -52,6 +62,8 @@ DRAM_ATTR static spi_flash_encryption_t esp_flash_encryption_default __attribute
|
||||
|
||||
DRAM_ATTR flash_chip_dummy_t *rom_flash_chip_dummy = (flash_chip_dummy_t *)&default_flash_chip_dummy;
|
||||
|
||||
DRAM_ATTR flash_chip_dummy_t *rom_flash_chip_dummy_hpm = (flash_chip_dummy_t *)&hpm_flash_chip_dummy;
|
||||
|
||||
#define SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS 200
|
||||
#define SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS 4000
|
||||
#define SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS 600 //according to GD25Q127(125°) + 100ms
|
||||
@ -462,35 +474,35 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t
|
||||
case SPI_FLASH_QIO:
|
||||
//for QIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
|
||||
addr_bitlen = SPI_FLASH_QIO_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->qio_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qio_dummy_bitlen : rom_flash_chip_dummy->qio_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_FASTRD_QIO_4B: CMD_FASTRD_QIO);
|
||||
conf_required = true;
|
||||
break;
|
||||
case SPI_FLASH_QOUT:
|
||||
addr_bitlen = SPI_FLASH_QOUT_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->qout_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qout_dummy_bitlen : rom_flash_chip_dummy->qout_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_FASTRD_QUAD_4B: CMD_FASTRD_QUAD);
|
||||
break;
|
||||
case SPI_FLASH_DIO:
|
||||
//for DIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
|
||||
addr_bitlen = SPI_FLASH_DIO_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->dio_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dio_dummy_bitlen : rom_flash_chip_dummy->dio_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_FASTRD_DIO_4B: CMD_FASTRD_DIO);
|
||||
conf_required = true;
|
||||
break;
|
||||
case SPI_FLASH_DOUT:
|
||||
addr_bitlen = SPI_FLASH_DOUT_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->dout_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dout_dummy_bitlen : rom_flash_chip_dummy->dout_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_FASTRD_DUAL_4B: CMD_FASTRD_DUAL);
|
||||
break;
|
||||
case SPI_FLASH_FASTRD:
|
||||
addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->fastrd_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->fastrd_dummy_bitlen : rom_flash_chip_dummy->fastrd_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_FASTRD_4B: CMD_FASTRD);
|
||||
break;
|
||||
case SPI_FLASH_SLOWRD:
|
||||
addr_bitlen = SPI_FLASH_SLOWRD_ADDR_BITLEN;
|
||||
dummy_cyclelen_base = rom_flash_chip_dummy->slowrd_dummy_bitlen;
|
||||
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->slowrd_dummy_bitlen : rom_flash_chip_dummy->slowrd_dummy_bitlen);
|
||||
read_command = (addr_32bit? CMD_READ_4B: CMD_READ);
|
||||
break;
|
||||
default:
|
||||
|
331
components/spi_flash/spi_flash_hpm_enable.c
Normal file
331
components/spi_flash/spi_flash_hpm_enable.c
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "spi_flash_defs.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "spi_flash_override.h"
|
||||
|
||||
// TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
|
||||
#include "../bootloader_support/include_bootloader/bootloader_flash_priv.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Flash high speed performance mode.
|
||||
* HPM: High performance mode.
|
||||
* HPF: High performance flag.
|
||||
*
|
||||
* Different flash chips might have different high performance strategy.
|
||||
* 1. Some flash chips send A3H to enable the HPM.
|
||||
* 2. Some flash chips write HPF bit in status register.
|
||||
* 3. Some flash chips adjust dummy cycles.
|
||||
******************************************************************************/
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHFREQ_120M
|
||||
#define FLASH_FREQUENCY 120
|
||||
#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
|
||||
#define FLASH_FREQUENCY 80
|
||||
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
|
||||
#define FLASH_FREQUENCY 40
|
||||
#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
|
||||
#define FLASH_FREQUENCY 20
|
||||
#endif
|
||||
|
||||
const static char *HPM_TAG = "flash HPM";
|
||||
|
||||
// TODO: This function will be changed after remove bootloader_flash to G0.IDF-4609
|
||||
extern uint32_t bootloader_flash_execute_command_common(
|
||||
uint8_t command,
|
||||
uint32_t addr_len, uint32_t address,
|
||||
uint8_t dummy_len,
|
||||
uint8_t mosi_len, uint32_t mosi_data,
|
||||
uint8_t miso_len);
|
||||
extern unsigned bootloader_read_status_8b_rdsr3(void);
|
||||
extern void bootloader_write_status_8b_wrsr3(unsigned new_status);
|
||||
|
||||
extern uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
|
||||
|
||||
//-----------------For flash chips which enter HPM via command-----------------------//
|
||||
|
||||
/**
|
||||
* @brief Probe the chip whether use command to enable HPM mode. Take GD as an example:
|
||||
* Some GD send 0xA3 command to enable HPM mode of the flash.
|
||||
*/
|
||||
static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t gd_sfdp = 0;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0xC84016:
|
||||
case 0xC84017:
|
||||
// Read BYTE4 in SFDP, 0 means C series, 6 means E series
|
||||
gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
|
||||
if (gd_sfdp == 0x0) {
|
||||
break;
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_cmd(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
|
||||
{
|
||||
// voltage and temperature are not been used now, to be completed in the future.
|
||||
(void)voltage_mv;
|
||||
(void)temperautre;
|
||||
spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
if (freq_mhz > 80) {
|
||||
chip_cap = SPI_FLASH_HPM_CMD_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with command, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send HPMEN command (A3H)
|
||||
*/
|
||||
static void spi_flash_enable_high_performance_send_cmd(void)
|
||||
{
|
||||
uint32_t dummy = 24;
|
||||
bootloader_flash_execute_command_common(CMD_HPMEN, 0, 0, dummy, 0, 0, 0);
|
||||
// Delay for T(HPM) refering to datasheet.
|
||||
esp_rom_delay_us(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether flash HPM has been enabled. According to flash datasheets, majorities of
|
||||
* HPF bit are at bit-5, sr-3. But some are not. Therefore, this function is only used for those
|
||||
* HPF bit is at bit-5, sr-3.
|
||||
*/
|
||||
static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
|
||||
{
|
||||
if((bootloader_read_status_8b_rdsr3() & (1 << 4)) == 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
//-----------------For flash chips which enter HPM via adjust dummy-----------------------//
|
||||
|
||||
/**
|
||||
* @brief Probe the chip whether adjust dummy to enable HPM mode. Take XMC as an example:
|
||||
* Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
|
||||
* might be 6, but when works under 120MHz, the dummy bits might be 10.
|
||||
*/
|
||||
static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t gd_sfdp = 0;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM by adjusting dummy cycles */
|
||||
// GD chips.
|
||||
case 0xC84017:
|
||||
case 0xC84018:
|
||||
// Read BYTE4 in SFDP, 0 means C series, 6 means E series
|
||||
gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
|
||||
if (gd_sfdp == 0x6) {
|
||||
break;
|
||||
} else {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_dummy(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
|
||||
{
|
||||
// voltage and temperature are not been used now, to be completed in the future.
|
||||
(void)voltage_mv;
|
||||
(void)temperautre;
|
||||
spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_DUMMY_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adjust dummy cycles. This function modifies the Dummy Cycle Bits in SR3.
|
||||
* Usually, the bits are at bit-0, bit-1, sr-3 and set DC[1:0]=[1,1].
|
||||
*
|
||||
* @note Don't forget to adjust dummy configurations for MSPI, you can get the
|
||||
* correct dummy from interface `spi_flash_hpm_get_dummy`.
|
||||
*/
|
||||
static void spi_flash_turn_high_performance_reconfig_dummy(void)
|
||||
{
|
||||
uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
|
||||
uint8_t new_status = (old_status_3 | 0x03);
|
||||
bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
|
||||
bootloader_write_status_8b_wrsr3(new_status);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether HPM has been enabled. This function checks the DC bits
|
||||
*/
|
||||
static esp_err_t spi_flash_high_performance_check_dummy_sr(void)
|
||||
{
|
||||
if((bootloader_read_status_8b_rdsr3() & 0x03) == 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
||||
{
|
||||
dummy_conf->dio_dummy = 8;
|
||||
dummy_conf->dout_dummy = 8;
|
||||
dummy_conf->qio_dummy = 10;
|
||||
dummy_conf->qout_dummy = 8;
|
||||
dummy_conf->fastrd_dummy = 8;
|
||||
}
|
||||
|
||||
//-----------------For flash chips which enter HPM via write status register-----------------------//
|
||||
|
||||
/**
|
||||
* @brief Probe the chip whether to write status register to enable HPM mode. Take ZB as an example:
|
||||
* Write status register bits to enable HPM mode of the flash. If ZB works under 80MHz, the register value
|
||||
* would be 0, but when works under 120MHz, the register value would be 1.
|
||||
*/
|
||||
static esp_err_t spi_flash_hpm_probe_chip_with_write_hpf_bit_5(uint32_t flash_id)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM by adjusting dummy cycles */
|
||||
// ZB chips.
|
||||
case 0x5E4016:
|
||||
break;
|
||||
default:
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static spi_flash_requirement_t spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5(uint32_t flash_id, uint32_t freq_mhz, int voltage_mv, int temperautre)
|
||||
{
|
||||
// voltage and temperature are not been used now, to be completed in the future.
|
||||
(void)voltage_mv;
|
||||
(void)temperautre;
|
||||
spi_flash_requirement_t chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_WRITE_SR_NEEDED;
|
||||
}
|
||||
ESP_EARLY_LOGD(HPM_TAG, "HPM with dummy, status is %d", chip_cap);
|
||||
return chip_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write bit 5 in status 3
|
||||
*/
|
||||
static void spi_flash_turn_high_performance_write_hpf_bit_5(void)
|
||||
{
|
||||
uint8_t old_status_3 = bootloader_read_status_8b_rdsr3();
|
||||
uint8_t new_status = (old_status_3 | 0x10);
|
||||
bootloader_execute_flash_command(CMD_WRENVSR, 0, 0, 0);
|
||||
bootloader_write_status_8b_wrsr3(new_status);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
//-----------------------generic functions-------------------------------------//
|
||||
|
||||
/**
|
||||
* @brief Default dummy for almost all flash chips. If your flash does't need to reconfigure dummy,
|
||||
* just call this function.
|
||||
*/
|
||||
void __attribute__((weak)) spi_flash_hpm_get_dummy_generic(spi_flash_hpm_dummy_conf_t *dummy_conf)
|
||||
{
|
||||
dummy_conf->dio_dummy = 4;
|
||||
dummy_conf->dout_dummy = 8;
|
||||
dummy_conf->qio_dummy = 6;
|
||||
dummy_conf->qout_dummy = 8;
|
||||
dummy_conf->fastrd_dummy = 8;
|
||||
}
|
||||
|
||||
const spi_flash_hpm_info_t __attribute__((weak)) spi_flash_hpm_enable_list[] = {
|
||||
/* vendor, chip_id, freq_threshold, temperature threshold, operation for setting high performance, reading HPF status, get dummy */
|
||||
{ "command", spi_flash_hpm_probe_chip_with_cmd, spi_flash_hpm_chip_hpm_requirement_check_with_cmd, spi_flash_enable_high_performance_send_cmd, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic },
|
||||
{ "dummy", spi_flash_hpm_probe_chip_with_dummy, spi_flash_hpm_chip_hpm_requirement_check_with_dummy, spi_flash_turn_high_performance_reconfig_dummy, spi_flash_high_performance_check_dummy_sr, spi_flash_hpm_get_dummy_xmc},
|
||||
{ "write sr3-bit5", spi_flash_hpm_probe_chip_with_write_hpf_bit_5, spi_flash_hpm_chip_hpm_requirement_check_with_write_hpf_bit_5, spi_flash_turn_high_performance_write_hpf_bit_5, spi_flash_high_performance_check_hpf_bit_5, spi_flash_hpm_get_dummy_generic},
|
||||
// default: do nothing, but keep the dummy get function. The first item with NULL as its probe will be the fallback.
|
||||
{ "NULL", NULL, NULL, NULL, NULL, spi_flash_hpm_get_dummy_generic},
|
||||
};
|
||||
|
||||
static const spi_flash_hpm_info_t *chip_hpm = NULL;
|
||||
static spi_flash_hpm_dummy_conf_t dummy_conf;
|
||||
static bool hpm_dummy_changed = false;
|
||||
|
||||
esp_err_t spi_flash_enable_high_performance_mode(void)
|
||||
{
|
||||
uint32_t flash_chip_id = g_rom_flashchip.device_id;
|
||||
uint32_t flash_freq = FLASH_FREQUENCY;
|
||||
spi_flash_requirement_t hpm_requirement_check;
|
||||
// voltage and temperature has not been implemented, just leave an interface here. Complete in the future.
|
||||
int voltage = 0;
|
||||
int temperature = 0;
|
||||
|
||||
const spi_flash_hpm_info_t *chip = spi_flash_hpm_enable_list;
|
||||
esp_err_t ret = ESP_OK;
|
||||
while (chip->probe) {
|
||||
ret = chip->probe(flash_chip_id);
|
||||
if (ret == ESP_OK) {
|
||||
break;
|
||||
}
|
||||
chip++;
|
||||
}
|
||||
chip_hpm = chip;
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
#if (FLASH_FREQUENCY == 120)
|
||||
ESP_EARLY_LOGW(HPM_TAG, "Flash high performance mode hasn't been supported");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
hpm_requirement_check = chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature);
|
||||
if ((hpm_requirement_check == SPI_FLASH_HPM_CMD_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) || (hpm_requirement_check == SPI_FLASH_HPM_WRITE_SR_NEEDED)) {
|
||||
ESP_EARLY_LOGI(HPM_TAG, "Enabling flash high speed mode by %s", chip_hpm->method);
|
||||
chip_hpm->flash_hpm_enable();
|
||||
ESP_EARLY_LOGD(HPM_TAG, "Checking whether HPM has been executed");
|
||||
|
||||
if (chip_hpm->flash_hpf_check() != ESP_OK) {
|
||||
ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been executed successfully");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
hpm_dummy_changed = (hpm_requirement_check == SPI_FLASH_HPM_DUMMY_NEEDED) ? true : false;
|
||||
} else if (hpm_requirement_check == SPI_FLASH_HPM_BEYOND_LIMIT) {
|
||||
ESP_EARLY_LOGE(HPM_TAG, "Flash does not have the ability to raise to that frequency");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void)
|
||||
{
|
||||
chip_hpm->flash_get_dummy(&dummy_conf);
|
||||
return &dummy_conf;
|
||||
}
|
||||
|
||||
bool spi_flash_hpm_dummy_adjust(void)
|
||||
{
|
||||
return hpm_dummy_changed;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
.. _auto_suspend:
|
||||
.. _auto-suspend:
|
||||
|
||||
When auto suspend is enabled
|
||||
----------------------------
|
||||
|
@ -27,6 +27,9 @@ Encrypted reads and writes use the old implementation, even if :ref:`CONFIG_SPI_
|
||||
Support for features of flash chips
|
||||
-----------------------------------
|
||||
|
||||
Quad/Dual mode chips
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Flash features of different vendors are operated in different ways and need special support. The fast/slow read and Dual mode (DOUT/DIO) of almost all 24-bits address flash chips are supported, because they don't need any vendor-specific commands.
|
||||
|
||||
Quad mode (QIO/QOUT) is supported on following chip types:
|
||||
@ -39,18 +42,33 @@ Quad mode (QIO/QOUT) is supported on following chip types:
|
||||
6. XMC
|
||||
7. BOYA
|
||||
|
||||
Optional Features
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
spi_flash_optional_feature
|
||||
|
||||
There are some features that are not supported by all flash models, or not supported by all Espressif chips. These features include:
|
||||
|
||||
.. only:: esp32s3
|
||||
|
||||
Octal mode (OPI) are supported on following chip types:
|
||||
- OPI flash - means that flash supports octal mode.
|
||||
|
||||
1. MXIC
|
||||
- 32-bit address flash - usually means that the flash has higher capacity (equal to or larger than 16MB) that needs longer address to access.
|
||||
|
||||
To know how to configure menuconfig for a board with different Flash and PSRAM, please refer to the :ref:`SPI Flash and External SPI RAM Configuration <flash-psram-configuration>`
|
||||
.. only:: esp32s3
|
||||
|
||||
The 32-bit address range of following chip type is supported:
|
||||
- High performance mode (HPM) - means that flash works under high frequency which is higher than 80MHz.
|
||||
|
||||
1. W25Q256
|
||||
2. GD25Q256
|
||||
- Flash unique ID - means that flash supports its unique 64-bits ID.
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
- Suspend & Resume - means that flash can accept suspend/resume command during its writing/erasing. The {IDF_TARGET_NAME} may keep the cache on when the flash is being written/erased and suspend it to read its contents randomly.
|
||||
|
||||
If you want to use these features, you need to ensure {IDF_TARGET_NAME} supports this feature, and ALL the flash chips in your product have this feature. For more details, refer :doc:`spi_flash_optional_feature`.
|
||||
|
||||
Users can also customize their own flash chip driver, see :doc:`spi_flash_override_driver` for more details.
|
||||
|
||||
@ -169,7 +187,7 @@ The ``esp_flash_t`` structure holds chip data as well as three important parts o
|
||||
|
||||
1. The host driver, which provides the hardware support to access the chip;
|
||||
2. The chip driver, which provides compatibility service to different chips;
|
||||
3. The OS functions, provides support of some OS functions (e.g. lock, delay) in different stages (1st/2st boot, or the app).
|
||||
3. The OS functions, provide support of some OS functions (e.g. lock, delay) in different stages (1st/2nd boot, or the app).
|
||||
|
||||
Host driver
|
||||
^^^^^^^^^^^
|
||||
|
@ -9,7 +9,7 @@ The SPI0/1 bus is shared between the instruction & data cache (for firmware exec
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
On {IDF_TARGET_NAME}, the config option :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` (enabled by default) allows the cache to read flash & PSRAM concurrently with SPI1 operations. See :ref:`auto_suspend` for more details.
|
||||
On {IDF_TARGET_NAME}, the config option :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` (enabled by default) allows the cache to read flash & PSRAM concurrently with SPI1 operations. See :ref:`auto-suspend` for more details.
|
||||
|
||||
If this option is disabled, the caches must be disabled while reading/writing/erasing operations. There are some constraints using driver on the SPI1 bus, see :ref:`impact_disabled_cache`. This constraints will cause more IRAM/DRAM usages.
|
||||
|
||||
|
117
docs/en/api-reference/storage/spi_flash_optional_feature.rst
Normal file
117
docs/en/api-reference/storage/spi_flash_optional_feature.rst
Normal file
@ -0,0 +1,117 @@
|
||||
Optional features for flash
|
||||
===========================
|
||||
|
||||
Some features are not supported on all ESP chips and Flash chips. You can check the list below for more information.
|
||||
|
||||
- `Auto Suspend & Resume <#auto-suspend-&-resume>`__
|
||||
|
||||
- `Flash unique ID <#flash-unique-id>`__
|
||||
|
||||
- `High performance mode <#high-performance-mode>`__
|
||||
|
||||
- `OPI flash support <#opi-flash-support>`__
|
||||
|
||||
- `32-bit Address Flash Chips <#32-bit-address-flash-chips>`__
|
||||
|
||||
.. note::
|
||||
|
||||
- The features listed above needs to be supported by both esp chips and flash chips.
|
||||
|
||||
- If you are using an official Espressif modules/SiP. Some of the modules/SiPs always support the feature, in this case you can see these features listed in the datasheet. Otherwise please contact `Espressif's business team <https://www.espressif.com/en/contact-us/sales-questions>`_ to know if we can supply such products for you.
|
||||
|
||||
- If you are making your own modules with your own bought flash chips, and you need features listed above. Please contact your vendor if they support the those features, and make sure that the chips can be supplied continuously.
|
||||
|
||||
.. attention::
|
||||
|
||||
This document only shows that IDF code has supported the features of those flash chips. It's not a list of stable flash chips certified by Espressif. If you build your own hardware from flash chips with your own brought flash chips (even with flash listed in this page), you need to validate the reliability of flash chips yourself.
|
||||
|
||||
Auto Suspend & Resume
|
||||
---------------------
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
You can refer to :ref:`auto-suspend` for more information about this feature. The support list is as follows.
|
||||
|
||||
ESP Chips List:
|
||||
|
||||
1. ESP32C3
|
||||
|
||||
Flash Chips List:
|
||||
|
||||
1. XM25QxxC series.
|
||||
|
||||
Flash unique ID
|
||||
---------------
|
||||
|
||||
Unique ID is not flash id, which means flash has 64-Bit unique ID for each device. The instruction to read the unique ID (4Bh) accesses a factory-set read-only 64-bit number that is unique to each flash device. This ID number helps you to recognize each single device. Not all flash vendors support this feature. If you try to read the unique ID on a chip which does not have this feature, the behavior is not determined. The support list is as follows.
|
||||
|
||||
ESP Chips Lists:
|
||||
|
||||
ALL
|
||||
|
||||
Flash Chips List:
|
||||
|
||||
1. ISSI
|
||||
2. GD
|
||||
3. TH
|
||||
4. FM
|
||||
5. Winbond
|
||||
6. XMC
|
||||
7. BOYA
|
||||
|
||||
High performance mode
|
||||
---------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This section is provided for Dual mode (DOUT/DIO) and Quad mode (QIO/QOUT) flash chips. Octal flash used on ESP-chips support High performance mode by default so far, you can refer to the octal flash support list below.
|
||||
|
||||
High performance mode (HPM) means that the SPI1 and flash chip works under high frequency. Usually, when the operating frequency of the flash is greater than 80MHz, it is considered that the flash works under HPM. As far as we acknowledged, flash chips have more than two different coping strategies when flash work under HPM. For some flash chips, HPM is controlled by high performance flag (HPF) in status register and for some flash chips, HPM is controlled by dummy cycle bit.
|
||||
|
||||
For following conditions, IDF start code deals with HPM internally.
|
||||
|
||||
ESP Chips List:
|
||||
|
||||
1. ESP32S3
|
||||
|
||||
Flash Chips (name & ID) List:
|
||||
|
||||
1. GD25Q64C (ID: 0xC84017)
|
||||
2. GD25Q32C (ID: 0xC84016)
|
||||
|
||||
.. attention::
|
||||
|
||||
It is hard to create several strategies to cover all situations, so all flash chips using HPM need to be supported explicitly. Therefore, if you try to use a flash not listed as supported under high performance mode, it might cause some error. So, when you try to use the flash chip beyond supported list, please test properly.
|
||||
|
||||
OPI flash support
|
||||
-----------------
|
||||
|
||||
OPI flash means that the flash chip supports octal peripheral interface, which has octal I/O pins. Different octal flash has different configurations and different commands. Hence, it is necessary to carefully check the support list.
|
||||
|
||||
.. only:: esp32s3
|
||||
|
||||
.. note::
|
||||
|
||||
To know how to configure menuconfig for a board with different Flash and PSRAM, please refer to the :ref:`SPI Flash and External SPI RAM Configuration <flash-psram-configuration>`
|
||||
|
||||
ESP Chips List:
|
||||
|
||||
1. ESP32S3
|
||||
|
||||
Flash Chips List:
|
||||
|
||||
1. MX25UM25645G
|
||||
|
||||
32-bit Address Flash Chips
|
||||
--------------------------
|
||||
|
||||
Most NOR flash chips used by Espressif chips use 24-bits address, which can cover 16 MBytes memory. However, for larger memory (usually equal to or larger than 16 MBytes), flash uses a 32-bits address to address larger memory. Regretfully, 32-bits address chips have vendor-specific commands, so we need to support the chips one by one.
|
||||
|
||||
ESP Chips List:
|
||||
|
||||
ALL ESP Chips support this.
|
||||
|
||||
Flash Chips List:
|
||||
|
||||
1. W25Q256
|
||||
2. GD25Q256
|
@ -1,5 +1,5 @@
|
||||
|
||||
.. _auto_suspend:
|
||||
.. _auto-suspend:
|
||||
|
||||
当使能 flash 擦除的自动暂停
|
||||
--------------------------------------
|
||||
|
@ -27,6 +27,9 @@ Kconfig 选项 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` 可将 ``spi_flash_*``
|
||||
Flash 特性支持情况
|
||||
-----------------------------------
|
||||
|
||||
支持的 Flash 列表
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
不同厂家的 flash 特性有不同的操作方式,因此需要特殊的驱动支持。当前驱动支持大多数厂家 Flash 24 位地址范围内的快速/慢速读,以及二线模式 (DIO / DOUT),因为他们不需要任何厂家的自定义命令。
|
||||
|
||||
当前驱动支持以下厂家/型号的 flash 的四线模式 (QIO/QOUT):
|
||||
@ -39,18 +42,33 @@ Flash 特性支持情况
|
||||
6. XMC
|
||||
7. BOYA
|
||||
|
||||
Flash 可选的功能
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
spi_flash_optional_feature
|
||||
|
||||
有一些功能可能不是所有的 flash 芯片都支持,或不是所有的 ESP 芯片都支持。这些功能包括:
|
||||
|
||||
.. only:: esp32s3
|
||||
|
||||
下列 flash 芯片支持八线模式 (OPI):
|
||||
- OPI flash - 表示 Flash 支持 8 线模式。
|
||||
|
||||
1. MXIC
|
||||
- 32 比特地址的 flash 支持 - 通常意味着拥有大于 16MB 内存空间的大容量 flash 需要更长的地址去访问。
|
||||
|
||||
关于如何为具有不同 flash 和 PSRAM 容量的开发板设置 menuconfig,请参考 :ref:`SPI flash 和片外 SPI RAM 设置 <flash-psram-configuration>`。
|
||||
.. only:: esp32s3
|
||||
|
||||
当前驱动支持以下厂家/型号的 flash 的 32 位地址范围的访问:
|
||||
- 高性能 (HPM) 模式 - 表示 flash 工作频率大于 80MHz 。
|
||||
|
||||
1. W25Q256
|
||||
2. GD25Q256
|
||||
- flash 的私有ID (unique ID) - 表示 flash 支持它自己的 64-bits 独一无二的 ID 。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
- 暂停与恢复 - 表示 flash 可以在读/写的过程中接受暂停/恢复的命令。{IDF_TARGET_NAME} 可以在 flash 正在写/擦除的过程中保持 cache 开启,并能随机读取 flash 中的内容。
|
||||
|
||||
如果您想使用这些功能,则需保证 {IDF_TARGET_NAME} 支持这些功能,且产品里所使用的 flash 芯片也要支持这些功能。请参阅 :doc:`spi_flash_optional_feature`,查看更多信息。
|
||||
|
||||
如果有需要,也可以自定义 flash 芯片驱动,参见 :doc:`spi_flash_override_driver` 。
|
||||
|
||||
|
@ -9,7 +9,7 @@ SPI1 Flash 并发约束
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
在 {IDF_TARGET_NAME} 上,默认启用的配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 flash / PSRAM 的 cache 访问和 SPI1 的操作存并发地执行。更多详情,参见 :ref:`auto_suspend` 。
|
||||
在 {IDF_TARGET_NAME} 上,默认启用的配置选项 :ref:`CONFIG_SPI_FLASH_AUTO_SUSPEND` 允许 flash / PSRAM 的 cache 访问和 SPI1 的操作存并发地执行。更多详情,参见 :ref:`auto-suspend` 。
|
||||
|
||||
然而当该选项被禁用时,读取/写入/擦除 flash 时, cache 必须被禁用。使用驱动访问 SPI1 的相关约束参见 :ref:`impact_disabled_cache` 。这些约束会带来更多的 IRAM / DRAM 消耗。
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
.. include:: ../../../en/api-reference/storage/spi_flash_optional_feature.rst
|
Reference in New Issue
Block a user