spi_flash: Support flash wrap (burst read), flash driver side

pull/10747/head
Cao Sen Miao 2023-02-10 14:51:11 +08:00
rodzic 254efe402e
commit 0d37436f36
34 zmienionych plików z 343 dodań i 581 usunięć

Wyświetl plik

@ -25,16 +25,6 @@ extern "C" {
*/
uint32_t bootloader_read_flash_id(void);
#if SOC_CACHE_SUPPORT_WRAP
/**
* @brief Set the burst mode setting command for specified wrap mode.
*
* @param mode The specified warp mode.
* @return always ESP_OK
*/
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
#endif
/**
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
*

Wyświetl plik

@ -49,7 +49,6 @@ extern "C" {
#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 */
#define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */
#define CMD_RESETEN 0x66
#define CMD_RESET 0x99

Wyświetl plik

@ -606,38 +606,6 @@ void bootloader_spi_flash_reset(void)
bootloader_execute_flash_command(CMD_RESET, 0, 0, 0);
}
#if SOC_CACHE_SUPPORT_WRAP
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = CMD_WRAP;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif //SOC_CACHE_SUPPORT_WRAP
/*******************************************************************************
* XMC startup flow
******************************************************************************/

Wyświetl plik

@ -17,6 +17,7 @@
#include "flash_qio_mode.h"
#include "soc/efuse_periph.h"
#include "soc/io_mux_reg.h"
#include "esp_private/spi_flash_os.h"
static const char *TAG = "qio_mode";
@ -96,7 +97,8 @@ void bootloader_enable_qio_mode(void)
bootloader_flash_qe_support_list[i].write_status_fn,
bootloader_flash_qe_support_list[i].status_qio_bit);
#if SOC_CACHE_SUPPORT_WRAP
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
spi_flash_wrap_probe();
spi_flash_wrap_disable();
#endif
}

Wyświetl plik

@ -443,6 +443,10 @@ config SOC_SPI_MEM_SUPPORT_CHECK_SUS
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_60M_SUPPORTED
bool
default y

Wyświetl plik

@ -222,6 +222,7 @@
#define SOC_SPI_MEM_SUPPORT_IDLE_INTR (1)
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_SRC_FREQ_60M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_30M_SUPPORTED 1

Wyświetl plik

@ -659,6 +659,10 @@ config SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED
bool
default y

Wyświetl plik

@ -305,6 +305,7 @@
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1

Wyświetl plik

@ -795,6 +795,10 @@ config SOC_SPI_MEM_SUPPORT_CHECK_SUS
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED
bool
default y

Wyświetl plik

@ -340,6 +340,7 @@
#define SOC_SPI_MEM_SUPPORT_IDLE_INTR (1)
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1

Wyświetl plik

@ -691,6 +691,10 @@ config SOC_SPI_MEM_SUPPORT_CHECK_SUS
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED
bool
default y

Wyświetl plik

@ -338,6 +338,7 @@
#define SOC_SPI_MEM_SUPPORT_IDLE_INTR (1)
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED 1

Wyświetl plik

@ -627,6 +627,10 @@ config SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED
bool
default y

Wyświetl plik

@ -310,6 +310,7 @@
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_MEMSPI_SRC_FREQ_48M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_24M_SUPPORTED 1

Wyświetl plik

@ -931,6 +931,10 @@ config SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_PM_SUPPORT_EXT_WAKEUP
bool
default y

Wyświetl plik

@ -407,6 +407,7 @@
#define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
/*-------------------------- Power Management CAPS ---------------------------*/
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)

Wyświetl plik

@ -1143,6 +1143,10 @@ config SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE
bool
default y
config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_COEX_HW_PTI
bool
default y

Wyświetl plik

@ -465,6 +465,7 @@
#define SOC_SPI_MEM_SUPPORT_OPI_MODE (1)
#define SOC_SPI_MEM_SUPPORT_TIME_TUNING (1)
#define SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
#define SOC_COEX_HW_PTI (1)

Wyświetl plik

