Merge branch 'feature/esp32c3_spi_flash' into 'master'

spi_flash: Add esp32c3 support

Closes IDF-2362

See merge request espressif/esp-idf!11639
This commit is contained in:
Angus Gratton
2020-12-18 14:02:04 +08:00
31 changed files with 716 additions and 212 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -0,0 +1,42 @@
// 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.
#pragma once
#include <stdint.h>
#include "soc/dport_reg.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Defined for flash mmap */
#define SOC_MMU_REGIONS_COUNT 4
#define SOC_MMU_PAGES_PER_REGION 64
#define SOC_MMU_IROM0_PAGES_START 64
#define SOC_MMU_IROM0_PAGES_END 256
#define SOC_MMU_DROM0_PAGES_START 0
#define SOC_MMU_DROM0_PAGES_END 64
#define SOC_MMU_INVALID_ENTRY_VAL DPORT_FLASH_MMU_TABLE_INVALID_VAL
#define SOC_MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK
#define SOC_MMU_PAGE_IN_FLASH(page) (page)
#define SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE ((volatile uint32_t*) 0x3FF10000)
#define SOC_MMU_VADDR1_START_ADDR SOC_IROM_MASK_LOW
#define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE ((SOC_MMU_VADDR1_FIRST_USABLE_ADDR - SOC_MMU_VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_IROM0_PAGES_START)
#define SOC_MMU_VADDR0_START_ADDR SOC_DROM_LOW
#define SOC_MMU_VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,42 @@
// 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.
#pragma once
#include <stdint.h>
#include "soc/cache_memory.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Defined for flash mmap */
#define SOC_MMU_REGIONS_COUNT 1
#define SOC_MMU_PAGES_PER_REGION 128
#define SOC_MMU_IROM0_PAGES_START (CACHE_IROM_MMU_START / sizeof(uint32_t))
#define SOC_MMU_IROM0_PAGES_END (CACHE_IROM_MMU_END / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_START (CACHE_DROM_MMU_START / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_END (CACHE_DROM_MMU_END / sizeof(uint32_t))
#define SOC_MMU_INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define SOC_MMU_ADDR_MASK MMU_ADDRESS_MASK
#define SOC_MMU_PAGE_IN_FLASH(page) (page) //Always in Flash
#define SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define SOC_MMU_VADDR1_START_ADDR SOC_IRAM_LOW
#define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE SOC_MMU_IROM0_PAGES_START
#define SOC_MMU_VADDR0_START_ADDR (SOC_DROM_LOW + (SOC_MMU_DROM0_PAGES_START * SPI_FLASH_MMU_PAGE_SIZE))
#define SOC_MMU_VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
#ifdef __cplusplus
}
#endif

View File

@@ -262,22 +262,6 @@
// Start (highest address) of ROM boot stack, only relevant during early boot
#define SOC_ROM_STACK_START 0x3fcebf10
/* Defined for flash mmap */
#define REGIONS_COUNT 1
#define PAGES_PER_REGION 128
#define IROM0_PAGES_START (CACHE_IROM_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (CACHE_IROM_MMU_END / sizeof(uint32_t))
#define DROM0_PAGES_START (CACHE_DROM_MMU_START / sizeof(uint32_t))
#define DROM0_PAGES_END (CACHE_DROM_MMU_END / sizeof(uint32_t))
#define INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK MMU_ADDRESS_MASK
#define PAGE_IN_FLASH(page) (page) //Always in Flash
#define DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW
#define PRO_IRAM0_FIRST_USABLE_PAGE IROM0_PAGES_START
#define VADDR0_START_ADDR (SOC_DROM_LOW + (DROM0_PAGES_START * SPI_FLASH_MMU_PAGE_SIZE))
#define VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
//interrupt cpu using table, Please see the core-isa.h
/*************************************************************************************************************
* Intr num Level Type PRO CPU usage APP CPU uasge

View File

@@ -0,0 +1,42 @@
// 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.
#pragma once
#include <stdint.h>
#include "soc/cache_memory.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Defined for flash mmap */
#define SOC_MMU_REGIONS_COUNT 6
#define SOC_MMU_PAGES_PER_REGION 64
#define SOC_MMU_IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t))
#define SOC_MMU_IROM0_PAGES_END (PRO_CACHE_IBUS1_MMU_END / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_START (PRO_CACHE_IBUS2_MMU_START / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t))
#define SOC_MMU_INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define SOC_MMU_ADDR_MASK MMU_ADDRESS_MASK
#define SOC_MMU_PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define SOC_MMU_VADDR1_START_ADDR SOC_IROM_MASK_LOW
#define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE ((SOC_MMU_VADDR1_FIRST_USABLE_ADDR - SOC_MMU_VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_IROM0_PAGES_START)
#define SOC_MMU_VADDR0_START_ADDR SOC_DROM_LOW
#define SOC_MMU_VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,42 @@
// 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.
#pragma once
#include <stdint.h>
#include "soc/cache_memory.h"
#include "soc/soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Defined for flash mmap */
#define SOC_MMU_REGIONS_COUNT 2
#define SOC_MMU_PAGES_PER_REGION 256
#define SOC_MMU_IROM0_PAGES_START (CACHE_IROM_MMU_START / sizeof(uint32_t))
#define SOC_MMU_IROM0_PAGES_END (CACHE_IROM_MMU_END / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_START (CACHE_DROM_MMU_START / sizeof(uint32_t))
#define SOC_MMU_DROM0_PAGES_END (CACHE_DROM_MMU_END / sizeof(uint32_t))
#define SOC_MMU_INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define SOC_MMU_ADDR_MASK MMU_ADDRESS_MASK
#define SOC_MMU_PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define SOC_MMU_VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW
#define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE SOC_MMU_IROM0_PAGES_START
#define SOC_MMU_VADDR0_START_ADDR (SOC_DROM_LOW + (SOC_MMU_DROM0_PAGES_START * SPI_FLASH_MMU_PAGE_SIZE))
#define SOC_MMU_VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
#ifdef __cplusplus
}
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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;
}
}

