mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-07 06:34:34 +02:00
Merge branch 'feature/support_hpm_on_flash' into 'master'
spi_flash: Building a framework to enable HPM when flash works under high speed mode, take GD as an example. Closes IDF-4537 See merge request espressif/esp-idf!16660
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "sdkconfig.h"
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
@@ -40,6 +41,13 @@ unsigned bootloader_read_status_8b_rdsr(void);
|
||||
*/
|
||||
unsigned bootloader_read_status_8b_rdsr2(void);
|
||||
|
||||
/**
|
||||
* @brief Read 8 bit status (third byte) using RDSR3 command
|
||||
*
|
||||
* @return Value of SR3
|
||||
*/
|
||||
unsigned bootloader_read_status_8b_rdsr3(void);
|
||||
|
||||
/**
|
||||
* @brief Read 16 bit status using RDSR & RDSR2 (low and high bytes)
|
||||
*
|
||||
@@ -57,6 +65,11 @@ void bootloader_write_status_8b_wrsr(unsigned new_status);
|
||||
*/
|
||||
void bootloader_write_status_8b_wrsr2(unsigned new_status);
|
||||
|
||||
/**
|
||||
* @brief Write 8 bit status (third byte) using WRSR3.
|
||||
*/
|
||||
void bootloader_write_status_8b_wrsr3(unsigned new_status);
|
||||
|
||||
/**
|
||||
* @brief Write 16 bit status using WRSR, (both write SR1 and SR2)
|
||||
*/
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -28,10 +28,12 @@ extern "C" {
|
||||
#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_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 */
|
||||
|
@@ -509,7 +509,7 @@ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -539,14 +539,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
|
||||
|
@@ -165,6 +165,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);
|
||||
@@ -180,6 +185,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);
|
||||
|
@@ -34,7 +34,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
|
||||
|
@@ -170,9 +170,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)
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_flash.h"
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#include "spi_flash_override.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -100,6 +101,21 @@ 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 bootlaoder_flash_dummy_conf_t.
|
||||
*/
|
||||
const spi_flash_hpm_dummy_conf_t *spi_flash_get_dummy(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
|
||||
|
60
components/spi_flash/include/spi_flash_override.h
Normal file
60
components/spi_flash/include/spi_flash_override.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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_NEEDED, // Means that in the certain condition, flash needs to enter the high performance mode.
|
||||
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 *manufacturer; /* Flash vendor */
|
||||
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
|
@@ -13,9 +13,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)
|
||||
|
266
components/spi_flash/spi_flash_hpm_enable.c
Normal file
266
components/spi_flash/spi_flash_hpm_enable.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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 "esp_rom_spiflash.h"
|
||||
#include "spi_flash_override.h"
|
||||
|
||||
// TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
|
||||
#include "bootloader_flash_override.h"
|
||||
#include "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);
|
||||
|
||||
//-----------------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;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0xC84016:
|
||||
case 0xC84017:
|
||||
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;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0xC84016:
|
||||
case 0xC84017:
|
||||
if (freq_mhz >= 80) {
|
||||
chip_cap = SPI_FLASH_HPM_NEEDED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
break;
|
||||
}
|
||||
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_EARLY_LOGW(HPM_TAG, "Enter HPM by reconfiguring dummy has not been fully tested");
|
||||
esp_err_t ret = ESP_OK;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM by adjusting dummy cycles */
|
||||
case 0x204017:
|
||||
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;
|
||||
switch (flash_id) {
|
||||
/* The flash listed here should enter the HPM with command 0xA3 */
|
||||
case 0x204017:
|
||||
if (freq_mhz >= 104) {
|
||||
chip_cap = SPI_FLASH_HPM_NEEDED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
chip_cap = SPI_FLASH_HPM_UNNEEDED;
|
||||
break;
|
||||
}
|
||||
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_WREN, 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;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------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 */
|
||||
{ "GD", 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 },
|
||||
{ "XMC", 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},
|
||||
// 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;
|
||||
|
||||
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;
|
||||
// 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) {
|
||||
ESP_EARLY_LOGE(HPM_TAG, "Flash high performance mode hasn't been supported");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature) == SPI_FLASH_HPM_NEEDED) {
|
||||
ESP_EARLY_LOGI(HPM_TAG, "Enabling high speed mode for chip %s", chip_hpm->manufacturer);
|
||||
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;
|
||||
}
|
||||
} else if (chip_hpm->chip_hpm_requirement_check(flash_chip_id, flash_freq, voltage, temperature) == 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;
|
||||
}
|
@@ -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
|
||||
^^^^^^^^^^^
|
||||
|
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
|
@@ -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
|
||||
|
||||
下列芯片支持八线模式 (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` 。
|
||||
|
||||
|
@@ -0,0 +1 @@
|
||||
.. include:: ../../../en/api-reference/storage/spi_flash_optional_feature.rst
|
@@ -1688,7 +1688,6 @@ components/spi_flash/include/esp_flash_spi_init.h
|
||||
components/spi_flash/include/esp_spi_flash.h
|
||||
components/spi_flash/include/esp_spi_flash_counters.h
|
||||
components/spi_flash/include/memspi_host_driver.h
|
||||
components/spi_flash/include/spi_flash/spi_flash_defs.h
|
||||
components/spi_flash/include/spi_flash_chip_boya.h
|
||||
components/spi_flash/include/spi_flash_chip_driver.h
|
||||
components/spi_flash/include/spi_flash_chip_gd.h
|
||||
|
Reference in New Issue
Block a user