@ -4,7 +4,7 @@ if(${target} STREQUAL "linux")
endif()
if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
set(cache_srcs "")
set(srcs "spi_flash_wrap.c")
set(priv_requires bootloader_support soc)
else()
set(srcs "flash_brownout_hook.c")
@ -35,7 +35,7 @@ else()
"cache_utils.c"
"flash_mmap.c"
"flash_ops.c"
"${target}/flash_ops_${target}.c"
"spi_flash_wrap.c"
)
list(APPEND cache_srcs

Wyświetl plik

@ -55,6 +55,8 @@
#include "esp_memory_utils.h"
#include "esp_intr_alloc.h"
#include "spi_flash_mmap.h"
#include "spi_flash_override.h"
#include "esp_private/spi_flash_os.h"
#include "esp_log.h"
#include "esp_cpu.h"
@ -555,16 +557,16 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
if (icache_wrap_enable) {
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
icache_wrap_size = 16;
icache_wrap_size = FLASH_WRAP_SIZE_16B;
#else
icache_wrap_size = 32;
icache_wrap_size = FLASH_WRAP_SIZE_32B;
#endif
}
if (dcache_wrap_enable) {
#if CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B
dcache_wrap_size = 16;
dcache_wrap_size = FLASH_WRAP_SIZE_16B;
#else
dcache_wrap_size = 32;
dcache_wrap_size = FLASH_WRAP_SIZE_32B;
#endif
}
@ -647,7 +649,6 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
#ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
flash_support_wrap = true;
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
if (!spi_flash_support_wrap_size(flash_wrap_size)) {
flash_support_wrap = false;
ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
@ -669,10 +670,9 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
return ESP_FAIL;
}
extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
if (flash_support_wrap && flash_wrap_size > 0) {
ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
spi_flash_enable_wrap(flash_wrap_size);
spI_flash_wrap_enable(flash_wrap_size);
esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
}
#if (CONFIG_IDF_TARGET_ESP32S2 && CONFIG_SPIRAM)
@ -801,20 +801,20 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
if (icache_wrap_enable) {
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
icache_wrap_size = 16;
icache_wrap_size = FLASH_WRAP_SIZE_16B;
#elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
icache_wrap_size = 32;
icache_wrap_size = FLASH_WRAP_SIZE_32B;
#else
icache_wrap_size = 64;
icache_wrap_size = FLASH_WRAP_SIZE_64B;
#endif
}
if (dcache_wrap_enable) {
#if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
dcache_wrap_size = 16;
dcache_wrap_size = FLASH_WRAP_SIZE_16B;
#elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
dcache_wrap_size = 32;
dcache_wrap_size = FLASH_WRAP_SIZE_32B;
#else
dcache_wrap_size = 64;
dcache_wrap_size = FLASH_WRAP_SIZE_64B;
#endif
}
@ -895,7 +895,6 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
#ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
flash_support_wrap = true;
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
if (!spi_flash_support_wrap_size(flash_wrap_size)) {
flash_support_wrap = false;
ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
@ -918,10 +917,9 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
return ESP_FAIL;
}
extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
if (flash_support_wrap && flash_wrap_size > 0) {
ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
spi_flash_enable_wrap(flash_wrap_size);
spI_flash_wrap_enable(flash_wrap_size);
esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
}
#if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
@ -963,7 +961,6 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
#ifdef CONFIG_ESPTOOLPY_FLASHMODE_QIO
flash_support_wrap = true;
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
if (!spi_flash_support_wrap_size(flash_wrap_size)) {
flash_support_wrap = false;
ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
@ -972,10 +969,9 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
#endif // CONFIG_ESPTOOLPY_FLASHMODE_QIO
extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
if (flash_support_wrap && flash_wrap_size > 0) {
ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
spi_flash_enable_wrap(flash_wrap_size);
spI_flash_wrap_enable(flash_wrap_size);
esp_enable_cache_flash_wrap((flash_wrap_size > 0));
}
return ESP_OK;

Wyświetl plik

@ -1,5 +0,0 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

Wyświetl plik

@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32c2/rom/cache.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
#define FLASH_WRAP_CMD 0x77
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch (wrap_size) {
case 8:
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32c3/rom/cache.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
#define FLASH_WRAP_CMD 0x77
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch (wrap_size) {
case 8:
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/soc_memory_layout.h"
#include "esp32c6/rom/cache.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
#define FLASH_WRAP_CMD 0x77
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
// IDF-6198 TODO: support wrap on esp32-c6
CLEAR_PERI_REG_MASK(SPI_MEM_CTRL2_REG(0), SPI_MEM_SPLIT_TRANS_EN_M);
switch (wrap_size) {
case 8:
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// TODO: IDF-6020

Wyświetl plik

@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32h4/rom/cache.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
#define FLASH_WRAP_CMD 0x77
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch (wrap_size) {
case 8:
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -1,64 +0,0 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s2/rom/cache.h"
#include "bootloader_flash.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_rom_spiflash.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
return bootloader_flash_wrap_set(mode);
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch(wrap_size) {
case 8:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)){
return ESP_FAIL;
}
switch(wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -1,64 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/param.h>
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s3/rom/cache.h"
#include "bootloader_flash.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "esp_rom_spiflash.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
return bootloader_flash_wrap_set(mode);
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch (wrap_size) {
case 8:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

Wyświetl plik

@ -135,23 +135,38 @@ const spi_flash_hpm_dummy_conf_t *spi_flash_hpm_get_dummy(void);
*/
bool spi_flash_hpm_dummy_adjust(void);
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
#if SOC_SPI_MEM_SUPPORT_WRAP
/**
* @brief set wrap mode of flash
* @brief set wrap size of flash
*
* @param mode: wrap mode support disable, 16 32, 64 byte
* @param wrap_size: wrap mode support disable, 16 32, 64 byte
*
* @return esp_err_t : ESP_OK for successful.
*
*/
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode);
esp_err_t spI_flash_wrap_enable(spi_flash_wrap_size_t wrap_size);
/**
* @brief Probe flash wrap method
*
* @return esp_err_t: ESP_OK for success
*/
esp_err_t spi_flash_wrap_probe(void);
/**
* @brief disable cache wrap
*/
esp_err_t spi_flash_wrap_disable(void);
/**
* @brief Check whether flash and esp chip supports wrap mode.
*
* @param wrap_size wrap size.
* @return true: wrap support, otherwise, false.
*/
bool spi_flash_support_wrap_size(uint32_t wrap_size);
#endif //SOC_SPI_MEM_SUPPORT_WRAP
/**
* @brief SPI flash critical section enter function.

Wyświetl plik

@ -47,6 +47,8 @@
#define CMD_SUSPEND 0x75
#define CMD_RESUME 0x7A
#define CMD_HPMEN 0xA3 /* Enable High Performance mode on flash */
#define CMD_WRAP 0x77
#define CMD_BURST_RD 0xC0 /* wrap(0x77) and burst read are functionally same. But commands and formats is different */
#define CMD_RST_EN 0x66
#define CMD_RST_DEV 0x99

Wyświetl plik

@ -50,6 +50,49 @@ typedef struct __attribute__((packed))
spi_flash_get_chip_dummy_fn_t flash_get_dummy;
} spi_flash_hpm_info_t;
/**
* @brief Enum for user to select valid wrap size.
*/
typedef enum {
FLASH_WRAP_SIZE_8B = 8,
FLASH_WRAP_SIZE_16B = 16,
FLASH_WRAP_SIZE_32B = 32,
FLASH_WRAP_SIZE_64B = 64,
} spi_flash_wrap_size_t;
/**
* @brief Probe flash wrap method
*
* @param flash_id Flash chip ID
*
* @return ESP_OK: If succeed
*/
typedef esp_err_t (*spi_flash_wrap_probe_fn_t)(uint32_t flash_id);
/**
* @brief Set flash wrap
*
* @param wrap_size: wrap_size
*
* @return ESP_OK: If succeed
*/
typedef esp_err_t (*spi_flash_wrap_set_fn_t)(spi_flash_wrap_size_t wrap_size);
/**
* @brief Clear flash wrap.
*
* @return ESP_OK: If succeed
*/
typedef esp_err_t (*spi_flash_wrap_clr_fn_t)(void);
typedef struct __attribute__((packed))
{
const char *method;
spi_flash_wrap_probe_fn_t probe;
spi_flash_wrap_set_fn_t chip_wrap_set;
spi_flash_wrap_clr_fn_t chip_wrap_clr;
} spi_flash_wrap_info_t;
/**
* Array of known flash chips and method to enable flash high performance mode.
*

Wyświetl plik

@ -11,6 +11,7 @@ entries:
spi_flash_chip_th (noflash)
memspi_host_driver (noflash)
flash_brownout_hook (noflash)
spi_flash_wrap (noflash)
if IDF_TARGET_ESP32S3 = y:
spi_flash_chip_mxic_opi (noflash)

Wyświetl plik

@ -0,0 +1,175 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.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"
#include "esp_private/spi_flash_os.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 wrap feature (also called burst read on some flash chips)
*
* Different flash chips enter wrap (burst read) mode in different strategies.
* 1. Command 0xC0 + 8 Bytes.
* 2. Command 0x77 + 24 dummy + 8 Bytes.
**********************************************************************************/
#if SOC_SPI_MEM_SUPPORT_WRAP
const static char *FLASH_WRAP_TAG = "flash wrap";
// 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);
esp_err_t spi_flash_wrap_probe_c0(uint32_t flash_id)
{
esp_err_t ret = ESP_OK;
switch (flash_id) {
/* The flash listed here should enter the wrap with command 0xC0 */
case 0xC22018:
break;
default:
ret = ESP_ERR_NOT_FOUND;
break;
}
return ret;
}
/**
* @brief Burst read with command 0xC0 + 8 Bytes
*
* |------------|-----------------------------|
* | data | wrap depth |
* | 00h | 8 |
* | 01h | 16 |
* | 02h | 32 |
* | 03h | 64 |
* |------------|-----------------------------|
*/
esp_err_t spi_flash_wrap_enable_c0(spi_flash_wrap_size_t wrap_size)
{
uint8_t wrap_code = (uint8_t) (__builtin_ctz(wrap_size) - 3);
bootloader_flash_execute_command_common(CMD_BURST_RD, 0, 0, 0, 8, wrap_code, 0);
return ESP_OK;
}
/**
* @brief Burst read with command 0x77 + 24 Dummy + 8 Bytes
*
* |-------------------|-----------------------------|
* | data(W6,W5) | wrap depth |
* | 00h | 8 |
* | 01h | 16 |
* | 02h | 32 |
* | 03h | 64 |
* |-------------------|-----------------------------|
*/
esp_err_t spi_flash_wrap_enable_77(spi_flash_wrap_size_t wrap_size)
{
uint8_t wrap_code = (uint8_t) (((__builtin_ctz(wrap_size) - 3) * 2) << 4);
// According to the special format, we need enable QIO_FWRITE for command 77h and clear it after this command is done.
REG_SET_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
bootloader_flash_execute_command_common(CMD_WRAP, 0, 0, 6, 8, wrap_code, 0);
REG_CLR_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
return ESP_OK;
}
/**
* @brief Burst read is cleared by setting 0x1xh,
* so we set 0x10 to disable this feature.
*/
esp_err_t spi_flash_wrap_clear_c0(void)
{
bootloader_flash_execute_command_common(CMD_BURST_RD, 0, 0, 0, 8, 0x10, 0);
return ESP_OK;
}
/**
* @brief Burst read is cleared by setting W4 bit 1,
* so we set 0x10 to disable this feature.
*/
esp_err_t spi_flash_wrap_clear_77(void)
{
// According to the special format, we need enable QIO_FWRITE for command 77h and clear it after this command is done.
REG_SET_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
bootloader_flash_execute_command_common(CMD_WRAP, 0, 0, 6, 8, 0x10, 0);
REG_CLR_BIT(SPI_MEM_USER_REG(1), SPI_MEM_FWRITE_QIO);
return ESP_OK;
}
const spi_flash_wrap_info_t __attribute__((weak)) spi_flash_wrap_list[] = {
/* method probe chip wrap set chip wrap clear */
{"C0H+8B", spi_flash_wrap_probe_c0, spi_flash_wrap_enable_c0, spi_flash_wrap_clear_c0},
{"default", NULL, spi_flash_wrap_enable_77, spi_flash_wrap_clear_77},
};
static const spi_flash_wrap_info_t *chip_wrap = NULL;
esp_err_t spi_flash_wrap_probe(void)
{
uint32_t flash_chip_id = g_rom_flashchip.device_id;
const spi_flash_wrap_info_t *chip = spi_flash_wrap_list;
esp_err_t ret = ESP_OK;
while (chip->probe) {
ret = chip->probe(flash_chip_id);
if (ret == ESP_OK) {
break;
}
chip++;
}
chip_wrap = chip;
return ret;
}
esp_err_t spI_flash_wrap_enable(spi_flash_wrap_size_t wrap_size)
{
// Calculate pre_code. pre_code equals log(2)(wrap_size) - 3
// So the wrap_size:pre_code is 8:0, 16:1, 32:2, 64:3.
return chip_wrap->chip_wrap_set(wrap_size);
}
esp_err_t spi_flash_wrap_disable(void)
{
return chip_wrap->chip_wrap_clr();
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
// Only QIO mode supports wrap.
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO)) {
ESP_EARLY_LOGE(FLASH_WRAP_TAG, "flash wrap is only supported in QIO mode");
abort();
}
// Only following size can be wrapped.
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}
#endif // SOC_SPI_MEM_SUPPORT_WRAP

Wyświetl plik

@ -30,6 +30,7 @@
#include "esp_timer.h"
#include "test_esp_flash_def.h"
#include "spi_flash_mmap.h"
#include "esp_private/spi_flash_os.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/cache.h"
@ -533,6 +534,46 @@ static void test_write_protection(const esp_partition_t* part)
TEST_CASE_FLASH("Test esp_flash can enable/disable write protetion", test_write_protection);
TEST_CASE_MULTI_FLASH("Test esp_flash can enable/disable write protetion", test_write_protection);
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO && SOC_SPI_MEM_SUPPORT_WRAP
// Only under QIO mode and mspi support wrap this feature makes sense.
static uint8_t wrap_buf[32];
void test_flash_wrap(const esp_partition_t* part)
{
esp_flash_t* chip = part->flash_chip;
uint32_t offs = erase_test_region(part, 1);
const int test_seed = 778;
srand(test_seed);
for (int i = 0 ; i < sizeof(wrap_buf); i++) {
wrap_buf[i] = rand();
}
printf("Write %p...\n", (void *)offs);
TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, wrap_buf, offs + 3, sizeof(wrap_buf)) );
bzero(wrap_buf, sizeof(wrap_buf));
printf("Read back...\n");
spi_flash_wrap_probe();
spI_flash_wrap_enable(FLASH_WRAP_SIZE_32B);
esp_flash_read(chip, wrap_buf, offs + 3, sizeof(wrap_buf));
spi_flash_wrap_disable();
printf("Buffer starts 0x%02x 0x%02x 0x%02x 0x%02x\n", wrap_buf[0], wrap_buf[1], wrap_buf[2], wrap_buf[3]);
srand(test_seed);
for (int i = 0; i < sizeof(wrap_buf) - 3; i++) {
uint8_t data = rand();
TEST_ASSERT_EQUAL_HEX8(data, wrap_buf[i]);
}
for (int i = sizeof(wrap_buf) - 3; i < sizeof(wrap_buf); i++) {
TEST_ASSERT_EQUAL_HEX8(0xFF, wrap_buf[i]);
}
}
TEST_CASE_FLASH("SPI flash wrap test", test_flash_wrap);
#endif
static const uint8_t large_const_buffer[16400] = {
203, // first byte
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,