mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
spi_flash: Add ESP32-C3 support
Based on internal commit 3ef01301fff
This commit is contained in:
parent
c2364e133d
commit
d4c9a45675
@ -78,6 +78,26 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
/*
|
||||
* In S3 ROM, extra bits than 24-bit are used to indicate requirements of M7-M0:
|
||||
* - 24: normal transactions
|
||||
* - 28: 24bit DIO + conf bits (M7-M0 excluded from dummy_bitlen)
|
||||
* - 32: 24bit QIO + conf bits (M7-M0 excluded from dummy_bitlen)
|
||||
|
||||
* Detect requirements for the conf bits by the address len, and modify the length to normal
|
||||
* case (addr_bitlen = 24, dummy_bitlen includes M7-M0) as other chip versions use.
|
||||
*/
|
||||
int m70_bits = addr_bitlen - 24;
|
||||
if (m70_bits) {
|
||||
assert(io_mode == SPI_FLASH_DIO || io_mode == SPI_FLASH_QIO);
|
||||
conf_required = true;
|
||||
addr_bitlen -= m70_bits;
|
||||
int line_width = (io_mode == SPI_FLASH_DIO? 2: 4);
|
||||
dummy_cyclelen_base += m70_bits / line_width;
|
||||
}
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
#if SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT
|
||||
// The CONTROL_DUMMY_OUTPUT feature is used to control M7-M0 bits.
|
||||
spi_flash_ll_set_dummy_out(dev, (conf_required? 1: 0), 1);
|
||||
@ -110,11 +130,18 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr
|
||||
{
|
||||
spi_dev_t *dev = get_spi_dev(host);
|
||||
esp_flash_io_mode_t io_mode = ((spi_flash_hal_context_t*)host)->base_io_mode;
|
||||
uint16_t command = trans->command;
|
||||
uint8_t dummy_bitlen = trans->dummy_bitlen;
|
||||
|
||||
if ((trans->flags & SPI_FLASH_TRANS_FLAG_IGNORE_BASEIO) != 0) {
|
||||
io_mode = 0;
|
||||
uint16_t command;
|
||||
uint8_t dummy_bitlen;
|
||||
if (trans->reserved != 0) {
|
||||
// Back-compatible with caller functions of ESP32-S3 ROM
|
||||
command = (uint8_t)trans->reserved;
|
||||
dummy_bitlen = 0;
|
||||
} else {
|
||||
command = trans->command;
|
||||
dummy_bitlen = trans->dummy_bitlen;
|
||||
if ((trans->flags & SPI_FLASH_TRANS_FLAG_IGNORE_BASEIO) != 0) {
|
||||
io_mode = ((spi_flash_hal_context_t*)host)->base_io_mode;
|
||||
}
|
||||
}
|
||||
|
||||
host->driver->configure_host_io_mode(host, command, trans->address_bitlen, dummy_bitlen, io_mode);
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_NEW_ROM_API
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
@ -95,4 +95,4 @@ bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host)
|
||||
return idle;
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPI_FLASH_NEW_ROM_API
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
@ -62,18 +62,7 @@ if(${spi_flash_mock})
|
||||
|
||||
else()
|
||||
if(BOOTLOADER_BUILD)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
|
||||
# need other parts of this component
|
||||
set(srcs "esp32/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S2)
|
||||
set(srcs "esp32s2/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
set(srcs "esp32s3/spi_flash_rom_patch.c")
|
||||
else()
|
||||
# but on other platforms no source files are needed for bootloader
|
||||
set(srcs)
|
||||
endif()
|
||||
set(srcs "${target}/spi_flash_rom_patch.c")
|
||||
set(cache_srcs "")
|
||||
set(priv_requires bootloader_support soc)
|
||||
else()
|
||||
@ -81,21 +70,12 @@ else()
|
||||
"cache_utils.c"
|
||||
"flash_mmap.c"
|
||||
"flash_ops.c"
|
||||
"${IDF_TARGET}/flash_ops_${IDF_TARGET}.c"
|
||||
"${target}/flash_ops_${target}.c"
|
||||
)
|
||||
set(srcs
|
||||
"partition.c")
|
||||
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
list(APPEND srcs
|
||||
"esp32/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S2)
|
||||
list(APPEND srcs
|
||||
"esp32s2/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
list(APPEND srcs
|
||||
"esp32s3/spi_flash_rom_patch.c")
|
||||
endif()
|
||||
"partition.c"
|
||||
"${target}/spi_flash_rom_patch.c"
|
||||
)
|
||||
|
||||
# New implementation after IDF v4.0
|
||||
list(APPEND srcs
|
||||
|
@ -53,6 +53,19 @@ menu "SPI Flash driver"
|
||||
to flash on ESP32-D2WD; (2) main SPI flash is connected to non-default pins; (3) main
|
||||
SPI flash chip is manufactured by ISSI.
|
||||
|
||||
config SPI_FLASH_ROM_IMPL
|
||||
bool "Use esp_flash implementation in ROM"
|
||||
depends on IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3
|
||||
default n
|
||||
help
|
||||
Enable this flag to use new SPI flash driver functions from ROM instead of ESP-IDF.
|
||||
|
||||
If keeping this as "n" in your project, you will have less free IRAM.
|
||||
But you can use all of our flash features.
|
||||
|
||||
If making this as "y" in your project, you will increase free IRAM.
|
||||
But you may miss out on some flash features and support for new flash chips.
|
||||
|
||||
choice SPI_FLASH_DANGEROUS_WRITE
|
||||
bool "Writing to dangerous flash regions"
|
||||
default SPI_FLASH_DANGEROUS_WRITE_ABORTS
|
||||
|
@ -875,6 +875,50 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache)
|
||||
{
|
||||
uint32_t i_autoload;
|
||||
if (icache) {
|
||||
i_autoload = Cache_Suspend_ICache();
|
||||
}
|
||||
REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
|
||||
if (icache) {
|
||||
Cache_Resume_ICache(i_autoload);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
|
||||
{
|
||||
int flash_wrap_size = 0;
|
||||
bool flash_support_wrap = false;
|
||||
|
||||
if (icache_wrap_enable) {
|
||||
flash_wrap_size = 32;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_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);
|
||||
}
|
||||
#else
|
||||
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
|
||||
#endif // CONFIG_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);
|
||||
esp_enable_cache_flash_wrap((flash_wrap_size > 0));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
145
components/spi_flash/esp32c3/flash_ops_esp32c3.c
Normal file
145
components/spi_flash/esp32c3/flash_ops_esp32c3.c
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#include "esp32c3/rom/cache.h"
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "spiflash_c3";
|
||||
|
||||
#define SPICACHE SPIMEM0
|
||||
#define SPIFLASH SPIMEM1
|
||||
|
||||
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
|
||||
{
|
||||
const spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
|
||||
esp_rom_spiflash_result_t rc;
|
||||
|
||||
assert((dest_addr % 16) == 0);
|
||||
assert((size % 16) == 0);
|
||||
|
||||
if (!esp_ptr_internal(src)) {
|
||||
uint8_t block[128]; // Need to buffer in RAM as we write
|
||||
while (size > 0) {
|
||||
size_t next_block = MIN(size, sizeof(block));
|
||||
memcpy(block, src, next_block);
|
||||
|
||||
esp_rom_spiflash_result_t r = spi_flash_write_encrypted_chip(dest_addr, block, next_block);
|
||||
if (r != ESP_ROM_SPIFLASH_RESULT_OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
size -= next_block;
|
||||
dest_addr += next_block;
|
||||
src = ((uint8_t *)src) + next_block;
|
||||
}
|
||||
bzero(block, sizeof(block));
|
||||
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
} else { // Already in internal memory
|
||||
ESP_LOGV(TAG, "calling esp_rom_spiflash_write_encrypted addr 0x%x src %p size 0x%x", dest_addr, src, size);
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
/* The ROM function SPI_Encrypt_Write assumes ADDR_BITLEN is already set but new
|
||||
implementation doesn't automatically set this to a usable value */
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
#endif
|
||||
|
||||
if (ops && ops->start) {
|
||||
ops->start();
|
||||
}
|
||||
rc = esp_rom_spiflash_write_encrypted(dest_addr, (uint32_t *)src, size);
|
||||
if (ops && ops->end) {
|
||||
ops->end();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
26
components/spi_flash/esp32c3/spi_flash_rom_patch.c
Normal file
26
components/spi_flash/esp32c3/spi_flash_rom_patch.c
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2015-2020 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.
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
#define SPI_IDX 1
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
|
||||
{
|
||||
REG_WRITE(SPI_MEM_CMD_REG(SPI_IDX), SPI_MEM_FLASH_WRDI);
|
||||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
@ -23,8 +23,6 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_flash_internal.h"
|
||||
|
||||
#include "spi_flash_chip_generic.h" //for spi_flash_chip_generic_yield()
|
||||
|
||||
static const char TAG[] = "spi_flash";
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE
|
||||
@ -70,10 +68,12 @@ _Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the i
|
||||
|
||||
esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
static esp_err_t spiflash_start_default(esp_flash_t *chip);
|
||||
static esp_err_t spiflash_end_default(esp_flash_t *chip, esp_err_t err);
|
||||
static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip);
|
||||
static esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
typedef struct {
|
||||
esp_err_t (*start)(esp_flash_t *chip);
|
||||
@ -82,6 +82,7 @@ typedef struct {
|
||||
esp_err_t (*flash_end_flush_cache)(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
} rom_spiflash_api_func_t;
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
// These functions can be placed in the ROM. For now we use the code in IDF.
|
||||
DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = {
|
||||
.start = spiflash_start_default,
|
||||
@ -91,12 +92,17 @@ DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = {
|
||||
};
|
||||
|
||||
DRAM_ATTR rom_spiflash_api_func_t *rom_spiflash_api_funcs = &default_spiflash_rom_api;
|
||||
#else
|
||||
extern rom_spiflash_api_func_t *esp_flash_api_funcs;
|
||||
#define rom_spiflash_api_funcs esp_flash_api_funcs
|
||||
#endif // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
/* Static function to notify OS of a new SPI flash operation.
|
||||
|
||||
If returns an error result, caller must abort. If returns ESP_OK, caller must
|
||||
call rom_spiflash_api_funcs->end() before returning.
|
||||
*/
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
static esp_err_t IRAM_ATTR spiflash_start_default(esp_flash_t *chip)
|
||||
{
|
||||
if (chip->os_func != NULL && chip->os_func->start != NULL) {
|
||||
@ -155,10 +161,7 @@ static IRAM_ATTR esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t er
|
||||
}
|
||||
return rom_spiflash_api_funcs->end(chip, err);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */
|
||||
inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len);
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
/* Top-level API functions, calling into chip_drv functions via chip->drv */
|
||||
|
||||
@ -270,6 +273,7 @@ esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* out_id)
|
||||
return read_id_core(chip, out_id, true);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
esp_err_t esp_flash_read_id(esp_flash_t* chip, uint32_t* out_id)
|
||||
{
|
||||
esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
|
||||
@ -279,6 +283,7 @@ esp_err_t esp_flash_read_id(esp_flash_t* chip, uint32_t* out_id)
|
||||
|
||||
return read_id_core(chip, out_id, false);
|
||||
}
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
|
||||
{
|
||||
@ -316,6 +321,8 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
/* Convenience macro for beginning of all API functions.
|
||||
* Check the return value of `rom_spiflash_api_funcs->chip_check` is correct,
|
||||
* and the chip supports the operation in question.
|
||||
@ -327,6 +334,9 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */
|
||||
inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len);
|
||||
|
||||
esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size)
|
||||
{
|
||||
esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
|
||||
@ -358,9 +368,11 @@ esp_err_t IRAM_ATTR esp_flash_erase_chip(esp_flash_t *chip)
|
||||
CHECK_WRITE_ADDRESS(chip, 0, chip->size);
|
||||
|
||||
//check before the operation, in case this is called too close to the last operation
|
||||
err = spi_flash_chip_generic_yield(chip, false);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
if (chip->chip_drv->yield) {
|
||||
err = chip->chip_drv->yield(chip, 0);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = rom_spiflash_api_funcs->start(chip);
|
||||
@ -432,9 +444,11 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
||||
bool bus_acquired = false;
|
||||
while (1) {
|
||||
//check before the operation, in case this is called too close to the last operation
|
||||
err = spi_flash_chip_generic_yield(chip, false);
|
||||
if (err != ESP_OK) {
|
||||
break;
|
||||
if (chip->chip_drv->yield) {
|
||||
err = chip->chip_drv->yield(chip, 0);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = rom_spiflash_api_funcs->start(chip);
|
||||
@ -707,9 +721,11 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3
|
||||
}
|
||||
|
||||
//check before the operation, in case this is called too close to the last operation
|
||||
err = spi_flash_chip_generic_yield(chip, false);
|
||||
if (err != ESP_OK) {
|
||||
break;
|
||||
if (chip->chip_drv->yield) {
|
||||
err = chip->chip_drv->yield(chip, 0);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = rom_spiflash_api_funcs->start(chip);
|
||||
@ -814,6 +830,7 @@ IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe)
|
||||
err = chip->chip_drv->set_io_mode(chip);
|
||||
return rom_spiflash_api_funcs->end(chip, err);
|
||||
}
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
esp_err_t esp_flash_app_disable_protect(bool disable)
|
||||
|
@ -87,12 +87,18 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
|
||||
.iomux = true, \
|
||||
.input_delay_ns = 0,\
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
|
||||
.host_id = SPI_HOST,\
|
||||
.speed = DEFAULT_FLASH_SPEED, \
|
||||
.cs_num = 0, \
|
||||
.iomux = true, \
|
||||
.input_delay_ns = 0,\
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
esp_flash_t *esp_flash_default_chip = NULL;
|
||||
|
||||
|
||||
static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_flash_spi_device_config_t *config, bool use_iomux, int cs_id)
|
||||
{
|
||||
//Not using spicommon_cs_initialize since we don't want to put the whole
|
||||
@ -111,11 +117,15 @@ static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_f
|
||||
if (use_iomux) {
|
||||
PIN_FUNC_SELECT(iomux_reg, spics_func);
|
||||
} else {
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
GPIO.enable_w1ts.val = (0x1 << cs_io_num);
|
||||
#else
|
||||
if (cs_io_num < 32) {
|
||||
GPIO.enable_w1ts = (0x1 << cs_io_num);
|
||||
} else {
|
||||
GPIO.enable1_w1ts.data = (0x1 << (cs_io_num - 32));
|
||||
}
|
||||
#endif
|
||||
GPIO.pin[cs_io_num].pad_driver = 0;
|
||||
esp_rom_gpio_connect_out_signal(cs_io_num, spics_out, false, false);
|
||||
if (cs_id == 0) {
|
||||
@ -208,10 +218,14 @@ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
/* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */
|
||||
extern const esp_flash_os_functions_t esp_flash_noos_functions;
|
||||
|
||||
/* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
esp_flash_t *esp_flash_default_chip = NULL;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
|
||||
static DRAM_ATTR memspi_host_inst_t esp_flash_default_host;
|
||||
@ -224,6 +238,7 @@ static DRAM_ATTR esp_flash_t default_chip = {
|
||||
|
||||
esp_err_t esp_flash_init_default_chip(void)
|
||||
{
|
||||
const esp_rom_spiflash_chip_t *legacy_chip = &g_rom_flashchip;
|
||||
memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT();
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
@ -243,14 +258,15 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
if (default_chip.size < g_rom_flashchip.chip_size) {
|
||||
ESP_EARLY_LOGE(TAG, "Detected size(%dk) smaller than the size in the binary image header(%dk). Probe failed.", default_chip.size/1024, g_rom_flashchip.chip_size/1024);
|
||||
if (default_chip.size < legacy_chip->chip_size) {
|
||||
ESP_EARLY_LOGE(TAG, "Detected size(%dk) smaller than the size in the binary image header(%dk). Probe failed.", default_chip.size/1024, legacy_chip->chip_size/1024);
|
||||
return ESP_ERR_FLASH_SIZE_NOT_MATCH;
|
||||
} else if (default_chip.size > g_rom_flashchip.chip_size) {
|
||||
ESP_EARLY_LOGW(TAG, "Detected size(%dk) larger than the size in the binary image header(%dk). Using the size in the binary image header.", default_chip.size/1024, g_rom_flashchip.chip_size/1024);
|
||||
default_chip.size = g_rom_flashchip.chip_size;
|
||||
} else if (default_chip.size > legacy_chip->chip_size) {
|
||||
ESP_EARLY_LOGW(TAG, "Detected size(%dk) larger than the size in the binary image header(%dk). Using the size in the binary image header.", default_chip.size/1024, legacy_chip->chip_size/1024);
|
||||
default_chip.size = legacy_chip->chip_size;
|
||||
} else {
|
||||
default_chip.size = legacy_chip->chip_size;
|
||||
}
|
||||
default_chip.size = g_rom_flashchip.chip_size;
|
||||
|
||||
esp_flash_default_chip = &default_chip;
|
||||
return ESP_OK;
|
||||
|
@ -107,6 +107,8 @@
|
||||
#define PAGES_LIMIT (IROM0_PAGES_END > DROM0_PAGES_END ? IROM0_PAGES_END:DROM0_PAGES_END)
|
||||
#define VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
typedef struct mmap_entry_{
|
||||
uint32_t handle;
|
||||
int page;
|
||||
@ -405,12 +407,16 @@ uint32_t IRAM_ATTR spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32_t spi_flash_cache2phys(const void *cached)
|
||||
size_t spi_flash_cache2phys(const void *cached)
|
||||
{
|
||||
intptr_t c = (intptr_t)cached;
|
||||
size_t cache_page;
|
||||
int offset = 0;
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
if (c >= VADDR1_START_ADDR && c < VADDR1_FIRST_USABLE_ADDR) {
|
||||
#else
|
||||
if (c >= SOC_IRAM_LOW && c < VADDR1_FIRST_USABLE_ADDR) {
|
||||
#endif
|
||||
/* IRAM address, doesn't map to flash */
|
||||
return SPI_FLASH_CACHE2PHYS_FAIL;
|
||||
} else if (c < VADDR1_FIRST_USABLE_ADDR) {
|
||||
@ -564,3 +570,4 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif //!CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
@ -116,8 +116,6 @@ const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
|
||||
.yield = NULL,
|
||||
};
|
||||
|
||||
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS
|
||||
#define UNSAFE_WRITE_ADDRESS abort()
|
||||
#else
|
||||
@ -132,7 +130,7 @@ static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
||||
#define CHECK_WRITE_ADDRESS(ADDR, SIZE)
|
||||
#else /* FAILS or ABORTS */
|
||||
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \
|
||||
if (s_flash_guard_ops && s_flash_guard_ops->is_safe_write_address && !s_flash_guard_ops->is_safe_write_address(ADDR, SIZE)) { \
|
||||
if (guard && guard->is_safe_write_address && !guard->is_safe_write_address(ADDR, SIZE)) { \
|
||||
return ESP_ERR_INVALID_ARG; \
|
||||
} \
|
||||
} while(0)
|
||||
@ -146,14 +144,39 @@ static __attribute__((unused)) bool is_safe_write_address(size_t addr, size_t si
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
#include "esp_heap_caps.h"
|
||||
typedef void *(*malloc_internal_cb_t)(size_t size);
|
||||
|
||||
void IRAM_ATTR *spi_flash_malloc_internal(size_t size)
|
||||
{
|
||||
return heap_caps_malloc(size, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void spi_flash_init(void)
|
||||
{
|
||||
spi_flash_init_lock();
|
||||
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
spi_flash_reset_counters();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
/* These two functions are in ROM only */
|
||||
extern void spi_flash_mmap_os_func_set(void *(*func1)(size_t size), void (*func2)(void *p));
|
||||
spi_flash_mmap_os_func_set(spi_flash_malloc_internal, heap_caps_free);
|
||||
|
||||
extern esp_err_t spi_flash_mmap_page_num_init(uint32_t page_num);
|
||||
spi_flash_mmap_page_num_init(128);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
|
||||
|
||||
void IRAM_ATTR spi_flash_guard_set(const spi_flash_guard_funcs_t *funcs)
|
||||
{
|
||||
s_flash_guard_ops = funcs;
|
||||
@ -164,6 +187,8 @@ const spi_flash_guard_funcs_t *IRAM_ATTR spi_flash_guard_get(void)
|
||||
return s_flash_guard_ops;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
size_t IRAM_ATTR spi_flash_get_chip_size(void)
|
||||
{
|
||||
return g_rom_flashchip.chip_size;
|
||||
@ -171,29 +196,33 @@ size_t IRAM_ATTR spi_flash_get_chip_size(void)
|
||||
|
||||
static inline void IRAM_ATTR spi_flash_guard_start(void)
|
||||
{
|
||||
if (s_flash_guard_ops && s_flash_guard_ops->start) {
|
||||
s_flash_guard_ops->start();
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
if (guard && guard->start) {
|
||||
guard->start();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR spi_flash_guard_end(void)
|
||||
{
|
||||
if (s_flash_guard_ops && s_flash_guard_ops->end) {
|
||||
s_flash_guard_ops->end();
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
if (guard && guard->end) {
|
||||
guard->end();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR spi_flash_guard_op_lock(void)
|
||||
{
|
||||
if (s_flash_guard_ops && s_flash_guard_ops->op_lock) {
|
||||
s_flash_guard_ops->op_lock();
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
if (guard && guard->op_lock) {
|
||||
guard->op_lock();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR spi_flash_guard_op_unlock(void)
|
||||
{
|
||||
if (s_flash_guard_ops && s_flash_guard_ops->op_unlock) {
|
||||
s_flash_guard_ops->op_unlock();
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
if (guard && guard->op_unlock) {
|
||||
guard->op_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,6 +261,7 @@ static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
|
||||
|
||||
esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
|
||||
{
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
CHECK_WRITE_ADDRESS(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
return spi_flash_erase_range(sec * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
@ -240,6 +270,7 @@ esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
|
||||
//deprecated, only used in compatible mode
|
||||
esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size)
|
||||
{
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
CHECK_WRITE_ADDRESS(start_addr, size);
|
||||
if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -379,6 +410,7 @@ static IRAM_ATTR esp_rom_spiflash_result_t spi_flash_write_inner(uint32_t target
|
||||
|
||||
esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
|
||||
{
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
CHECK_WRITE_ADDRESS(dst, size);
|
||||
// Out of bound writes are checked in ROM code, but we can give better
|
||||
// error code here
|
||||
@ -479,6 +511,7 @@ out:
|
||||
esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
|
||||
CHECK_WRITE_ADDRESS(dest_addr, size);
|
||||
if ((dest_addr % 16) != 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
|
@ -182,6 +182,10 @@ struct spi_flash_chip_t {
|
||||
* Read the requested register (status, etc.).
|
||||
*/
|
||||
esp_err_t (*read_reg)(esp_flash_t *chip, spi_flash_register_t reg_id, uint32_t* out_reg);
|
||||
|
||||
/** Yield to other tasks. Called during erase operations. */
|
||||
esp_err_t (*yield)(esp_flash_t *chip, uint32_t wip);
|
||||
|
||||
};
|
||||
|
||||
/* Pointer to an array of pointers to all known drivers for flash chips. This array is used
|
||||
|
@ -29,4 +29,8 @@
|
||||
* chips, and GD25LQ chips, WRSR (01H) command is used; while WRSR2 (31H) is used for GD25Q32 -
|
||||
* GD25Q127 chips.
|
||||
*/
|
||||
esp_err_t spi_flash_chip_gd_probe(esp_flash_t *chip, uint32_t flash_id);
|
||||
esp_err_t spi_flash_chip_gd_set_io_mode(esp_flash_t *chip);
|
||||
esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode);
|
||||
|
||||
extern const spi_flash_chip_t esp_flash_chip_gd;
|
||||
|
@ -392,7 +392,7 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, bool add
|
||||
* @param wip Write (erase) in progress, `true` if this function is called during waiting idle of a erase/write command; else `false`.
|
||||
* @return ESP_OK if success, otherwise failed.
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, bool wip);
|
||||
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, uint32_t wip);
|
||||
|
||||
/// Default timeout configuration used by most chips
|
||||
const flash_chip_op_timeout_t spi_flash_chip_generic_timeout;
|
||||
|
@ -24,4 +24,8 @@
|
||||
* default autodetection, this is used as a catchall if a more specific chip_drv
|
||||
* is not found.
|
||||
*/
|
||||
esp_err_t spi_flash_chip_issi_probe(esp_flash_t *chip, uint32_t flash_id);
|
||||
esp_err_t spi_flash_chip_issi_set_io_mode(esp_flash_t *chip);
|
||||
esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode);
|
||||
|
||||
extern const spi_flash_chip_t esp_flash_chip_issi;
|
||||
|
@ -22,7 +22,6 @@
|
||||
#define SPI_FLASH_HAL_MAX_WRITE_BYTES 64
|
||||
#define SPI_FLASH_HAL_MAX_READ_BYTES 64
|
||||
|
||||
static const char TAG[] = "memspi";
|
||||
DRAM_ATTR static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
@ -73,12 +72,20 @@ esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_
|
||||
else {
|
||||
host->inst.driver = &esp_flash_gpspi_host;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
if (cfg->host_id == SPI_HOST) {
|
||||
host->inst.driver = &esp_flash_default_host;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t err = spi_flash_hal_init(host, cfg);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static const char TAG[] = "memspi";
|
||||
|
||||
esp_err_t memspi_host_read_id_hs(spi_flash_host_inst_t *host, uint32_t *id)
|
||||
{
|
||||
uint32_t id_buf = 0;
|
||||
@ -214,3 +221,5 @@ int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address,
|
||||
*align_address = address;
|
||||
return MIN(max_len, len);
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
@ -14,8 +14,11 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "spi_flash_chip_generic.h"
|
||||
#include "spi_flash_chip_gd.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
#define FLASH_ID_MASK 0xFF00
|
||||
#define FLASH_SIZE_MASK 0xFF
|
||||
#define GD25Q_PRODUCT_ID 0x4000
|
||||
@ -70,7 +73,7 @@ esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t*
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static const char chip_name[] = "gd";
|
||||
|
||||
@ -107,4 +110,5 @@ const spi_flash_chip_t esp_flash_chip_gd = {
|
||||
.get_io_mode = spi_flash_chip_gd_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
};
|
||||
|
@ -20,10 +20,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
|
||||
static const char TAG[] = "chip_generic";
|
||||
|
||||
|
||||
typedef struct flash_chip_dummy {
|
||||
uint8_t dio_dummy_bitlen;
|
||||
uint8_t qio_dummy_bitlen;
|
||||
@ -62,6 +58,10 @@ const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = {
|
||||
.page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static const char TAG[] = "chip_generic";
|
||||
|
||||
esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id)
|
||||
{
|
||||
// This is the catch-all probe function, claim the chip always if nothing
|
||||
@ -322,7 +322,7 @@ esp_err_t spi_flash_chip_generic_read_reg(esp_flash_t* chip, spi_flash_register_
|
||||
return chip->host->driver->read_status(chip->host, (uint8_t*)out_reg);
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, bool wip)
|
||||
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, uint32_t wip)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t flags = wip? 1: 0; //check_yield() and yield() impls should not issue suspend/resume if this flag is zero
|
||||
@ -472,6 +472,7 @@ esp_err_t spi_flash_chip_generic_set_io_mode(esp_flash_t *chip)
|
||||
spi_flash_common_read_status_16b_rdsr_rdsr2,
|
||||
BIT_QE);
|
||||
}
|
||||
#endif // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
static const char chip_name[] = "generic";
|
||||
|
||||
@ -509,8 +510,10 @@ const spi_flash_chip_t esp_flash_chip_generic = {
|
||||
.get_io_mode = spi_flash_chip_generic_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
/*******************************************************************************
|
||||
* Utility functions
|
||||
******************************************************************************/
|
||||
@ -647,3 +650,5 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "spi_flash_chip_generic.h"
|
||||
#include "spi_flash_chip_issi.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
/* Driver for ISSI flash chip, as used in ESP32 D2WD */
|
||||
@ -93,4 +94,5 @@ const spi_flash_chip_t esp_flash_chip_issi = {
|
||||
.get_io_mode = spi_flash_chip_issi_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
};
|
||||
|
@ -72,4 +72,5 @@ const spi_flash_chip_t esp_flash_chip_mxic = {
|
||||
.get_io_mode = spi_flash_chip_mxic_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_mxic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
};
|
||||
|
@ -175,6 +175,7 @@ const spi_flash_chip_t esp_flash_chip_winbond = {
|
||||
.get_io_mode = spi_flash_chip_generic_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
};
|
||||
|
||||
|
||||
|
@ -38,6 +38,12 @@ typedef struct {
|
||||
uint32_t dcache_autoload;
|
||||
} spi_noos_arg_t;
|
||||
|
||||
static DRAM_ATTR spi_noos_arg_t spi_arg = { 0 };
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
typedef struct {
|
||||
uint32_t icache_autoload;
|
||||
} spi_noos_arg_t;
|
||||
|
||||
static DRAM_ATTR spi_noos_arg_t spi_arg = { 0 };
|
||||
#endif
|
||||
|
||||
@ -50,6 +56,9 @@ static IRAM_ATTR esp_err_t start(void *arg)
|
||||
spi_noos_arg_t *spi_arg = arg;
|
||||
spi_arg->icache_autoload = Cache_Suspend_ICache();
|
||||
spi_arg->dcache_autoload = Cache_Suspend_DCache();
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
spi_noos_arg_t *spi_arg = arg;
|
||||
spi_arg->icache_autoload = Cache_Suspend_ICache();
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -80,6 +89,13 @@ static IRAM_ATTR esp_err_t delay_us(void *arg, uint32_t us)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Currently when the os is not up yet, the caller is supposed to call esp_flash APIs with proper
|
||||
// buffers.
|
||||
IRAM_ATTR void* get_temp_buffer_not_supported(void* arg, size_t reqest_size, size_t* out_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = {
|
||||
.start = start,
|
||||
.end = end,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "ccomp_timer.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#define FUNC_SPI 1
|
||||
|
||||
@ -82,6 +83,26 @@ static uint8_t sector_buf[4096];
|
||||
#define FSPI_PIN_NUM_WP 38
|
||||
#define FSPI_PIN_NUM_CS 34
|
||||
|
||||
// Just use the same pins for HSPI
|
||||
#define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI
|
||||
#define HSPI_PIN_NUM_MISO FSPI_PIN_NUM_MISO
|
||||
#define HSPI_PIN_NUM_CLK FSPI_PIN_NUM_CLK
|
||||
#define HSPI_PIN_NUM_HD FSPI_PIN_NUM_HD
|
||||
#define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP
|
||||
#define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define SPI1_CS_IO 26 //the pin which is usually used by the PSRAM cs
|
||||
#define SPI1_HD_IO 27 //the pin which is usually used by the PSRAM hd
|
||||
#define SPI1_WP_IO 28 //the pin which is usually used by the PSRAM wp
|
||||
|
||||
#define FSPI_PIN_NUM_MOSI 7
|
||||
#define FSPI_PIN_NUM_MISO 2
|
||||
#define FSPI_PIN_NUM_CLK 6
|
||||
#define FSPI_PIN_NUM_HD 4
|
||||
#define FSPI_PIN_NUM_WP 5
|
||||
#define FSPI_PIN_NUM_CS 10
|
||||
|
||||
// Just use the same pins for HSPI
|
||||
#define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI
|
||||
#define HSPI_PIN_NUM_MISO FSPI_PIN_NUM_MISO
|
||||
@ -108,7 +129,8 @@ typedef void (*flash_test_func_t)(const esp_partition_t *part);
|
||||
|
||||
These tests run for all the flash chip configs shown in config_list, below (internal and external).
|
||||
*/
|
||||
#if defined(CONFIG_SPIRAM)
|
||||
#if defined(CONFIG_SPIRAM) || TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
||||
|
||||
#define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
|
||||
#define FLASH_TEST_CASE_3_IGNORE(STR, FUNCT_TO_RUN)
|
||||
#else
|
||||
@ -188,7 +210,20 @@ flashtest_config_t config_list[] = {
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
flashtest_config_t config_list[] = {
|
||||
FLASHTEST_CONFIG_COMMON,
|
||||
/* No runners for esp32s2 for these config yet */
|
||||
/* No runners for esp32s3 for these config yet */
|
||||
{
|
||||
.io_mode = TEST_SPI_READ_MODE,
|
||||
.speed = TEST_SPI_SPEED,
|
||||
.host_id = FSPI_HOST,
|
||||
.cs_id = 0,
|
||||
.cs_io_num = FSPI_PIN_NUM_CS,
|
||||
.input_delay_ns = 0,
|
||||
},
|
||||
};
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
flashtest_config_t config_list[] = {
|
||||
FLASHTEST_CONFIG_COMMON,
|
||||
/* No runners for esp32c3 for these config yet */
|
||||
{
|
||||
.io_mode = TEST_SPI_READ_MODE,
|
||||
.speed = TEST_SPI_SPEED,
|
||||
@ -197,16 +232,6 @@ flashtest_config_t config_list[] = {
|
||||
.cs_io_num = FSPI_PIN_NUM_CS,
|
||||
.input_delay_ns = 0,
|
||||
},
|
||||
// /* current runner doesn't have a flash on HSPI */
|
||||
// {
|
||||
// .io_mode = TEST_SPI_READ_MODE,
|
||||
// .speed = TEST_SPI_SPEED,
|
||||
// .host_id = HSPI_HOST,
|
||||
// .cs_id = 0,
|
||||
// // uses GPIO matrix on esp32s2 regardless if FORCE_GPIO_MATRIX
|
||||
// .cs_io_num = HSPI_PIN_NUM_CS,
|
||||
// .input_delay_ns = 20,
|
||||
// },
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -296,7 +321,7 @@ static void setup_bus(spi_host_device_t host_id)
|
||||
gpio_set_level(HSPI_PIN_NUM_WP, 1);
|
||||
#endif
|
||||
}
|
||||
#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||
#if !DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
|
||||
else if (host_id == VSPI_HOST) {
|
||||
ESP_LOGI(TAG, "setup flash on SPI%d (VSPI) CS0...\n", host_id + 1);
|
||||
spi_bus_config_t vspi_bus_cfg = {
|
||||
@ -801,12 +826,14 @@ TEST_CASE("SPI flash test reading with all speed/mode permutations", "[esp_flash
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPIRAM
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
||||
TEST_CASE("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash_3][test_env=UT_T1_ESP_FLASH]")
|
||||
{
|
||||
for (int i = 0; i < TEST_CONFIG_NUM; i++) {
|
||||
test_permutations_chip(&config_list[i]);
|
||||
}
|
||||
}
|
||||
#endif //TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -153,6 +153,9 @@ TEST_CASE("Can mmap into data address space", "[spi_flash][mmap]")
|
||||
TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(start, SPI_FLASH_MMAP_DATA));
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
||||
// TODO ESP32C3 IDF-2458
|
||||
|
||||
TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
|
||||
{
|
||||
setup_mmap_tests();
|
||||
@ -209,6 +212,9 @@ TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
|
||||
|
||||
}
|
||||
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
|
||||
|
||||
|
||||
TEST_CASE("Can mmap unordered pages into contiguous memory", "[spi_flash][mmap]")
|
||||
{
|
||||
int nopages;
|
||||
@ -352,7 +358,8 @@ TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash][mmap]")
|
||||
{
|
||||
uint8_t buf[64];
|
||||
|
||||
static const uint8_t constant_data[] = { 1, 2, 3, 7, 11, 16, 3, 88 };
|
||||
/* Avoid put constant data in the sdata/sdata2 section */
|
||||
static const uint8_t constant_data[] = { 1, 2, 3, 7, 11, 16, 3, 88, 99};
|
||||
|
||||
/* esp_partition_find is in IROM */
|
||||
uint32_t phys = spi_flash_cache2phys(esp_partition_find);
|
||||
|
@ -238,7 +238,7 @@ TEST_CASE("Test spi_flash_write", "[spi_flash][esp_flash]")
|
||||
* NB: At the moment these only support aligned addresses, because memcpy
|
||||
* is not aware of the 32-but load requirements for these regions.
|
||||
*/
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
||||
#define TEST_SOC_IROM_ADDR (SOC_IROM_LOW)
|
||||
#define TEST_SOC_CACHE_RAM_BANK0_ADDR (SOC_IRAM_LOW)
|
||||
#define TEST_SOC_CACHE_RAM_BANK1_ADDR (SOC_IRAM_LOW + 0x2000)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "ccomp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -21,6 +22,8 @@
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
struct flash_test_ctx {
|
||||
@ -391,9 +394,9 @@ TEST_CASE("spi_flash deadlock with high priority busy-waiting task", "[spi_flash
|
||||
|
||||
TEST_CASE("WEL is cleared after boot", "[spi_flash]")
|
||||
{
|
||||
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
|
||||
esp_rom_spiflash_chip_t *legacy_chip = &g_rom_flashchip;
|
||||
uint32_t status;
|
||||
esp_rom_spiflash_read_status(&g_rom_spiflash_chip, &status);
|
||||
esp_rom_spiflash_read_status(legacy_chip, &status);
|
||||
|
||||
TEST_ASSERT((status & 0x2) == 0);
|
||||
}
|
||||
@ -402,15 +405,15 @@ TEST_CASE("WEL is cleared after boot", "[spi_flash]")
|
||||
// ISSI chip has its QE bit on other chips' BP4, which may get cleared by accident
|
||||
TEST_CASE("rom unlock will not erase QE bit", "[spi_flash]")
|
||||
{
|
||||
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
|
||||
esp_rom_spiflash_chip_t *legacy_chip = &g_rom_flashchip;
|
||||
uint32_t status;
|
||||
printf("dev_id: %08X \n", g_rom_spiflash_chip.device_id);
|
||||
printf("dev_id: %08X \n", legacy_chip->device_id);
|
||||
|
||||
if (((g_rom_spiflash_chip.device_id >> 16) & 0xff) != 0x9D) {
|
||||
if (((legacy_chip->device_id >> 16) & 0xff) != 0x9D) {
|
||||
TEST_IGNORE_MESSAGE("This test is only for ISSI chips. Ignore.");
|
||||
}
|
||||
esp_rom_spiflash_unlock();
|
||||
esp_rom_spiflash_read_status(&g_rom_spiflash_chip, &status);
|
||||
esp_rom_spiflash_read_status(legacy_chip, &status);
|
||||
printf("status: %08x\n", status);
|
||||
|
||||
TEST_ASSERT(status & 0x40);
|
||||
|
Loading…
x
Reference in New Issue
Block a user