View 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;
}

View File

@@ -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)

View File

@@ -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;
}
default_chip.size = g_rom_flashchip.chip_size;
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;
esp_flash_default_chip = &default_chip;
return ESP_OK;

View File

@@ -35,22 +35,26 @@
#include "esp32/rom/cache.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/spiram.h"
#include "soc/mmu.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/cache.h"
#include "esp32s2/rom/spi_flash.h"
#include "esp32s2/spiram.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/mmu.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/spiram.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/mmu.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/cache.h"
#include "esp32c3/rom/spi_flash.h"
#include "soc/cache_memory.h"
#include "soc/mmu.h"
#endif
#ifndef NDEBUG
@@ -59,53 +63,11 @@
#endif
#include "sys/queue.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#define PAGES_PER_REGION 64
#define REGIONS_COUNT 4
#define IROM0_PAGES_START 64
#define IROM0_PAGES_END 256
#define DROM0_PAGES_START 0
#define DROM0_PAGES_END 64
#define PAGE_IN_FLASH(page) (page)
#define INVALID_ENTRY_VAL DPORT_FLASH_MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK
#define VADDR1_START_ADDR 0x40000000
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)
#define VADDR0_START_ADDR SOC_DROM_LOW
#elif CONFIG_IDF_TARGET_ESP32S2
#define PAGES_PER_REGION 64
#define REGIONS_COUNT 6
#define IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (PRO_CACHE_IBUS1_MMU_END / sizeof(uint32_t))
#define DROM0_PAGES_START (PRO_CACHE_IBUS2_MMU_START / sizeof(uint32_t))
#define DROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t))
#define DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK MMU_ADDRESS_MASK
#define PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define VADDR1_START_ADDR 0x40000000
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)
#define VADDR0_START_ADDR SOC_DROM_LOW
#elif CONFIG_IDF_TARGET_ESP32S3
#define REGIONS_COUNT 2
#define PAGES_PER_REGION 256
#define IROM0_PAGES_START (CACHE_IROM_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (CACHE_IROM_MMU_END / sizeof(uint32_t))
#define DROM0_PAGES_START (CACHE_DROM_MMU_START / sizeof(uint32_t))
#define DROM0_PAGES_END (CACHE_DROM_MMU_END / sizeof(uint32_t))
#define DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK MMU_ADDRESS_MASK
#define PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW
#define PRO_IRAM0_FIRST_USABLE_PAGE (IROM0_PAGES_START)
#define VADDR0_START_ADDR (SOC_DROM_LOW + (DROM0_PAGES_START * SPI_FLASH_MMU_PAGE_SIZE))
#endif
#define IROM0_PAGES_NUM (SOC_MMU_IROM0_PAGES_END - SOC_MMU_IROM0_PAGES_START)
#define DROM0_PAGES_NUM (SOC_MMU_DROM0_PAGES_END - SOC_MMU_DROM0_PAGES_START)
#define PAGES_LIMIT ((SOC_MMU_IROM0_PAGES_END > SOC_MMU_DROM0_PAGES_END) ? SOC_MMU_IROM0_PAGES_END:SOC_MMU_DROM0_PAGES_END)
#define IROM0_PAGES_NUM (IROM0_PAGES_END - IROM0_PAGES_START)
#define DROM0_PAGES_NUM (DROM0_PAGES_END - DROM0_PAGES_START)
#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;
@@ -117,33 +79,33 @@ typedef struct mmap_entry_{
static LIST_HEAD(mmap_entries_head, mmap_entry_) s_mmap_entries_head =
LIST_HEAD_INITIALIZER(s_mmap_entries_head);
static uint8_t s_mmap_page_refcnt[REGIONS_COUNT * PAGES_PER_REGION] = {0};
static uint8_t s_mmap_page_refcnt[SOC_MMU_REGIONS_COUNT * SOC_MMU_PAGES_PER_REGION] = {0};
static uint32_t s_mmap_last_handle = 0;
static void IRAM_ATTR spi_flash_mmap_init(void)
{
if (s_mmap_page_refcnt[DROM0_PAGES_START] != 0) {
if (s_mmap_page_refcnt[SOC_MMU_DROM0_PAGES_START] != 0) {
return; /* mmap data already initialised */
}
DPORT_INTERRUPT_DISABLE();
for (int i = 0; i < REGIONS_COUNT * PAGES_PER_REGION; ++i) {
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
for (int i = 0; i < SOC_MMU_REGIONS_COUNT * SOC_MMU_PAGES_PER_REGION; ++i) {
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i]);
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
if (entry_pro != entry_app) {
// clean up entries used by boot loader
entry_pro = INVALID_ENTRY_VAL;
DPORT_PRO_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
entry_pro = SOC_MMU_INVALID_ENTRY_VAL;
SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
}
#endif
if ((entry_pro & INVALID_ENTRY_VAL) == 0 && (i == DROM0_PAGES_START || i == PRO_IRAM0_FIRST_USABLE_PAGE || entry_pro != 0)) {
if ((entry_pro & SOC_MMU_INVALID_ENTRY_VAL) == 0 && (i == SOC_MMU_DROM0_PAGES_START || i == SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE || entry_pro != 0)) {
s_mmap_page_refcnt[i] = 1;
} else {
DPORT_PRO_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
DPORT_APP_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
#endif
}
}
@@ -154,14 +116,14 @@ static void IRAM_ATTR get_mmu_region(spi_flash_mmap_memory_t memory, int* out_be
{
if (memory == SPI_FLASH_MMAP_DATA) {
// Vaddr0
*out_begin = DROM0_PAGES_START;
*out_begin = SOC_MMU_DROM0_PAGES_START;
*out_size = DROM0_PAGES_NUM;
*region_addr = VADDR0_START_ADDR;
*region_addr = SOC_MMU_VADDR0_START_ADDR;
} else {
// only part of VAddr1 is usable, so adjust for that
*out_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
*out_size = IROM0_PAGES_END - *out_begin;
*region_addr = VADDR1_FIRST_USABLE_ADDR;
*out_begin = SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE;
*out_size = SOC_MMU_IROM0_PAGES_END - *out_begin;
*region_addr = SOC_MMU_VADDR1_FIRST_USABLE_ADDR;
}
}
@@ -236,9 +198,9 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
int pos;
DPORT_INTERRUPT_DISABLE();
for (pos = start; pos < start + page_count; ++pos, ++pageno) {
int table_val = (int) DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[pos]);
int table_val = (int) DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[pos]);
uint8_t refcnt = s_mmap_page_refcnt[pos];
if (refcnt != 0 && table_val != PAGE_IN_FLASH(pages[pageno])) {
if (refcnt != 0 && table_val != SOC_MMU_PAGE_IN_FLASH(pages[pageno])) {
break;
}
}
@@ -259,23 +221,23 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
DPORT_INTERRUPT_DISABLE();
for (int i = start; i != start + page_count; ++i, ++pageno) {
// sanity check: we won't reconfigure entries with non-zero reference count
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i]);
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
#endif
assert(s_mmap_page_refcnt[i] == 0 ||
(entry_pro == PAGE_IN_FLASH(pages[pageno])
(entry_pro == SOC_MMU_PAGE_IN_FLASH(pages[pageno])
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
&& entry_app == PAGE_IN_FLASH(pages[pageno])
&& entry_app == SOC_MMU_PAGE_IN_FLASH(pages[pageno])
#endif
));
if (s_mmap_page_refcnt[i] == 0) {
if (entry_pro != PAGE_IN_FLASH(pages[pageno])
if (entry_pro != SOC_MMU_PAGE_IN_FLASH(pages[pageno])
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
|| entry_app != PAGE_IN_FLASH(pages[pageno])
|| entry_app != SOC_MMU_PAGE_IN_FLASH(pages[pageno])
#endif
) {
DPORT_PRO_FLASH_MMU_TABLE[i] = PAGE_IN_FLASH(pages[pageno]);
SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = SOC_MMU_PAGE_IN_FLASH(pages[pageno]);
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno];
#endif
@@ -336,9 +298,9 @@ void IRAM_ATTR spi_flash_munmap(spi_flash_mmap_handle_t handle)
for (int i = it->page; i < it->page + it->count; ++i) {
assert(s_mmap_page_refcnt[i] > 0);
if (--s_mmap_page_refcnt[i] == 0) {
DPORT_PRO_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
DPORT_APP_FLASH_MMU_TABLE[i] = SOC_MMU_INVALID_ENTRY_VAL;
#endif
}
}
@@ -364,7 +326,7 @@ static uint32_t IRAM_ATTR NOINLINE_ATTR spi_flash_protected_read_mmu_entry(int i
{
uint32_t value;
spi_flash_disable_interrupts_caches_and_other_cpu();
value = DPORT_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[index]);
value = DPORT_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[index]);
spi_flash_enable_interrupts_caches_and_other_cpu();
return value;
}
@@ -377,7 +339,7 @@ void spi_flash_mmap_dump(void)
for (it = LIST_FIRST(&s_mmap_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
printf("handle=%d page=%d count=%d\n", it->handle, it->page, it->count);
}
for (int i = 0; i < REGIONS_COUNT * PAGES_PER_REGION; ++i) {
for (int i = 0; i < SOC_MMU_REGIONS_COUNT * SOC_MMU_PAGES_PER_REGION; ++i) {
if (s_mmap_page_refcnt[i] != 0) {
uint32_t paddr = spi_flash_protected_read_mmu_entry(i);
printf("page %d: refcnt=%d paddr=%d\n", i, (int) s_mmap_page_refcnt[i], paddr);
@@ -396,7 +358,7 @@ uint32_t IRAM_ATTR spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
get_mmu_region(memory,&region_begin,&region_size,&region_addr);
DPORT_INTERRUPT_DISABLE();
for (int i = region_begin; i < region_begin + region_size; ++i) {
if (s_mmap_page_refcnt[i] == 0 && DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == INVALID_ENTRY_VAL) {
if (s_mmap_page_refcnt[i] == 0 && DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i]) == SOC_MMU_INVALID_ENTRY_VAL) {
count++;
}
}
@@ -405,17 +367,18 @@ 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 (c >= VADDR1_START_ADDR && c < VADDR1_FIRST_USABLE_ADDR) {
if (c >= SOC_MMU_VADDR1_START_ADDR && c < SOC_MMU_VADDR1_FIRST_USABLE_ADDR) {
/* IRAM address, doesn't map to flash */
return SPI_FLASH_CACHE2PHYS_FAIL;
} else if (c < VADDR1_FIRST_USABLE_ADDR) {
}
if (c < SOC_MMU_VADDR1_FIRST_USABLE_ADDR) {
/* expect cache is in DROM */
cache_page = (c - VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + DROM0_PAGES_START;
cache_page = (c - SOC_MMU_VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_DROM0_PAGES_START;
#if CONFIG_SPIRAM_RODATA
if (c >= (uint32_t)&_rodata_reserved_start && c <= (uint32_t)&_rodata_reserved_end) {
offset = rodata_flash2spiram_offset();
@@ -423,7 +386,7 @@ uint32_t spi_flash_cache2phys(const void *cached)
#endif
} else {
/* expect cache is in IROM */
cache_page = (c - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START;
cache_page = (c - SOC_MMU_VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_IROM0_PAGES_START;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (c >= (uint32_t)&_instruction_reserved_start && c <= (uint32_t)&_instruction_reserved_end) {
offset = instruction_flash2spiram_offset();
@@ -436,11 +399,11 @@ uint32_t spi_flash_cache2phys(const void *cached)
return SPI_FLASH_CACHE2PHYS_FAIL;
}
uint32_t phys_page = spi_flash_protected_read_mmu_entry(cache_page);
if (phys_page == INVALID_ENTRY_VAL) {
if (phys_page == SOC_MMU_INVALID_ENTRY_VAL) {
/* page is not mapped */
return SPI_FLASH_CACHE2PHYS_FAIL;
}
uint32_t phys_offs = ((phys_page & MMU_ADDR_MASK) + offset) * SPI_FLASH_MMU_PAGE_SIZE;
uint32_t phys_offs = ((phys_page & SOC_MMU_ADDR_MASK) + offset) * SPI_FLASH_MMU_PAGE_SIZE;
return phys_offs | (c & (SPI_FLASH_MMU_PAGE_SIZE-1));
}
@@ -451,25 +414,25 @@ const void *IRAM_ATTR spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memo
intptr_t base;
if (memory == SPI_FLASH_MMAP_DATA) {
start = DROM0_PAGES_START;
end = DROM0_PAGES_END;
base = VADDR0_START_ADDR;
page_delta = DROM0_PAGES_START > IROM0_PAGES_START ? DROM0_PAGES_START : 0;
start = SOC_MMU_DROM0_PAGES_START;
end = SOC_MMU_DROM0_PAGES_END;
base = SOC_MMU_VADDR0_START_ADDR;
page_delta = SOC_MMU_DROM0_PAGES_START;
} else {
start = PRO_IRAM0_FIRST_USABLE_PAGE;
end = IROM0_PAGES_END;
base = VADDR1_START_ADDR;
page_delta = DROM0_PAGES_START > IROM0_PAGES_START ? 0: IROM0_PAGES_START;
start = SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE;
end = SOC_MMU_IROM0_PAGES_END;
base = SOC_MMU_VADDR1_START_ADDR;
page_delta = SOC_MMU_IROM0_PAGES_START;
}
spi_flash_disable_interrupts_caches_and_other_cpu();
DPORT_INTERRUPT_DISABLE();
for (int i = start; i < end; i++) {
uint32_t mmu_value = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
uint32_t mmu_value = DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i]);
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
if (mmu_value & MMU_ACCESS_SPIRAM) {
mmu_value += instruction_flash2spiram_offset();
mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
mmu_value = (mmu_value & SOC_MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
}
}
#endif
@@ -477,11 +440,11 @@ const void *IRAM_ATTR spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memo
if (phys_page >= rodata_flash_start_page_get() && phys_page <= rodata_flash_start_page_get()) {
if (mmu_value & MMU_ACCESS_SPIRAM) {
mmu_value += rodata_flash2spiram_offset();
mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
mmu_value = (mmu_value & SOC_MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
}
}
#endif
if (mmu_value == PAGE_IN_FLASH(phys_page)) {
if (mmu_value == SOC_MMU_PAGE_IN_FLASH(phys_page)) {
i -= page_delta;
intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i);
DPORT_INTERRUPT_RESTORE();
@@ -501,22 +464,22 @@ static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **o
*out_ptr = NULL;
/* SPI_FLASH_MMAP_DATA */
start[0] = DROM0_PAGES_START;
end[0] = DROM0_PAGES_END;
start[0] = SOC_MMU_DROM0_PAGES_START;
end[0] = SOC_MMU_DROM0_PAGES_END;
/* SPI_FLASH_MMAP_INST */
start[1] = PRO_IRAM0_FIRST_USABLE_PAGE;
end[1] = IROM0_PAGES_END;
start[1] = SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE;
end[1] = SOC_MMU_IROM0_PAGES_END;
DPORT_INTERRUPT_DISABLE();
for (int j = 0; j < 2; j++) {
for (int i = start[j]; i < end[j]; i++) {
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) {
if (DPORT_SEQUENCE_REG_READ((uint32_t)&SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[i]) == SOC_MMU_PAGE_IN_FLASH(phys_page)) {
#if !CONFIG_IDF_TARGET_ESP32
if (j == 0) { /* SPI_FLASH_MMAP_DATA */
*out_ptr = (const void *)(VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
*out_ptr = (const void *)(SOC_MMU_VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
} else { /* SPI_FLASH_MMAP_INST */
*out_ptr = (const void *)(VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1]));
*out_ptr = (const void *)(SOC_MMU_VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1]));
}
#endif
DPORT_INTERRUPT_RESTORE();
@@ -564,3 +527,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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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,

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);