Merge branch 'refactor_flash/remove_legacy_driver' into 'master'

spi_flash: Totally remove legacy driver (prefix with `spi_flash`) support on V5.0

Closes IDF-4473

See merge request espressif/esp-idf!18026
This commit is contained in:
Simon 2022-07-01 14:45:39 +08:00
commit f4eea001c8
192 changed files with 861 additions and 2118 deletions

View File

@ -945,7 +945,7 @@ UT_C3_SDSPI:
UT_S3:
extends: .unit_test_esp32s3_template
parallel: 28
parallel: 29
tags:
- ESP32S3_IDF
- UT_T1_1

View File

@ -14,11 +14,10 @@
#include "esp_err.h"
#include "esp_partition.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_spi_flash.h"
#include "sdkconfig.h"
#include "esp_ota_ops.h"

View File

@ -7,7 +7,8 @@
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include "spi_flash_mmap.h" /* including in bootloader for error values */
#include "esp_private/spi_flash_os.h"
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "bootloader_flash_override.h"

View File

@ -10,7 +10,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include <spi_flash_mmap.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "bootloader_flash.h"

View File

@ -23,6 +23,9 @@
# define SPIFLASH SPIMEM1
#endif
// This dependency will be removed in the future. IDF-5025
#include "esp_flash.h"
#include "esp_rom_spiflash.h"
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@ -43,7 +46,7 @@
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
#ifndef BOOTLOADER_BUILD
/* Normal app version maps to esp_spi_flash.h operations...
/* Normal app version maps to spi_flash_mmap.h operations...
*/
static const char *TAG = "bootloader_mmap";
@ -82,33 +85,31 @@ void bootloader_munmap(const void *mapping)
esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_decrypt)
{
if (allow_decrypt && esp_flash_encryption_enabled()) {
return spi_flash_read_encrypted(src, dest, size);
return esp_flash_read_encrypted(NULL, src, dest, size);
} else {
return spi_flash_read(src, dest, size);
return esp_flash_read(NULL, dest, src, size);
}
}
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
{
if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) {
#if CONFIG_IDF_TARGET_ESP32
return spi_flash_write_encrypted(dest_addr, src, size);
#else
return esp_rom_spiflash_write_encrypted(dest_addr, src, size);
#endif
return esp_flash_write_encrypted(NULL, dest_addr, src, size);
} else {
return spi_flash_write(dest_addr, src, size);
return esp_flash_write(NULL, src, dest_addr, size);
}
}
esp_err_t bootloader_flash_erase_sector(size_t sector)
{
return spi_flash_erase_sector(sector);
// Will de-dependency IDF-5025
return esp_flash_erase_region(NULL, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
}
esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
{
return spi_flash_erase_range(start_addr, size);
// Will de-dependency IDF-5025
return esp_flash_erase_region(NULL, start_addr, size);
}
#else //BOOTLOADER_BUILD

View File

@ -9,7 +9,7 @@
#include "esp_attr.h"
#include "esp_err.h"
#ifndef BOOTLOADER_BUILD
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#endif
#include "hal/efuse_ll.h"
#include "sdkconfig.h"

View File

@ -11,7 +11,7 @@
#include <esp_fault.h>
#include <esp_log.h>
#include <esp_attr.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <bootloader_flash_priv.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>

View File

@ -11,7 +11,7 @@
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_fault.h"
#include "esp32/rom/sha.h"
#include "uECC_verify_antifault.h"

View File

@ -26,7 +26,7 @@
#include "test/test_common_spi.h"
#include "soc/gpio_periph.h"
#include "sdkconfig.h"
#include "../cache_utils.h"
#include "esp_private/cache_utils.h"
#include "soc/soc_memory_layout.h"
#include "esp_private/spi_common_internal.h"
#include "esp_private/esp_clk.h"

View File

@ -29,8 +29,9 @@
#include "sdkconfig.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_attr.h"
#include "esp_private/spi_flash_os.h"
// Enable internal routing for the output and input gpio pins
#define TEST_GPIO_INTERNAL_ROUTING 1

View File

@ -11,7 +11,8 @@
#include "freertos/semphr.h"
#include "unity.h"
#include "driver/gptimer.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_flash.h"
#include "soc/soc_caps.h"
#if CONFIG_GPTIMER_ISR_IRAM_SAFE
@ -41,7 +42,7 @@ static void flash_read_task(void *varg)
{
read_task_arg_t *arg = (read_task_arg_t *)varg;
for (size_t i = 0; i < arg->repeat_count; i++) {
TEST_ESP_OK(spi_flash_read(arg->flash_addr, arg->buf, arg->buf_size));
TEST_ESP_OK(esp_flash_read(NULL, arg->buf, arg->flash_addr, arg->buf_size));
}
xSemaphoreGive(arg->done_sem);
vTaskDelete(NULL);

View File

@ -11,10 +11,10 @@
#include "freertos/semphr.h"
#include "unity.h"
#include "driver/i2s_std.h"
#include "esp_spi_flash.h"
#include "esp_attr.h"
#include "soc/soc_caps.h"
#include "esp_private/i2s_platform.h"
#include "esp_private/spi_flash_os.h"
#include "test_inc/test_i2s.h"
#if CONFIG_I2S_ISR_IRAM_SAFE

View File

@ -12,9 +12,10 @@
#include "unity.h"
#include "driver/pulse_cnt.h"
#include "driver/gpio.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_attr.h"
#include "soc/soc_caps.h"
#include "esp_private/spi_flash_os.h"
#include "test_pulse_cnt_board.h"
#if CONFIG_PCNT_ISR_IRAM_SAFE

View File

@ -47,9 +47,6 @@
#if __has_include("esp_ping.h")
#include "esp_ping.h"
#endif
#if __has_include("esp_spi_flash.h")
#include "esp_spi_flash.h"
#endif
#if __has_include("esp_tls_errors.h")
#include "esp_tls_errors.h"
#endif
@ -71,6 +68,9 @@
#if __has_include("soc/esp32s2/esp_ds.h")
#include "soc/esp32s2/esp_ds.h"
#endif
#if __has_include("spi_flash_mmap.h")
#include "spi_flash_mmap.h"
#endif
#if __has_include("ulp_fsm_common.h")
#include "ulp_fsm_common.h"
#endif
@ -565,7 +565,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# ifdef ESP_ERR_FLASH_BASE
ERR_TBL_IT(ESP_ERR_FLASH_BASE), /* 24576 0x6000 Starting number of flash error codes */
# endif
// components/spi_flash/include/esp_spi_flash.h
// components/spi_flash/include/spi_flash_mmap.h
# ifdef ESP_ERR_FLASH_OP_FAIL
ERR_TBL_IT(ESP_ERR_FLASH_OP_FAIL), /* 24577 0x6001 */
# endif

View File

@ -9,7 +9,9 @@
#include "soc/dport_reg.h"
#include "esp_attr.h"
#include "string.h"
#include "esp_spi_flash.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/cache_utils.h"
#include "spi_flash_mmap.h"
//Errors that can be returned
#define MMU_SET_ADDR_ALIGNED_ERROR 1

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -19,7 +19,7 @@ This code tests the interaction between PSRAM and SPI flash routines.
#include <stdio.h>
#include <string.h>
#include "esp_heap_caps.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_partition.h"
#include "test_utils.h"
#include "soc/soc.h"

View File

@ -12,8 +12,9 @@
#include "esp_lcd_panel_ops.h"
#include "esp_random.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "test_rgb_board.h"
#include "esp_private/spi_flash_os.h"
#if CONFIG_LCD_RGB_ISR_IRAM_SAFE
#define TEST_LCD_CALLBACK_ATTR IRAM_ATTR

View File

@ -12,8 +12,9 @@
#include "freertos/semphr.h"
#include "freertos/ringbuf.h"
#include "driver/gptimer.h"
#include "esp_private/spi_flash_os.h"
#include "esp_heap_caps.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "unity.h"
#include "test_utils.h"
#include "esp_rom_sys.h"

View File

@ -43,6 +43,7 @@ PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency );
PROVIDE( esp_rom_spiflash_attach = spi_flash_attach );
PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock );
PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable);
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );
PROVIDE ( esp_rom_regi2c_read = rom_i2c_readReg );
PROVIDE ( esp_rom_regi2c_read_mask = rom_i2c_readReg_Mask );

View File

@ -45,6 +45,7 @@ PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency );
PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock );
PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable );
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );
PROVIDE ( esp_rom_regi2c_read = rom_i2c_readReg );
PROVIDE ( esp_rom_regi2c_read_mask = rom_i2c_readReg_Mask );

View File

@ -48,6 +48,7 @@ PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency );
PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock );
PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable);
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );
PROVIDE ( esp_rom_regi2c_read = rom_i2c_readReg );
PROVIDE ( esp_rom_regi2c_read_mask = rom_i2c_readReg_Mask );

View File

@ -48,6 +48,7 @@ PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency );
PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock );
PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable);
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );
PROVIDE ( esp_rom_regi2c_read = rom_i2c_readReg );
PROVIDE ( esp_rom_regi2c_read_mask = rom_i2c_readReg_Mask );

View File

@ -23,3 +23,4 @@ PROVIDE ( esp_rom_spiflash_wait_idle = SPI_Wait_Idle );
PROVIDE ( esp_rom_spiflash_config_readmode = SPIReadModeCnfig );
PROVIDE ( esp_rom_spiflash_erase_block = SPIEraseBlock );
PROVIDE ( esp_rom_spiflash_write_encrypted = SPI_Encrypt_Write );
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );

View File

@ -49,6 +49,7 @@ PROVIDE ( esp_rom_get_cpu_ticks_per_us = ets_get_cpu_frequency );
PROVIDE( esp_rom_spiflash_attach = spi_flash_attach );
PROVIDE ( esp_rom_spiflash_clear_bp = esp_rom_spiflash_unlock );
PROVIDE ( esp_rom_spiflash_write_enable = SPI_write_enable);
PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea );
PROVIDE ( esp_rom_regi2c_read = rom_i2c_readReg );
PROVIDE ( esp_rom_regi2c_read_mask = rom_i2c_readReg_Mask );

View File

@ -1,22 +1,15 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "esp_err.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_private/cache_utils.h"
#include "esp_rom_sys.h"

View File

@ -6,7 +6,7 @@
#include <stdio.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/extmem_reg.h"
#include "esp_private/panic_internal.h"

View File

@ -72,7 +72,7 @@
#include "soc/periph_defs.h"
#include "esp_cpu.h"
#include "esp_private/esp_clk.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#if CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX || CONFIG_ESP32S3_TRAX
#include "esp_private/trax.h"

View File

@ -6,9 +6,10 @@
#include <stdlib.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_ipc_isr.h"
#include "esp_private/system_internal.h"
#include "esp_private/cache_utils.h"
#include "soc/soc_memory_layout.h"
#include "esp_cpu.h"

View File

@ -23,7 +23,7 @@
#include "esp_system.h"
#include "esp_log.h"
#include "esp_heap_caps_init.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_flash_internal.h"
#include "esp_newlib.h"
#include "esp_timer.h"
@ -289,9 +289,9 @@ static void do_core_init(void)
err = esp_pthread_init();
assert(err == ESP_OK && "Failed to init pthread module!");
spi_flash_init();
/* init default OS-aware flash access critical section */
spi_flash_guard_set(&g_flash_guard_default_ops);
#if CONFIG_SPI_FLASH_ROM_IMPL
spi_flash_rom_impl_init();
#endif
esp_flash_app_init();
esp_err_t flash_ret = esp_flash_init_default_chip();

View File

@ -6,8 +6,9 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_rom_sys.h"
#include "esp_private/spi_flash_os.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h" // for ETSTimer type
#elif CONFIG_IDF_TARGET_ESP32S2

View File

@ -7,7 +7,7 @@
#include "esp_attr.h"
#include "esp_partition.h"
#include "esp_ota_ops.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_flash_encrypt.h"
#include "sdkconfig.h"
#include "core_dump_checksum.h"

View File

@ -11,6 +11,7 @@
#include "esp_flash_internal.h"
#include "esp_flash_encrypt.h"
#include "esp_rom_crc.h"
#include "esp_private/spi_flash_os.h"
#define BLANK_COREDUMP_SIZE 0xFFFFFFFF
@ -41,15 +42,9 @@ typedef struct _core_dump_flash_config_t
/* Core dump flash data. */
static core_dump_flash_config_t s_core_flash_config;
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) spi_flash_write(_off_, _data_, _len_)
#define ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(_off_, _data_, _len_) spi_flash_write_encrypted(_off_, _data_, _len_)
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) spi_flash_erase_range(_off_, _len_)
#else
#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) esp_flash_write(esp_flash_default_chip, _data_, _off_, _len_)
#define ESP_COREDUMP_FLASH_WRITE_ENCRYPTED(_off_, _data_, _len_) esp_flash_write_encrypted(esp_flash_default_chip, _off_, _data_, _len_)
#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
#endif
esp_err_t esp_core_dump_image_check(void);
static esp_err_t esp_core_dump_partition_and_size_get(const esp_partition_t **partition, uint32_t* size);

View File

@ -9,8 +9,6 @@
#define CONFIG_PARTITION_TABLE_OFFSET 0x8000
#define CONFIG_ESPTOOLPY_FLASHSIZE "8MB"
//currently use the legacy implementation, since the stubs for new HAL are not done yet
#define CONFIG_SPI_FLASH_USE_LEGACY_IMPL 1
#define CONFIG_FATFS_VOLUME_COUNT 2
#define CONFIG_MMU_PAGE_SIZE 0X10000 // 64KB

View File

@ -7,7 +7,7 @@
#include "unity.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include <stdlib.h>
#include <sys/param.h>
#include <string.h>

View File

@ -7,8 +7,9 @@
#include "unity.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_memory_utils.h"
#include "esp_private/spi_flash_os.h"
#include <stdlib.h>
#include <sys/param.h>

View File

@ -7,8 +7,9 @@
#include <string.h>
#include <sys/param.h>
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/soc_memory_layout.h"
#include "esp_private/cache_utils.h"
#define ASSERT_STR "assert failed: "
#define CACHE_DISABLED_STR "<cached disabled>"

View File

@ -8,7 +8,7 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "hal/cpu_hal.h"
#include "../cache_utils.h"
#include "esp_private/cache_utils.h"
#define RECORD_TIME_PREPARE() uint32_t __t1, __t2
#define RECORD_TIME_START() do {__t1 = cpu_hal_get_cycle_count();}while(0)

View File

@ -12,7 +12,7 @@
#include <type_traits>
#include <cstring>
#include <algorithm>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "compressed_enum_table.hpp"
#include "intrusive_list.h"
#include "nvs_item_hash_list.hpp"

View File

@ -1,6 +1,4 @@
#define CONFIG_NVS_ENCRYPTION 1
//currently use the legacy implementation, since the stubs for new HAL are not done yet
#define CONFIG_SPI_FLASH_USE_LEGACY_IMPL 1
#define CONFIG_LOG_MAXIMUM_LEVEL 3
#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1
#define CONFIG_IDF_TARGET_LINUX 1

View File

@ -1,16 +1,8 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef spi_flash_emulation_h
#define spi_flash_emulation_h
@ -18,7 +10,7 @@
#include <cassert>
#include <algorithm>
#include <random>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "catch.hpp"
using std::copy;

View File

@ -1,18 +1,10 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "catch.hpp"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_partition.h"
#include "spi_flash_emulation.h"
#include <functional>

View File

@ -22,6 +22,7 @@ else()
"flash_ops.c"
"${target}/flash_ops_${target}.c"
)
set(srcs
"partition.c"
"partition_target.c"

View File

@ -100,19 +100,10 @@ menu "SPI Flash driver"
bool "Allowed"
endchoice
config SPI_FLASH_USE_LEGACY_IMPL
bool "Use the legacy implementation before IDF v4.0"
default n
help
The implementation of SPI flash has been greatly changed in IDF v4.0.
Enable this option to use the legacy implementation.
config SPI_FLASH_SHARE_SPI1_BUS
bool "Support other devices attached to SPI1 bus"
default n
# The bus lock on SPI1 is meaningless when the legacy implementation is used, or the SPI
# driver does not support SPI1.
depends on !SPI_FLASH_USE_LEGACY_IMPL && !IDF_TARGET_ESP32S2
depends on !IDF_TARGET_ESP32S2
help
Each SPI bus needs a lock for arbitration among devices. This allows multiple
devices on a same bus, but may reduce the speed of esp_flash driver access to the
@ -160,7 +151,7 @@ menu "SPI Flash driver"
config SPI_FLASH_AUTO_SUSPEND
bool "Auto suspend long erase/write operations (READ DOCS FIRST)"
default n
depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_USE_LEGACY_IMPL && !SPI_FLASH_ROM_IMPL
depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_ROM_IMPL
help
This option is default n before ESP32-C3, because it needs bootloader support.
@ -191,14 +182,12 @@ menu "SPI Flash driver"
config SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
bool "Flash timeout checkout disabled"
depends on !SPI_FLASH_USE_LEGACY_IMPL
default n
help
This option is helpful if you are using a flash chip whose timeout is quite large or unpredictable.
config SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST
bool "Override default chip driver list"
depends on !SPI_FLASH_USE_LEGACY_IMPL
default n
help
This option allows the chip driver list to be customized, instead of using the default list provided by

View File

@ -1,3 +1 @@
See the spi_flash.rst in the programming guide folder for more details.
The docs above is for the new SPI Flash API above 4.0, for legacy implementation (CONFIG_SPI_FLASH_USE_LEGACY_IMPL enabled), read README_legayc.rst in the same folder with this readme.

View File

@ -1,108 +0,0 @@
SPI Flash API (Legacy)
========================
Overview
--------
This is the readme for the APIs before IDF v4.0. Enable the kconfig option ``SPI_FLASH_USE_LEGACY_IMPL`` to use the
legacy implementation.
The spi_flash component contains API functions related to reading, writing, erasing, memory mapping for data in the external SPI flash. The spi_flash component also has higher-level API functions which work with partitions defined in the :doc:`partition table </api-guides/partition-tables>`.
Note that all the functionality is limited to the "main" SPI flash chip, the same SPI flash chip from which programs are runs. For ``spi_flash_*`` functions, this is a software limitation. The underlying ROM functions which work with SPI flash do not have provisions for working with flash chips attached to SPI peripherals other than SPI0.
SPI flash access API
--------------------
This is the set of API functions for working with data in flash:
- :cpp:func:`spi_flash_read` reads data from flash to RAM
- :cpp:func:`spi_flash_write` writes data from RAM to flash
- :cpp:func:`spi_flash_erase_sector` erases individual sectors of flash
- :cpp:func:`spi_flash_erase_range` erases ranges of addresses in flash
- :cpp:func:`spi_flash_get_chip_size` returns flash chip size, in bytes, as configured in menuconfig
Generally, try to avoid using the raw SPI flash functions in favor of :ref:`partition-specific functions <flash-partition-apis>`.
SPI Flash Size
--------------
The SPI flash size is configured by writing a field in the software bootloader image header, flashed at offset 0x1000.
By default, the SPI flash size is detected by esptool.py when this bootloader is written to flash, and the header is updated with the correct size. Alternatively, it is possible to generate a fixed flash size by setting :ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in project configuration.
If it is necessary to override the configured flash size at runtime, it is possible to set the ``chip_size`` member of the ``g_rom_flashchip`` structure. This size is used by ``spi_flash_*`` functions (in both software & ROM) to check the bounds.
Concurrency Constraints
-----------------------
Because the SPI flash is also used for firmware execution via the instruction & data caches, these caches must be disabled while reading/writing/erasing. This means that both CPUs must be running code from IRAM and must only be reading data from DRAM while flash write operations occur.
If you use the API functions documented here, then these constraints are applied automatically and transparently. However, note that it will have some performance impact on other tasks in the system.
For differences between IRAM, DRAM, and flash cache, please refer to the :ref:`application memory layout <memory-layout>` documentation.
To avoid reading flash cache accidentally, when one CPU initiates a flash write or erase operation, the other CPU is put into a blocked state, and all non-IRAM-safe interrupts are disabled on both CPUs until the flash operation completes.
If one CPU initiates a flash write or erase operation, the other CPU is put into a blocked state to avoid reading flash cache accidentally. All interrupts not safe for IRAM are disabled on both CPUs until the flash operation completes.
.. _iram-safe-interrupt-handlers:
IRAM-Safe Interrupt Handlers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have an interrupt handler that you want to execute while a flash operation is in progress (for example, for low latency operations), set the ``ESP_INTR_FLAG_IRAM`` flag when the :doc:`interrupt handler is registered </api-reference/system/intr_alloc>`.
You must ensure that all data and functions accessed by these interrupt handlers, including the ones that handlers call, are located in IRAM or DRAM. See :ref:`how-to-place-code-in-iram`.
If a function or symbol is not correctly put into IRAM/DRAM, and the interrupt handler reads from the flash cache during a flash operation, it will cause a crash due to Illegal Instruction exception (for code which should be in IRAM) or garbage data to be read (for constant data which should be in DRAM).
.. _flash-partition-apis:
Partition table API
-------------------
ESP-IDF projects use a partition table to maintain information about various regions of SPI flash memory (bootloader, various application binaries, data, filesystems). More information on partition tables can be found :doc:`here </api-guides/partition-tables>`.
This component provides API functions to enumerate partitions found in the partition table and perform operations on them. These functions are declared in ``esp_partition.h``:
- :cpp:func:`esp_partition_find` checks a partition table for entries with specific type, returns an opaque iterator.
- :cpp:func:`esp_partition_get` returns a structure describing the partition for a given iterator.
- :cpp:func:`esp_partition_next` shifts the iterator to the next found partition.
- :cpp:func:`esp_partition_iterator_release` releases iterator returned by ``esp_partition_find``.
- :cpp:func:`esp_partition_find_first` - a convenience function which returns the structure describing the first partition found by ``esp_partition_find``.
- :cpp:func:`esp_partition_read`, :cpp:func:`esp_partition_write`, :cpp:func:`esp_partition_erase_range` are equivalent to :cpp:func:`spi_flash_read`, :cpp:func:`spi_flash_write`, :cpp:func:`spi_flash_erase_range`, but operate within partition boundaries.
.. note::
Application code should mostly use these ``esp_partition_*`` API functions instead of lower level ``spi_flash_*`` API functions. Partition table API functions do bounds checking and calculate correct offsets in flash, based on data stored in a partition table.
SPI Flash Encryption
--------------------
It is possible to encrypt the contents of SPI flash and have it transparently decrypted by hardware.
Refer to the :doc:`Flash Encryption documentation </security/flash-encryption>` for more details.
Memory mapping API
------------------
ESP32 features memory hardware which allows regions of flash memory to be mapped into instruction and data address spaces. This mapping works only for read operations. It is not possible to modify contents of flash memory by writing to a mapped memory region.
Mapping happens in 64KB pages. Memory mapping hardware can map up to four megabytes of flash into data address space and up to 16 megabytes of flash into instruction address space. See the technical reference manual for more details about memory mapping hardware.
Note that some 64KB pages are used to map the application itself into memory, so the actual number of available 64KB pages may be less.
Reading data from flash using a memory mapped region is the only way to decrypt contents of flash when :doc:`flash encryption </security/flash-encryption>` is enabled. Decryption is performed at the hardware level.
Memory mapping API are declared in ``esp_spi_flash.h`` and ``esp_partition.h``:
- :cpp:func:`spi_flash_mmap` maps a region of physical flash addresses into instruction space or data space of the CPU.
- :cpp:func:`spi_flash_munmap` unmaps previously mapped region.
- :cpp:func:`esp_partition_mmap` maps part of a partition into the instruction space or data space of the CPU.
Differences between :cpp:func:`spi_flash_mmap` and :cpp:func:`esp_partition_mmap` are as follows:
- :cpp:func:`spi_flash_mmap` must be given a 64KB aligned physical address.
- :cpp:func:`esp_partition_mmap` may be given any arbitrary offset within the partition, it will adjust the returned pointer to mapped memory as necessary
Note that since memory mapping happens in 64KB blocks, it may be possible to read data outside of the partition provided to ``esp_partition_mmap``.

View File

@ -44,7 +44,7 @@
#endif
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_log.h"
#include "esp_cpu.h"

View File

@ -3,77 +3,3 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_spi_flash.h"
#include "esp32/rom/cache.h"
#include "esp_rom_spiflash.h"
static inline void IRAM_ATTR spi_flash_guard_start(void)
{
const spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
if (ops && ops->start) {
ops->start();
}
}
static inline void IRAM_ATTR spi_flash_guard_end(void)
{
const spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
if (ops && ops->end) {
ops->end();
}
}
extern void IRAM_ATTR flash_rom_init(void);
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
{
const uint8_t *ssrc = (const uint8_t *)src;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
assert((dest_addr % 16) == 0);
assert((size % 16) == 0);
/* esp_rom_spiflash_write_encrypted encrypts data in RAM as it writes,
so copy to a temporary buffer - 32 bytes at a time.
Each call to esp_rom_spiflash_write_encrypted takes a 32 byte "row" of
data to encrypt, and each row is two 16 byte AES blocks
that share a key (as derived from flash address).
*/
uint8_t encrypt_buf[32] __attribute__((aligned(4)));
uint32_t row_size;
for (size_t i = 0; i < size; i += row_size) {
uint32_t row_addr = dest_addr + i;
if (i == 0 && (row_addr % 32) != 0) {
/* writing to second block of a 32 byte row */
row_size = 16;
row_addr -= 16;
/* copy to second block in buffer */
memcpy(encrypt_buf + 16, ssrc + i, 16);
/* decrypt the first block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr, encrypt_buf, 16);
} else if (size - i == 16) {
/* 16 bytes left, is first block of a 32 byte row */
row_size = 16;
/* copy to first block in buffer */
memcpy(encrypt_buf, ssrc + i, 16);
/* decrypt the second block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr + 16, encrypt_buf + 16, 16);
} else {
/* Writing a full 32 byte row (2 blocks) */
row_size = 32;
memcpy(encrypt_buf, ssrc + i, 32);
}
spi_flash_guard_start();
flash_rom_init();
rc = esp_rom_spiflash_write_encrypted(row_addr, (uint32_t *)encrypt_buf, 32);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
}
bzero(encrypt_buf, sizeof(encrypt_buf));
return rc;
}

View File

@ -7,7 +7,7 @@
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32c2/rom/cache.h"
@ -16,61 +16,11 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
static const char *TAG = "spiflash_esp32c2";
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
extern void IRAM_ATTR flash_rom_init(void);
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);
/* src needs to be 32 bit aligned */
if (!esp_ptr_internal(src) || (intptr_t)src & 0x3) {
WORD_ALIGNED_ATTR 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();
}
flash_rom_init();
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)
{

View File

@ -7,7 +7,7 @@
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32c3/rom/cache.h"
@ -16,61 +16,11 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
static const char *TAG = "spiflash_c3";
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
extern void IRAM_ATTR flash_rom_init(void);
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);
/* src needs to be 32 bit aligned */
if (!esp_ptr_internal(src) || (intptr_t)src & 0x3) {
WORD_ALIGNED_ATTR 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();
}
flash_rom_init();
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)
{

View File

@ -7,7 +7,7 @@
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32h2/rom/cache.h"
@ -16,61 +16,11 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_spiflash.h"
static const char *TAG = "spiflash_h2";
#include "esp_private/spi_flash_os.h"
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
extern void IRAM_ATTR flash_rom_init(void);
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);
/* src needs to be 32 bit aligned */
if (!esp_ptr_internal(src) || (intptr_t)src & 0x3) {
WORD_ALIGNED_ATTR 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();
}
flash_rom_init();
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)
{

View File

@ -7,7 +7,7 @@
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s2/rom/cache.h"
@ -17,60 +17,9 @@
#include "esp_log.h"
#include "esp_rom_spiflash.h"
static const char *TAG = "spiflash_s2";
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
extern void IRAM_ATTR flash_rom_init(void);
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 SPI_Encrypt_Write 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();
}
flash_rom_init();
rc = esp_rom_spiflash_write_encrypted(dest_addr, (uint32_t*)src, size);
if (ops && ops->end) {
ops->end();
}
return rc;
}
}
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
return bootloader_flash_wrap_set(mode);

View File

@ -7,7 +7,7 @@
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s3/rom/cache.h"
@ -17,59 +17,9 @@
#include "esp_log.h"
#include "esp_rom_spiflash.h"
static const char *TAG = "spiflash_s3";
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
extern void IRAM_ATTR flash_rom_init(void);
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 SPI_Encrypt_Write 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();
}
flash_rom_init();
rc = esp_rom_spiflash_write_encrypted(dest_addr, (void *)src, size);
if (ops && ops->end) {
ops->end();
}
return rc;
}
}
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
return bootloader_flash_wrap_set(mode);

View File

@ -16,6 +16,7 @@
#include "sdkconfig.h"
#include "esp_flash_internal.h"
#include "spi_flash_defs.h"
#include "spi_flash_mmap.h"
#include "esp_rom_caps.h"
#include "esp_rom_spiflash.h"
#if CONFIG_IDF_TARGET_ESP32S2
@ -1051,19 +1052,32 @@ inline static IRAM_ATTR bool regions_overlap(uint32_t a_start, uint32_t a_len,ui
return (a_end > b_start && b_end > a_start);
}
//currently the legacy implementation is used, from flash_ops.c
esp_err_t spi_flash_read_encrypted(size_t src, void *dstv, size_t size);
esp_err_t IRAM_ATTR esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length)
{
/*
* Since currently this feature is supported only by the hardware, there
* is no way to support non-standard chips. We use the legacy
* implementation and skip the chip and driver layers.
*/
esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip);
if (err != ESP_OK) return err;
return spi_flash_read_encrypted(address, out_buffer, length);
if (address + length > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_SIZE;
}
if (length == 0) {
return ESP_OK;
}
if (out_buffer == NULL) {
return ESP_ERR_INVALID_ARG;
}
const uint8_t *map;
spi_flash_mmap_handle_t map_handle;
size_t map_src = address & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
size_t map_size = length + (address - map_src);
err = spi_flash_mmap(map_src, map_size, SPI_FLASH_MMAP_DATA, (const void **)&map, &map_handle);
if (err != ESP_OK) {
return err;
}
memcpy(out_buffer, map + (address - map_src), length);
spi_flash_munmap(map_handle);
return err;
}
// test only, non-public
@ -1115,7 +1129,6 @@ esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip)
return chip->chip_drv->sus_setup(chip);
}
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
esp_err_t esp_flash_app_disable_protect(bool disable)
{
if (disable) {
@ -1124,65 +1137,3 @@ esp_err_t esp_flash_app_disable_protect(bool disable)
return esp_flash_app_enable_os_functions(esp_flash_default_chip);
}
}
#endif
/*------------------------------------------------------------------------------
Adapter layer to original api before IDF v4.0
------------------------------------------------------------------------------*/
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
/* Translate any ESP_ERR_FLASH_xxx error code (new API) to a generic ESP_ERR_xyz error code
*/
static IRAM_ATTR esp_err_t spi_flash_translate_rc(esp_err_t err)
{
switch (err) {
case ESP_OK:
case ESP_ERR_INVALID_ARG:
case ESP_ERR_INVALID_SIZE:
case ESP_ERR_NO_MEM:
return err;
case ESP_ERR_FLASH_NOT_INITIALISED:
case ESP_ERR_FLASH_PROTECTED:
return ESP_ERR_INVALID_STATE;
case ESP_ERR_NOT_FOUND:
case ESP_ERR_FLASH_UNSUPPORTED_HOST:
case ESP_ERR_FLASH_UNSUPPORTED_CHIP:
return ESP_ERR_NOT_SUPPORTED;
case ESP_ERR_FLASH_NO_RESPONSE:
return ESP_ERR_INVALID_RESPONSE;
default:
ESP_EARLY_LOGE(TAG, "unexpected spi flash error code: 0x%x", err);
abort();
}
}
esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
{
esp_err_t err = esp_flash_erase_region(NULL, start_addr, size);
return spi_flash_translate_rc(err);
}
esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
{
esp_err_t err = esp_flash_write(NULL, srcv, dst, size);
return spi_flash_translate_rc(err);
}
esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
{
esp_err_t err = esp_flash_read(NULL, dstv, src, size);
return spi_flash_translate_rc(err);
}
esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
{
esp_err_t err = esp_flash_write_encrypted(NULL, dest_addr, src, size);
return spi_flash_translate_rc(err);
}
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL

View File

@ -20,6 +20,8 @@
#include "esp_flash_internal.h"
#include "esp_rom_gpio.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/cache_utils.h"
#include "esp_spi_flash_counters.h"
#include "esp_rom_spiflash.h"
__attribute__((unused)) static const char TAG[] = "spi_flash";
@ -29,8 +31,6 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
esp_flash_t *esp_flash_default_chip = NULL;
#endif
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#if defined CONFIG_ESPTOOLPY_FLASHFREQ_120M
#define DEFAULT_FLASH_SPEED 120
#elif defined CONFIG_ESPTOOLPY_FLASHFREQ_80M
@ -387,6 +387,11 @@ esp_err_t esp_flash_init_default_chip(void)
esp_err_t esp_flash_app_init(void)
{
esp_err_t err = ESP_OK;
spi_flash_init_lock();
spi_flash_guard_set(&g_flash_guard_default_ops);
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
spi_flash_reset_counters();
#endif
#if CONFIG_SPI_FLASH_SHARE_SPI1_BUS
err = esp_flash_init_main_bus_lock();
if (err != ESP_OK) return err;
@ -394,5 +399,3 @@ esp_err_t esp_flash_app_init(void)
err = esp_flash_app_enable_os_functions(&default_chip);
return err;
}
#endif //!CONFIG_SPI_FLASH_USE_LEGACY_IMPL

View File

@ -15,11 +15,12 @@
#include "soc/mmu.h"
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_flash_encrypt.h"
#include "esp_log.h"
#include "cache_utils.h"
#include "esp_private/cache_utils.h"
#include "hal/mmu_ll.h"
#include "esp_rom_spiflash.h"
#if CONFIG_IDF_TARGET_ESP32
#include "soc/dport_reg.h"
@ -129,7 +130,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_
if (src_addr & INVALID_PHY_PAGE(CONFIG_MMU_PAGE_SIZE)) {
return ESP_ERR_INVALID_ARG;
}
if ((src_addr + size) > spi_flash_get_chip_size()) {
if ((src_addr + size) > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_ARG;
}
// region which should be mapped
@ -162,7 +163,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
return ESP_ERR_INVALID_ARG;
}
for (int i = 0; i < page_count; i++) {
if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= spi_flash_get_chip_size()) {
if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_ARG;
}
}

View File

@ -17,7 +17,7 @@
#include <soc/soc_memory_layout.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_log.h"
#include "esp_private/system_internal.h"
#include "esp_private/spi_flash_os.h"
@ -41,14 +41,12 @@
#endif
#include "esp_rom_spiflash.h"
#include "esp_flash_partitions.h"
#include "cache_utils.h"
#include "esp_private/cache_utils.h"
#include "esp_flash.h"
#include "esp_attr.h"
#include "bootloader_flash.h"
#include "esp_compiler.h"
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size);
/* bytes erased by SPIEraseBlock() ROM function */
#define BLOCK_ERASE_SIZE 65536
@ -87,34 +85,29 @@ static spi_flash_counters_t s_flash_stats;
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
#if CONFIG_SPI_FLASH_USE_LEGACY_IMPL
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
#endif //CONFIG_SPI_FLASH_USE_LEGACY_IMPL
static bool is_safe_write_address(size_t addr, size_t size);
static void spi_flash_os_yield(void);
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
.end = spi_flash_enable_interrupts_caches_and_other_cpu,
.op_lock = spi_flash_op_lock,
.op_unlock = spi_flash_op_unlock,
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
.is_safe_write_address = is_safe_write_address,
#endif
.yield = spi_flash_os_yield,
};
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
.end = spi_flash_enable_interrupts_caches_no_os,
.op_lock = NULL,
.op_unlock = NULL,
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
.is_safe_write_address = NULL,
#endif
.yield = NULL,
};
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;
}
const spi_flash_guard_funcs_t *IRAM_ATTR spi_flash_guard_get(void)
{
return s_flash_guard_ops;
}
#ifdef CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS
#define UNSAFE_WRITE_ADDRESS abort()
#else
@ -122,20 +115,6 @@ const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
#endif
/* CHECK_WRITE_ADDRESS macro to fail writes which land in the
bootloader, partition table, or running application region.
*/
#if CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
// Following helps in masking "unused variable" warning
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) ({(void) guard;})
#else /* FAILS or ABORTS */
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \
if (guard && guard->is_safe_write_address && !guard->is_safe_write_address(ADDR, SIZE)) { \
return ESP_ERR_INVALID_ARG; \
} \
} while(0)
#endif // CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
static __attribute__((unused)) bool is_safe_write_address(size_t addr, size_t size)
{
if (!esp_partition_main_flash_region_safe(addr, size)) {
@ -146,12 +125,23 @@ static __attribute__((unused)) bool is_safe_write_address(size_t addr, size_t si
#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);
}
void IRAM_ATTR spi_flash_rom_impl_init(void)
{
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
void IRAM_ATTR esp_mspi_pin_init(void)
@ -179,695 +169,6 @@ esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
#endif // CONFIG_ESPTOOLPY_OCT_FLASH
}
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;
}
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;
}
static inline void IRAM_ATTR spi_flash_guard_start(void)
{
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)
{
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)
{
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)
{
const spi_flash_guard_funcs_t *guard = spi_flash_guard_get();
if (guard && guard->op_unlock) {
guard->op_unlock();
}
}
static void IRAM_ATTR spi_flash_os_yield(void)
{
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
if (likely(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) {
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
}
#endif
}
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
{
static bool unlocked = false;
if (!unlocked) {
spi_flash_guard_start();
bootloader_flash_unlock();
spi_flash_guard_end();
unlocked = true;
}
return ESP_ROM_SPIFLASH_RESULT_OK;
}
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
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);
}
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
//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;
}
if (size % SPI_FLASH_SEC_SIZE != 0) {
return ESP_ERR_INVALID_SIZE;
}
if (size + start_addr > spi_flash_get_chip_size()) {
return ESP_ERR_INVALID_SIZE;
}
size_t start = start_addr / SPI_FLASH_SEC_SIZE;
size_t end = start + size / SPI_FLASH_SEC_SIZE;
const size_t sectors_per_block = BLOCK_ERASE_SIZE / SPI_FLASH_SEC_SIZE;
COUNTER_START();
esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
int64_t no_yield_time_us = 0;
#endif
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
int64_t start_time_us = esp_system_get_time();
#endif
spi_flash_guard_start();
#ifndef CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE
if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
sector += sectors_per_block;
COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
} else
#endif
{
rc = esp_rom_spiflash_erase_sector(sector);
++sector;
COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
}
spi_flash_guard_end();
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
no_yield_time_us += (esp_system_get_time() - start_time_us);
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
no_yield_time_us = 0;
if (s_flash_guard_ops && s_flash_guard_ops->yield) {
s_flash_guard_ops->yield();
}
}
#endif
}
}
COUNTER_STOP(erase);
spi_flash_guard_start();
// Ensure WEL is 0 after the operation, even if the erase failed.
esp_rom_spiflash_write_disable();
spi_flash_check_and_flush_cache(start_addr, size);
spi_flash_guard_end();
return spi_flash_translate_rc(rc);
}
/* Wrapper around esp_rom_spiflash_write() that verifies data as written if CONFIG_SPI_FLASH_VERIFY_WRITE is set.
If CONFIG_SPI_FLASH_VERIFY_WRITE is not set, this is esp_rom_spiflash_write().
*/
static IRAM_ATTR esp_rom_spiflash_result_t spi_flash_write_inner(uint32_t target, const uint32_t *src_addr, int32_t len)
{
#ifndef CONFIG_SPI_FLASH_VERIFY_WRITE
return esp_rom_spiflash_write(target, src_addr, len);
#else // CONFIG_SPI_FLASH_VERIFY_WRITE
esp_rom_spiflash_result_t res = ESP_ROM_SPIFLASH_RESULT_OK;
assert(len % sizeof(uint32_t) == 0);
uint32_t before_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM / sizeof(uint32_t)];
uint32_t after_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM / sizeof(uint32_t)];
uint32_t *expected_buf = before_buf;
int32_t remaining = len;
for(int i = 0; i < len; i += sizeof(before_buf)) {
int i_w = i / sizeof(uint32_t); // index in words (i is an index in bytes)
int32_t read_len = MIN(sizeof(before_buf), remaining);
// Read "before" contents from flash
res = esp_rom_spiflash_read(target + i, before_buf, read_len);
if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
int r_w = r / sizeof(uint32_t); // index in words (r is index in bytes)
uint32_t write = src_addr[i_w + r_w];
uint32_t before = before_buf[r_w];
uint32_t expected = write & before;
#ifdef CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
if ((before & write) != write) {
spi_flash_guard_end();
ESP_LOGW(TAG, "Write at offset 0x%x requests 0x%08x but will write 0x%08x -> 0x%08x",
target + i + r, write, before, before & write);
spi_flash_guard_start();
}
#endif
expected_buf[r_w] = expected;
}
res = esp_rom_spiflash_write(target + i, &src_addr[i_w], read_len);
if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
res = esp_rom_spiflash_read(target + i, after_buf, read_len);
if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
int r_w = r / sizeof(uint32_t); // index in words (r is index in bytes)
uint32_t expected = expected_buf[r_w];
uint32_t actual = after_buf[r_w];
if (expected != actual) {
#ifdef CONFIG_SPI_FLASH_LOG_FAILED_WRITE
spi_flash_guard_end();
ESP_LOGE(TAG, "Bad write at offset 0x%x expected 0x%08x readback 0x%08x", target + i + r, expected, actual);
spi_flash_guard_start();
#endif
res = ESP_ROM_SPIFLASH_RESULT_ERR;
}
}
if (res != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
remaining -= read_len;
}
return res;
#endif // CONFIG_SPI_FLASH_VERIFY_WRITE
}
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
if (dst + size > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_SIZE;
}
if (size == 0) {
return ESP_OK;
}
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
COUNTER_START();
const uint8_t *srcc = (const uint8_t *) srcv;
/*
* Large operations are split into (up to) 3 parts:
* - Left padding: 4 bytes up to the first 4-byte aligned destination offset.
* - Middle part
* - Right padding: 4 bytes from the last 4-byte aligned offset covered.
*/
size_t left_off = dst & ~3U;
size_t left_size = MIN(((dst + 3) & ~3U) - dst, size);
size_t mid_off = left_size;
size_t mid_size = (size - left_size) & ~3U;
size_t right_off = left_size + mid_size;
size_t right_size = size - mid_size - left_size;
rc = spi_flash_unlock();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
if (left_size > 0) {
uint32_t t = 0xffffffff;
memcpy(((uint8_t *) &t) + (dst - left_off), srcc, left_size);
spi_flash_guard_start();
rc = spi_flash_write_inner(left_off, &t, 4);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(write, 4);
}
if (mid_size > 0) {
/* If src buffer is 4-byte aligned as well and is not in a region that requires cache access to be enabled, we
* can write directly without buffering in RAM. */
#ifdef ESP_PLATFORM
bool direct_write = esp_ptr_internal(srcc)
&& esp_ptr_byte_accessible(srcc)
&& ((uintptr_t) srcc + mid_off) % 4 == 0;
#else
bool direct_write = true;
#endif
while(mid_size > 0 && rc == ESP_ROM_SPIFLASH_RESULT_OK) {
uint32_t write_buf[8];
uint32_t write_size = MIN(mid_size, MAX_WRITE_CHUNK);
const uint8_t *write_src = srcc + mid_off;
if (!direct_write) {
write_size = MIN(write_size, sizeof(write_buf));
memcpy(write_buf, write_src, write_size);
write_src = (const uint8_t *)write_buf;
}
spi_flash_guard_start();
rc = spi_flash_write_inner(dst + mid_off, (const uint32_t *) write_src, write_size);
spi_flash_guard_end();
COUNTER_ADD_BYTES(write, write_size);
mid_size -= write_size;
mid_off += write_size;
}
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
}
if (right_size > 0) {
uint32_t t = 0xffffffff;
memcpy(&t, srcc + right_off, right_size);
spi_flash_guard_start();
rc = spi_flash_write_inner(dst + right_off, &t, 4);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(write, 4);
}
out:
COUNTER_STOP(write);
spi_flash_guard_start();
// Ensure WEL is 0 after the operation, even if the write failed.
esp_rom_spiflash_write_disable();
spi_flash_check_and_flush_cache(dst, size);
spi_flash_guard_end();
return spi_flash_translate_rc(rc);
}
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#if !CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#if !CONFIG_ESPTOOLPY_OCT_FLASH // Test for encryption on opi flash, IDF-3852.
extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode);
extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
void IRAM_ATTR flash_rom_init(void)
{
uint32_t freqdiv = 0;
#if CONFIG_IDF_TARGET_ESP32
uint32_t dummy_bit = 0;
#if CONFIG_ESPTOOLPY_FLASHFREQ_80M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_26M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_26M;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
dummy_bit = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
#endif
#endif//CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESPTOOLPY_FLASHFREQ_80M
freqdiv = 1;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
freqdiv = 2;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_26M
freqdiv = 3;
#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
freqdiv = 4;
#endif
#if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32
esp_rom_spiflash_read_mode_t read_mode;
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO
read_mode = ESP_ROM_SPIFLASH_QIO_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_QOUT
read_mode = ESP_ROM_SPIFLASH_QOUT_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_DIO
read_mode = ESP_ROM_SPIFLASH_DIO_MODE;
#elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT
read_mode = ESP_ROM_SPIFLASH_DOUT_MODE;
#endif
#endif //!CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32
g_rom_spiflash_dummy_len_plus[1] = dummy_bit;
#else
spi_dummy_len_fix(1, freqdiv);
#endif //CONFIG_IDF_TARGET_ESP32
#if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32
spi_common_set_dummy_output(read_mode);
#endif //!CONFIG_IDF_TARGET_ESP32S2
esp_rom_spiflash_config_clk(freqdiv, 1);
}
#endif //CONFIG_ESPTOOLPY_OCT_FLASH
#else
void IRAM_ATTR flash_rom_init(void)
{
return;
}
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;
}
if ((size % 16) != 0) {
return ESP_ERR_INVALID_SIZE;
}
COUNTER_START();
esp_rom_spiflash_result_t rc = spi_flash_unlock();
err = spi_flash_translate_rc(rc);
if (err != ESP_OK) {
goto fail;
}
#ifndef CONFIG_SPI_FLASH_VERIFY_WRITE
err = spi_flash_write_encrypted_chip(dest_addr, src, size);
COUNTER_ADD_BYTES(write, size);
spi_flash_guard_start();
esp_rom_spiflash_write_disable();
spi_flash_check_and_flush_cache(dest_addr, size);
spi_flash_guard_end();
#else
const uint32_t* src_w = (const uint32_t*)src;
uint32_t read_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM / sizeof(uint32_t)];
int32_t remaining = size;
for(int i = 0; i < size; i += sizeof(read_buf)) {
int i_w = i / sizeof(uint32_t); // index in words (i is an index in bytes)
int32_t read_len = MIN(sizeof(read_buf), remaining);
// Read "before" contents from flash
esp_err_t err = spi_flash_read(dest_addr + i, read_buf, read_len);
if (err != ESP_OK) {
break;
}
#ifdef CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE
//The written data cannot be predicted, so warning is shown if any of the bits is not 1.
for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
uint32_t before = read_buf[r / sizeof(uint32_t)];
if (before != 0xFFFFFFFF) {
ESP_LOGW(TAG, "Encrypted write at offset 0x%x but not erased (0x%08x)",
dest_addr + i + r, before);
}
}
#endif
err = spi_flash_write_encrypted_chip(dest_addr + i, src + i, read_len);
if (err != ESP_OK) {
break;
}
COUNTER_ADD_BYTES(write, size);
spi_flash_guard_start();
esp_rom_spiflash_write_disable();
spi_flash_check_and_flush_cache(dest_addr, size);
spi_flash_guard_end();
err = spi_flash_read_encrypted(dest_addr + i, read_buf, read_len);
if (err != ESP_OK) {
break;
}
for (int r = 0; r < read_len; r += sizeof(uint32_t)) {
int r_w = r / sizeof(uint32_t); // index in words (r is index in bytes)
uint32_t expected = src_w[i_w + r_w];
uint32_t actual = read_buf[r_w];
if (expected != actual) {
#ifdef CONFIG_SPI_FLASH_LOG_FAILED_WRITE
ESP_LOGE(TAG, "Bad write at offset 0x%x expected 0x%08x readback 0x%08x", dest_addr + i + r, expected, actual);
#endif
err = ESP_FAIL;
}
}
if (err != ESP_OK) {
break;
}
remaining -= read_len;
}
#endif // CONFIG_SPI_FLASH_VERIFY_WRITE
fail:
COUNTER_STOP(write);
return err;
}
esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
{
// Out of bound reads are checked in ROM code, but we can give better
// error code here
if (src + size > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_SIZE;
}
if (size == 0) {
return ESP_OK;
}
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
COUNTER_START();
spi_flash_guard_start();
/* To simplify boundary checks below, we handle small reads separately. */
if (size < 16) {
uint32_t t[6]; /* Enough for 16 bytes + 4 on either side for padding. */
uint32_t read_src = src & ~3U;
uint32_t left_off = src & 3U;
uint32_t read_size = (left_off + size + 3) & ~3U;
rc = esp_rom_spiflash_read(read_src, t, read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, read_size);
#ifdef ESP_PLATFORM
if (esp_ptr_external_ram(dstv)) {
spi_flash_guard_end();
memcpy(dstv, ((uint8_t *) t) + left_off, size);
spi_flash_guard_start();
} else {
memcpy(dstv, ((uint8_t *) t) + left_off, size);
}
#else
memcpy(dstv, ((uint8_t *) t) + left_off, size);
#endif
goto out;
}
uint8_t *dstc = (uint8_t *) dstv;
intptr_t dsti = (intptr_t) dstc;
/*
* Large operations are split into (up to) 3 parts:
* - The middle part: from the first 4-aligned position in src to the first
* 4-aligned position in dst.
*/
size_t src_mid_off = (src % 4 == 0 ? 0 : 4 - (src % 4));
size_t dst_mid_off = (dsti % 4 == 0 ? 0 : 4 - (dsti % 4));
size_t mid_size = (size - MAX(src_mid_off, dst_mid_off)) & ~3U;
/*
* - Once the middle part is in place, src_mid_off bytes from the preceding
* 4-aligned source location are added on the left.
*/
size_t pad_left_src = src & ~3U;
size_t pad_left_size = src_mid_off;
/*
* - Finally, the right part is added: from the end of the middle part to
* the end. Depending on the alignment of source and destination, this may
* be a 4 or 8 byte read from pad_right_src.
*/
size_t pad_right_src = (src + pad_left_size + mid_size) & ~3U;
size_t pad_right_off = (pad_right_src - src);
size_t pad_right_size = (size - pad_right_off);
#ifdef ESP_PLATFORM
bool direct_read = esp_ptr_internal(dstc)
&& esp_ptr_byte_accessible(dstc)
&& ((uintptr_t) dstc + dst_mid_off) % 4 == 0;
#else
bool direct_read = true;
#endif
if (mid_size > 0) {
uint32_t mid_remaining = mid_size;
uint32_t mid_read = 0;
while (mid_remaining > 0) {
uint32_t read_size = MIN(mid_remaining, MAX_READ_CHUNK);
uint32_t read_buf[8];
uint8_t *read_dst_final = dstc + dst_mid_off + mid_read;
uint8_t *read_dst = read_dst_final;
if (!direct_read) {
read_size = MIN(read_size, sizeof(read_buf));
read_dst = (uint8_t *) read_buf;
}
rc = esp_rom_spiflash_read(src + src_mid_off + mid_read,
(uint32_t *) read_dst, read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
mid_remaining -= read_size;
mid_read += read_size;
if (!direct_read) {
spi_flash_guard_end();
memcpy(read_dst_final, read_buf, read_size);
spi_flash_guard_start();
} else if (mid_remaining > 0) {
/* Drop guard momentarily, allows other tasks to preempt */
spi_flash_guard_end();
spi_flash_guard_start();
}
}
COUNTER_ADD_BYTES(read, mid_size);
/*
* If offsets in src and dst are different, perform an in-place shift
* to put destination data into its final position.
* Note that the shift can be left (src_mid_off < dst_mid_off) or right.
*/
if (src_mid_off != dst_mid_off) {
if (!direct_read) {
spi_flash_guard_end();
}
memmove(dstc + src_mid_off, dstc + dst_mid_off, mid_size);
if (!direct_read) {
spi_flash_guard_start();
}
}
}
if (pad_left_size > 0) {
uint32_t t;
rc = esp_rom_spiflash_read(pad_left_src, &t, 4);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, 4);
if (!direct_read) {
spi_flash_guard_end();
}
memcpy(dstc, ((uint8_t *) &t) + (4 - pad_left_size), pad_left_size);
if (!direct_read) {
spi_flash_guard_start();
}
}
if (pad_right_size > 0) {
uint32_t t[2];
int32_t read_size = (pad_right_size <= 4 ? 4 : 8);
rc = esp_rom_spiflash_read(pad_right_src, t, read_size);
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
goto out;
}
COUNTER_ADD_BYTES(read, read_size);
if (!direct_read) {
spi_flash_guard_end();
}
memcpy(dstc + pad_right_off, t, pad_right_size);
if (!direct_read) {
spi_flash_guard_start();
}
}
out:
spi_flash_guard_end();
COUNTER_STOP(read);
return spi_flash_translate_rc(rc);
}
#endif // !CONFIG_SPI_FLASH_USE_LEGACY_IMPL
esp_err_t IRAM_ATTR spi_flash_read_encrypted(size_t src, void *dstv, size_t size)
{
if (src + size > g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_SIZE;
}
if (size == 0) {
return ESP_OK;
}
esp_err_t err;
const uint8_t *map;
spi_flash_mmap_handle_t map_handle;
size_t map_src = src & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
size_t map_size = size + (src - map_src);
err = spi_flash_mmap(map_src, map_size, SPI_FLASH_MMAP_DATA, (const void **)&map, &map_handle);
if (err != ESP_OK) {
return err;
}
memcpy(dstv, map + (src - map_src), size);
spi_flash_munmap(map_handle);
return err;
}
#if CONFIG_SPI_FLASH_USE_LEGACY_IMPL
static esp_err_t IRAM_ATTR spi_flash_translate_rc(esp_rom_spiflash_result_t rc)
{
switch (rc) {
case ESP_ROM_SPIFLASH_RESULT_OK:
return ESP_OK;
case ESP_ROM_SPIFLASH_RESULT_TIMEOUT:
return ESP_ERR_FLASH_OP_TIMEOUT;
case ESP_ROM_SPIFLASH_RESULT_ERR:
default:
return ESP_ERR_FLASH_OP_FAIL;
}
}
#endif //CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
static inline void dump_counter(spi_flash_counter_t *counter, const char *name)
@ -895,11 +196,6 @@ void spi_flash_dump_counters(void)
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
#if CONFIG_SPI_FLASH_USE_LEGACY_IMPL && !CONFIG_IDF_TARGET_ESP32
// TODO esp32s2: Remove once ESP32-S2 & later chips has new SPI Flash API support
esp_flash_t *esp_flash_default_chip = NULL;
#endif
void IRAM_ATTR spi_flash_set_rom_required_regs(void)
{
#if CONFIG_ESPTOOLPY_OCT_FLASH

View File

@ -180,7 +180,7 @@ esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
/** @brief Erase a region of the flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param chip Pointer to identify flash chip. If NULL, esp_flash_default_chip is substituted. Must have been successfully initialised via esp_flash_init()
* @param start Address to start erasing flash. Must be sector aligned.
* @param len Length of region to erase. Must also be sector aligned.
*
@ -200,7 +200,7 @@ esp_err_t esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len
/** @brief Read if the entire chip is write protected
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param chip Pointer to identify flash chip. If NULL, esp_flash_default_chip is substituted. Must have been successfully initialised via esp_flash_init()
* @param[out] write_protected Pointer to boolean, set to the value of the write protect flag.
*
* @note A correct result for this flag depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
@ -212,7 +212,7 @@ esp_err_t esp_flash_get_chip_write_protect(esp_flash_t *chip, bool *write_protec
/** @brief Set write protection for the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param chip Pointer to identify flash chip. If NULL, esp_flash_default_chip is substituted. Must have been successfully initialised via esp_flash_init()
* @param write_protect Boolean value for the write protect flag
*
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
@ -272,7 +272,7 @@ esp_err_t esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_regi
/** @brief Read data from the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param chip Pointer to identify flash chip. If NULL, esp_flash_default_chip is substituted. Must have been successfully initialised via esp_flash_init()
* @param buffer Pointer to a buffer where the data will be read. To get better performance, this should be in the DRAM and word aligned.
* @param address Address on flash to read from. Must be less than chip->size field.
* @param length Length (in bytes) of data to read.
@ -291,7 +291,7 @@ esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint
/** @brief Write data to the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param chip Pointer to identify flash chip. If NULL, esp_flash_default_chip is substituted. Must have been successfully initialised via esp_flash_init()
* @param address Address on flash to write to. Must be previously erased (SPI NOR flash can only write bits 1->0).
* @param buffer Pointer to a buffer with the data to write. To get better performance, this should be in the DRAM and word aligned.
* @param length Length (in bytes) of data to write.
@ -318,7 +318,6 @@ esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t addres
* - ESP_OK: on success
* - ESP_ERR_NOT_SUPPORTED: encrypted write not supported for this chip.
* - ESP_ERR_INVALID_ARG: Either the address, buffer or length is invalid.
* - or other flash error code from spi_flash_write_encrypted().
*/
esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length);
@ -332,7 +331,6 @@ esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const v
* @return
* - ESP_OK: on success
* - ESP_ERR_NOT_SUPPORTED: encrypted read not supported for this chip.
* - or other flash error code from spi_flash_read_encrypted().
*/
esp_err_t esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_buffer, uint32_t length);

View File

@ -24,11 +24,7 @@ extern "C" {
*
* Called by OS startup code. You do not need to call this in your own applications.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_init_default_chip(...) ({ESP_OK;})
#else
esp_err_t esp_flash_init_default_chip(void);
#endif
/**
* Enable OS-level SPI flash protections in IDF
@ -37,11 +33,7 @@ esp_err_t esp_flash_init_default_chip(void);
*
* @return ESP_OK if success, otherwise failed. See return value of ``esp_flash_init_os_functions``.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_app_init(...) ({ESP_OK;})
#else
esp_err_t esp_flash_app_init(void);
#endif
/**
* Disable (or enable) OS-level SPI flash protections in IDF
@ -50,11 +42,7 @@ esp_err_t esp_flash_app_init(void);
*
* @return always ESP_OK.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_app_disable_protect(...) ({ESP_OK;})
#else
esp_err_t esp_flash_app_disable_protect(bool disable);
#endif
/**
* Initialize OS-level functions for a specific chip.

View File

@ -12,7 +12,7 @@
#include <stddef.h>
#include "esp_err.h"
#include "esp_flash.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#ifdef __cplusplus
extern "C" {
@ -229,9 +229,9 @@ esp_err_t esp_partition_read(const esp_partition_t* partition,
* This can be done using esp_partition_erase_range function.
*
* Partitions marked with an encryption flag will automatically be
* written via the spi_flash_write_encrypted() function. If writing to
* written via the esp_flash_write_encrypted() function. If writing to
* an encrypted partition, all write offsets and lengths must be
* multiples of 16 bytes. See the spi_flash_write_encrypted() function
* multiples of 16 bytes. See the esp_flash_write_encrypted() function
* for more details. Unencrypted partitions do not have this
* restriction.
*
@ -403,7 +403,6 @@ bool esp_partition_check_identity(const esp_partition_t* partition_1, const esp_
* @param[out] out_partition Output, if non-NULL, receives the pointer to the resulting esp_partition_t structure
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if CONFIG_CONFIG_SPI_FLASH_USE_LEGACY_IMPL is enabled
* - ESP_ERR_NO_MEM if memory allocation has failed
* - ESP_ERR_INVALID_ARG if the new partition overlaps another partition on the same flash chip
* - ESP_ERR_INVALID_SIZE if the partition doesn't fit into the flash chip size

View File

@ -1,22 +1,20 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_SPI_FLASH_CACHE_UTILS_H
#define ESP_SPI_FLASH_CACHE_UTILS_H
#pragma once
#include "sdkconfig.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* This header file contains declarations of cache manipulation functions
@ -70,5 +68,19 @@ void esp_config_data_cache_mode(void);
esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable);
#endif
/** @brief Check at runtime if flash cache is enabled on both CPUs
*
* @return true if both CPUs have flash cache enabled, false otherwise.
*/
bool spi_flash_cache_enabled(void);
#endif //ESP_SPI_FLASH_CACHE_UTILS_H
/**
* @brief Re-enable cache for the core defined as cpuid parameter.
*
* @param cpuid the core number to enable instruction cache for
*/
void spi_flash_enable_cache(uint32_t cpuid);
#ifdef __cplusplus
}
#endif

View File

@ -139,6 +139,101 @@ esp_err_t spi_flash_enable_high_performance_mode(void);
*/
const spi_flash_hpm_dummy_conf_t *spi_flash_get_dummy(void);
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
/**
* @brief set wrap mode of flash
*
* @param mode: wrap mode support disable, 16 32, 64 byte
*
* @return esp_err_t : ESP_OK for successful.
*
*/
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode);
/**
* @brief SPI flash critical section enter function.
*
*/
typedef void (*spi_flash_guard_start_func_t)(void);
/**
* @brief SPI flash critical section exit function.
*/
typedef void (*spi_flash_guard_end_func_t)(void);
/**
* Structure holding SPI flash access critical sections management functions.
*
* Flash API uses two types of flash access management functions:
* 1) Functions which prepare/restore flash cache and interrupts before calling
* appropriate ROM functions (SPIWrite, SPIRead and SPIEraseBlock):
* - 'start' function should disables flash cache and non-IRAM interrupts and
* is invoked before the call to one of ROM function above.
* - 'end' function should restore state of flash cache and non-IRAM interrupts and
* is invoked after the call to one of ROM function above.
* These two functions are not recursive.
*
* Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called
* from task the functions use OS primitives. When there is no OS at all or when
* it is not guaranteed that OS is functional (accessing flash from exception handler) these
* functions cannot use OS primitives or even does not need them (multithreaded access is not possible).
*
* @note Structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*/
typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start function. */
spi_flash_guard_end_func_t end; /**< critical section end function. */
} spi_flash_guard_funcs_t;
/**
* @brief Sets guard functions to access flash.
*
* @note Pointed structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*
* @param funcs pointer to structure holding flash access guard functions.
*/
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
/**
* @brief Get the guard functions used for flash access
*
* @return The guard functions that were set via spi_flash_guard_set(). These functions
* can be called if implementing custom low-level SPI flash operations.
*/
const spi_flash_guard_funcs_t *spi_flash_guard_get(void);
/**
* @brief Default OS-aware flash access guard functions
*/
extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
/**
* @brief Non-OS flash access guard functions
*
* @note This version of flash guard functions is to be used when no OS is present or from panic handler.
* It does not use any OS primitives and IPC and implies that only calling CPU is active.
*/
extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
/**
* @brief This function is used to re-initialize the flash mmap when using ROM flash
* implementations.
*
* @note Only called in startup. User should not call this function.
*/
void spi_flash_rom_impl_init(void);
#ifdef __cplusplus
}
#endif

View File

@ -1,421 +1,7 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_SPI_FLASH_H
#define ESP_SPI_FLASH_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "sdkconfig.h"
#include "esp_spi_flash_counters.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "sdkconfig.h"
#define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1)
#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2)
#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */
#define SPI_FLASH_MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE /**< Flash cache MMU mapping page size */
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
/**
* @brief set wrap mode of flash
*
* @param mode: wrap mode support disable, 16 32, 64 byte
*
* @return esp_err_t : ESP_OK for successful.
*
*/
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode);
/**
* @brief Initialize SPI flash access driver
*
* This function must be called exactly once, before any other
* spi_flash_* functions are called.
* Currently this function is called from startup code. There is
* no need to call it from application code.
*
*/
void spi_flash_init(void);
/**
* @brief Get flash chip size, as set in binary image header
*
* @note This value does not necessarily match real flash size.
*
* @return size of flash chip, in bytes
*/
size_t spi_flash_get_chip_size(void);
/**
* @brief Erase the Flash sector.
*
* @param sector: Sector number, the count starts at sector 0, 4KB per sector.
*
* @return esp_err_t
*/
esp_err_t spi_flash_erase_sector(size_t sector);
/**
* @brief Erase a range of flash sectors
*
* @param start_address Address where erase operation has to start.
* Must be 4kB-aligned
* @param size Size of erased range, in bytes. Must be divisible by 4kB.
*
* @return esp_err_t
*/
esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
/**
* @brief Write data to Flash.
*
* @note For fastest write performance, write a 4 byte aligned size at a
* 4 byte aligned offset in flash from a source buffer in DRAM. Varying any of
* these parameters will still work, but will be slower due to buffering.
*
* @note Writing more than 8KB at a time will be split into multiple
* write operations to avoid disrupting other tasks in the system.
*
* @param dest_addr Destination address in Flash.
* @param src Pointer to the source buffer.
* @param size Length of data, in bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size);
/**
* @brief Write data encrypted to Flash.
*
* @note Flash encryption must be enabled for this function to work.
*
* @note Flash encryption must be enabled when calling this function.
* If flash encryption is disabled, the function returns
* ESP_ERR_INVALID_STATE. Use esp_flash_encryption_enabled()
* function to determine if flash encryption is enabled.
*
* @note Both dest_addr and size must be multiples of 16 bytes. For
* absolute best performance, both dest_addr and size arguments should
* be multiples of 32 bytes.
*
* @param dest_addr Destination address in Flash. Must be a multiple of 16 bytes.
* @param src Pointer to the source buffer.
* @param size Length of data, in bytes. Must be a multiple of 16 bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
/**
* @brief Read data from Flash.
*
* @note For fastest read performance, all parameters should be
* 4 byte aligned. If source address and read size are not 4 byte
* aligned, read may be split into multiple flash operations. If
* destination buffer is not 4 byte aligned, a temporary buffer will
* be allocated on the stack.
*
* @note Reading more than 16KB of data at a time will be split
* into multiple reads to avoid disruption to other tasks in the
* system. Consider using spi_flash_mmap() to read large amounts
* of data.
*
* @param src_addr source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
*
* @return esp_err_t
*/
esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);
/**
* @brief Read data from Encrypted Flash.
*
* If flash encryption is enabled, this function will transparently decrypt data as it is read.
* If flash encryption is not enabled, this function behaves the same as spi_flash_read().
*
* See esp_flash_encryption_enabled() for a function to check if flash encryption is enabled.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
* @return esp_err_t
*/
esp_err_t spi_flash_read_encrypted(size_t src, void *dest, size_t size);
/**
* @brief Enumeration which specifies memory space requested in an mmap call
*/
typedef enum {
SPI_FLASH_MMAP_DATA, /**< map to data memory (Vaddr0), allows byte-aligned access, 4 MB total */
SPI_FLASH_MMAP_INST, /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total */
} spi_flash_mmap_memory_t;
/**
* @brief Opaque handle for memory region obtained from spi_flash_mmap.
*/
typedef uint32_t spi_flash_mmap_handle_t;
/**
* @brief Map region of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the requested region of flash memory into the address space.
* It may reuse MMU pages which already provide the required mapping.
*
* As with any allocator, if mmap/munmap are heavily used then the address space
* may become fragmented. To troubleshoot issues with page allocation, use
* spi_flash_mmap_dump() function.
*
* @param src_addr Physical address in flash where requested region starts.
* This address *must* be aligned to 64kB boundary
* (SPI_FLASH_MMU_PAGE_SIZE)
* @param size Size of region to be mapped. This size will be rounded
* up to a 64kB boundary
* @param memory Address space where the region should be mapped (data or instruction)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
*/
esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Map sequences of pages of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the indicated pages of flash memory contiguously into address space.
* In this respect, it works in a similar way as spi_flash_mmap() but it allows mapping
* a (maybe non-contiguous) set of pages into a contiguous region of memory.
*
* @param pages An array of numbers indicating the 64kB pages in flash to be mapped
* contiguously into memory. These indicate the indexes of the 64kB pages,
* not the byte-size addresses as used in other functions.
* Array must be located in internal memory.
* @param page_count Number of entries in the pages array
* @param memory Address space where the region should be mapped (instruction or data)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if pages can not be allocated
* - ESP_ERR_INVALID_ARG if pagecount is zero or pages array is not in
* internal memory
*/
esp_err_t spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Release region previously obtained using spi_flash_mmap
*
* @note Calling this function will not necessarily unmap memory region.
* Region will only be unmapped when there are no other handles which
* reference this region. In case of partially overlapping regions
* it is possible that memory will be unmapped partially.
*
* @param handle Handle obtained from spi_flash_mmap
*/
void spi_flash_munmap(spi_flash_mmap_handle_t handle);
/**
* @brief Display information about mapped regions
*
* This function lists handles obtained using spi_flash_mmap, along with range
* of pages allocated to each handle. It also lists all non-zero entries of
* MMU table and corresponding reference counts.
*/
void spi_flash_mmap_dump(void);
/**
* @brief get free pages number which can be mmap
*
* This function will return number of free pages available in mmu table. This could be useful
* before calling actual spi_flash_mmap (maps flash range to DCache or ICache memory) to check
* if there is sufficient space available for mapping.
*
* @param memory memory type of MMU table free page
*
* @return number of free pages which can be mmaped
*/
uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */
/**
* @brief Given a memory address where flash is mapped, return the corresponding physical flash offset.
*
* Cache address does not have have been assigned via spi_flash_mmap(), any address in memory mapped flash space can be looked up.
*
* @param cached Pointer to flashed cached memory.
*
* @return
* - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
* - Otherwise, returns physical offset in flash
*/
size_t spi_flash_cache2phys(const void *cached);
/** @brief Given a physical offset in flash, return the address where it is mapped in the memory space.
*
* Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
*
* @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries
* point to the same physical address, there may be more than one cache address corresponding to that physical
* address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
*
* @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and
* phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
*
* @param phys_offs Physical offset in flash memory to look up.
* @param memory Address space type to look up a flash cache address mapping for (instruction or data)
*
* @return
* - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
* - Cached memory address (in IROM or DROM space) corresponding to phys_offs.
*/
const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory);
/** @brief Check at runtime if flash cache is enabled on both CPUs
*
* @return true if both CPUs have flash cache enabled, false otherwise.
*/
bool spi_flash_cache_enabled(void);
/**
* @brief Re-enable cache for the core defined as cpuid parameter.
*
* @param cpuid the core number to enable instruction cache for
*/
void spi_flash_enable_cache(uint32_t cpuid);
/**
* @brief SPI flash critical section enter function.
*
*/
typedef void (*spi_flash_guard_start_func_t)(void);
/**
* @brief SPI flash critical section exit function.
*/
typedef void (*spi_flash_guard_end_func_t)(void);
/**
* @brief SPI flash operation lock function.
*/
typedef void (*spi_flash_op_lock_func_t)(void);
/**
* @brief SPI flash operation unlock function.
*/
typedef void (*spi_flash_op_unlock_func_t)(void);
/**
* @brief Function to protect SPI flash critical regions corruption.
*/
typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
/**
* @brief Function to yield to the OS during erase operation.
*/
typedef void (*spi_flash_os_yield_t)(void);
/**
* Structure holding SPI flash access critical sections management functions.
*
* Flash API uses two types of flash access management functions:
* 1) Functions which prepare/restore flash cache and interrupts before calling
* appropriate ROM functions (SPIWrite, SPIRead and SPIEraseBlock):
* - 'start' function should disables flash cache and non-IRAM interrupts and
* is invoked before the call to one of ROM function above.
* - 'end' function should restore state of flash cache and non-IRAM interrupts and
* is invoked after the call to one of ROM function above.
* These two functions are not recursive.
* 2) Functions which synchronizes access to internal data used by flash API.
* This functions are mostly intended to synchronize access to flash API internal data
* in multithreaded environment and use OS primitives:
* - 'op_lock' locks access to flash API internal data.
* - 'op_unlock' unlocks access to flash API internal data.
* These two functions are recursive and can be used around the outside of multiple calls to
* 'start' & 'end', in order to create atomic multi-part flash operations.
* 3) When CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is disabled, flash writing/erasing
* API checks for addresses provided by user to avoid corruption of critical flash regions
* (bootloader, partition table, running application etc.).
*
* Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called
* from task the functions use OS primitives. When there is no OS at all or when
* it is not guaranteed that OS is functional (accessing flash from exception handler) these
* functions cannot use OS primitives or even does not need them (multithreaded access is not possible).
*
* @note Structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*/
typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start function. */
spi_flash_guard_end_func_t end; /**< critical section end function. */
spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
#endif
spi_flash_os_yield_t yield; /**< yield to the OS during flash erase */
} spi_flash_guard_funcs_t;
/**
* @brief Sets guard functions to access flash.
*
* @note Pointed structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*
* @param funcs pointer to structure holding flash access guard functions.
*/
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
/**
* @brief Get the guard functions used for flash access
*
* @return The guard functions that were set via spi_flash_guard_set(). These functions
* can be called if implementing custom low-level SPI flash operations.
*/
const spi_flash_guard_funcs_t *spi_flash_guard_get(void);
/**
* @brief Default OS-aware flash access guard functions
*/
extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
/**
* @brief Non-OS flash access guard functions
*
* @note This version of flash guard functions is to be used when no OS is present or from panic handler.
* It does not use any OS primitives and IPC and implies that only calling CPU is active.
*/
extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
#ifdef __cplusplus
}
#endif
#endif /* ESP_SPI_FLASH_H */
#warning esp_spi_flash.h is deprecated, please use spi_flash_mmap.h instead
#include "spi_flash_mmap.h"

View File

@ -0,0 +1,170 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file contains `spi_flash_mmap_xx` APIs, mainly for doing memory mapping
* to an SPI0-connected external Flash, as well as some helper functions to
* convert between virtual and physical address
**/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "sdkconfig.h"
#include "esp_spi_flash_counters.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1)
#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2)
#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */
#define SPI_FLASH_MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE /**< Flash cache MMU mapping page size */
/**
* @brief Enumeration which specifies memory space requested in an mmap call
*/
typedef enum {
SPI_FLASH_MMAP_DATA, /**< map to data memory (Vaddr0), allows byte-aligned access, 4 MB total */
SPI_FLASH_MMAP_INST, /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total */
} spi_flash_mmap_memory_t;
/**
* @brief Opaque handle for memory region obtained from spi_flash_mmap.
*/
typedef uint32_t spi_flash_mmap_handle_t;
/**
* @brief Map region of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the requested region of flash memory into the address space.
* It may reuse MMU pages which already provide the required mapping.
*
* As with any allocator, if mmap/munmap are heavily used then the address space
* may become fragmented. To troubleshoot issues with page allocation, use
* spi_flash_mmap_dump() function.
*
* @param src_addr Physical address in flash where requested region starts.
* This address *must* be aligned to 64kB boundary
* (SPI_FLASH_MMU_PAGE_SIZE)
* @param size Size of region to be mapped. This size will be rounded
* up to a 64kB boundary
* @param memory Address space where the region should be mapped (data or instruction)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
*/
esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Map sequences of pages of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the indicated pages of flash memory contiguously into address space.
* In this respect, it works in a similar way as spi_flash_mmap() but it allows mapping
* a (maybe non-contiguous) set of pages into a contiguous region of memory.
*
* @param pages An array of numbers indicating the 64kB pages in flash to be mapped
* contiguously into memory. These indicate the indexes of the 64kB pages,
* not the byte-size addresses as used in other functions.
* Array must be located in internal memory.
* @param page_count Number of entries in the pages array
* @param memory Address space where the region should be mapped (instruction or data)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if pages can not be allocated
* - ESP_ERR_INVALID_ARG if pagecount is zero or pages array is not in
* internal memory
*/
esp_err_t spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Release region previously obtained using spi_flash_mmap
*
* @note Calling this function will not necessarily unmap memory region.
* Region will only be unmapped when there are no other handles which
* reference this region. In case of partially overlapping regions
* it is possible that memory will be unmapped partially.
*
* @param handle Handle obtained from spi_flash_mmap
*/
void spi_flash_munmap(spi_flash_mmap_handle_t handle);
/**
* @brief Display information about mapped regions
*
* This function lists handles obtained using spi_flash_mmap, along with range
* of pages allocated to each handle. It also lists all non-zero entries of
* MMU table and corresponding reference counts.
*/
void spi_flash_mmap_dump(void);
/**
* @brief get free pages number which can be mmap
*
* This function will return number of free pages available in mmu table. This could be useful
* before calling actual spi_flash_mmap (maps flash range to DCache or ICache memory) to check
* if there is sufficient space available for mapping.
*
* @param memory memory type of MMU table free page
*
* @return number of free pages which can be mmaped
*/
uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */
/**
* @brief Given a memory address where flash is mapped, return the corresponding physical flash offset.
*
* Cache address does not have have been assigned via spi_flash_mmap(), any address in memory mapped flash space can be looked up.
*
* @param cached Pointer to flashed cached memory.
*
* @return
* - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
* - Otherwise, returns physical offset in flash
*/
size_t spi_flash_cache2phys(const void *cached);
/** @brief Given a physical offset in flash, return the address where it is mapped in the memory space.
*
* Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
*
* @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries
* point to the same physical address, there may be more than one cache address corresponding to that physical
* address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
*
* @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and
* phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
*
* @param phys_offs Physical offset in flash memory to look up.
* @param memory Address space type to look up a flash cache address mapping for (instruction or data)
*
* @return
* - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
* - Cached memory address (in IROM or DROM space) corresponding to phys_offs.
*/
const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory);
#ifdef __cplusplus
}
#endif

View File

@ -9,7 +9,7 @@
#include "memspi_host_driver.h"
#include "string.h"
#include "esp_log.h"
#include "cache_utils.h"
#include "esp_private/cache_utils.h"
#include "esp_flash_partitions.h"
#include "esp_memory_utils.h"

View File

@ -355,9 +355,6 @@ esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset
if (out_partition != NULL) {
*out_partition = NULL;
}
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return ESP_ERR_NOT_SUPPORTED;
#endif
if (offset + size > flash_chip->size) {
return ESP_ERR_INVALID_SIZE;

View File

@ -17,7 +17,7 @@
#include "esp_flash_encrypt.h"
#include "esp_log.h"
#include "esp_rom_md5.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "bootloader_common.h"
#include "esp_ota_ops.h"
@ -35,11 +35,7 @@ esp_err_t esp_partition_read(const esp_partition_t *partition,
}
if (!partition->encrypted) {
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_read(partition->flash_chip, dst, partition->address + src_offset, size);
#else
return spi_flash_read(partition->address + src_offset, dst, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
}
#if CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE
@ -76,23 +72,14 @@ esp_err_t esp_partition_write(const esp_partition_t *partition,
}
dst_offset = partition->address + dst_offset;
if (!partition->encrypted) {
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_write(partition->flash_chip, src, dst_offset, size);
#else
return spi_flash_write(dst_offset, src, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
}
#if CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE
if (partition->flash_chip != esp_flash_default_chip) {
return ESP_ERR_NOT_SUPPORTED;
}
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_write_encrypted(partition->flash_chip, dst_offset, src, size);
#else
return spi_flash_write_encrypted(dst_offset, src, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#else
return ESP_ERR_NOT_SUPPORTED;
#endif // CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE
@ -109,11 +96,7 @@ esp_err_t esp_partition_read_raw(const esp_partition_t *partition,
return ESP_ERR_INVALID_SIZE;
}
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_read(partition->flash_chip, dst, partition->address + src_offset, size);
#else
return spi_flash_read(partition->address + src_offset, dst, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
}
esp_err_t esp_partition_write_raw(const esp_partition_t *partition,
@ -128,11 +111,7 @@ esp_err_t esp_partition_write_raw(const esp_partition_t *partition,
}
dst_offset = partition->address + dst_offset;
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_write(partition->flash_chip, src, dst_offset, size);
#else
return spi_flash_write(dst_offset, src, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
}
esp_err_t esp_partition_erase_range(const esp_partition_t *partition,
@ -151,11 +130,8 @@ esp_err_t esp_partition_erase_range(const esp_partition_t *partition,
if (offset % SPI_FLASH_SEC_SIZE != 0) {
return ESP_ERR_INVALID_ARG;
}
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
return esp_flash_erase_region(partition->flash_chip, partition->address + offset, size);
#else
return spi_flash_erase_range(partition->address + offset, size);
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
}
/*

View File

@ -6,7 +6,6 @@ SOURCE_FILES := \
partition.c \
../spi_flash/partition_target.c \
flash_ops.c \
esp32/flash_ops_esp32.c \
) \
INCLUDE_DIRS := \
@ -16,6 +15,7 @@ INCLUDE_DIRS := \
../private_include \
$(addprefix stubs/, \
app_update/include \
bsd/include \
driver/include \
esp_timer/include \
freertos/include \

View File

@ -3,11 +3,13 @@
#include <string.h>
#include <stdlib.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_partition.h"
#include "esp_err.h"
#include "esp_rom_spiflash.h"
#include "esp_flash.h"
#include "bsd_strings.h"
SpiFlash spiflash = SpiFlash();
@ -85,6 +87,11 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest,
return spiflash.read(target, dest, len);
}
extern "C" esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length)
{
return spiflash.read(address, buffer, length);
}
esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block)
{
return spiflash.erase_block(block);
@ -100,11 +107,29 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_page(uint32_t page)
return spiflash.erase_page(page);
}
extern "C" esp_err_t esp_flash_erase_region(esp_flash_t *chip, uint32_t start_addr, uint32_t size)
{
size_t start = start_addr / SPI_FLASH_SEC_SIZE;
size_t end = start + size / SPI_FLASH_SEC_SIZE;
const size_t sectors_per_block = 65536 / SPI_FLASH_SEC_SIZE;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
rc = spiflash.erase_sector(sector);
++sector;
}
return rc;
}
esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src, int32_t len)
{
return spiflash.write(target, src, len);
}
extern "C" esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
{
return spiflash.write(address, buffer, length);
}
esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
{
return spiflash.write(flash_addr, data, len);

View File

@ -1,4 +1,4 @@
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_partition.h"
#include "esp_err.h"

View File

@ -5,12 +5,14 @@ SOURCE_FILES := \
esp32/crc.cpp \
esp32/esp_random.c \
esp_timer/src/esp_timer.c \
bsd/strlcpy.c\
bootloader_support/src/bootloader_common.c
INCLUDE_DIRS := \
../include \
../private_include \
app_update/include \
bsd/include \
driver/include \
esp_timer/include \
freertos/include \

View File

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
size_t strlcpy(char *dst, const char *src, size_t dsize);

View File

@ -0,0 +1,60 @@
/* $OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $ */
/*-
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
/*
* Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0).
* Returns strlen(src); if retval >= dsize, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t dsize)
{
const char *osrc = src;
size_t nleft = dsize;
/* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */
while (*src++)
;
}
return(src - osrc - 1); /* count does not include NUL */
}

View File

@ -8,7 +8,6 @@
#include <sys/param.h> //For max/min
#include "esp_attr.h"
#include "esp_private/system_internal.h"
#include "esp_spi_flash.h" //for ``g_flash_guard_default_ops``
#include "esp_flash.h"
#include "esp_flash_partitions.h"
#include "freertos/FreeRTOS.h"
@ -19,6 +18,7 @@
#include "esp_compiler.h"
#include "esp_rom_sys.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/cache_utils.h"
#include "esp_private/spi_common_internal.h"
@ -61,14 +61,14 @@ static inline bool on_spi1_check_yield(spi1_app_func_arg_t* ctx);
IRAM_ATTR static void cache_enable(void* arg)
{
#ifndef CONFIG_SPI_FLASH_AUTO_SUSPEND
g_flash_guard_default_ops.end();
spi_flash_enable_interrupts_caches_and_other_cpu();
#endif
}
IRAM_ATTR static void cache_disable(void* arg)
{
#ifndef CONFIG_SPI_FLASH_AUTO_SUSPEND
g_flash_guard_default_ops.start();
spi_flash_disable_interrupts_caches_and_other_cpu();
#endif
}

View File

@ -1,9 +1,4 @@
if(CONFIG_SPI_FLASH_USE_LEGACY_IMPL)
set(exclude_srcs "test_esp_flash.c" "test_partition_ext.c")
endif()
idf_component_register(SRC_DIRS "."
EXCLUDE_SRCS "${exclude_srcs}"
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES cmock test_utils spi_flash bootloader_support app_update
driver esp_timer)

View File

@ -12,11 +12,11 @@
#include <freertos/semphr.h>
#include <unity.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <esp_attr.h>
#include <esp_flash_encrypt.h>
#include "../cache_utils.h"
#include "esp_private/cache_utils.h"
static QueueHandle_t result_queue;

View File

@ -5,7 +5,7 @@
#include <unity.h>
#include <test_utils.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <esp_attr.h>
#include <esp_flash_encrypt.h>
#include <string.h>
@ -39,10 +39,9 @@ static void verify_erased_flash(size_t offset, size_t length)
uint8_t *readback = (uint8_t *)heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
printf("verify erased 0x%x - 0x%x\n", offset, offset + length);
TEST_ASSERT_EQUAL_HEX(ESP_OK,
spi_flash_read(offset, readback, length));
esp_flash_read(NULL, readback, offset, length));
for (int i = 0; i < length; i++) {
char message[32];
TEST_ASSERT_EQUAL_HEX_MESSAGE(0xFF, readback[i], message);
TEST_ASSERT_EQUAL_HEX8(0xFF, readback[i]);
}
free(readback);
}
@ -52,7 +51,7 @@ TEST_CASE("test 16 byte encrypted writes", "[flash_encryption][test_env=UT_T1_Fl
setup_tests();
TEST_ASSERT_EQUAL_HEX(ESP_OK,
spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE));
esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE));
uint8_t fortyeight_bytes[0x30]; // 0, 1, 2, 3, 4... 47
for(int i = 0; i < sizeof(fortyeight_bytes); i++) {
@ -61,10 +60,10 @@ TEST_CASE("test 16 byte encrypted writes", "[flash_encryption][test_env=UT_T1_Fl
/* Verify unaligned start or length fails */
TEST_ASSERT_EQUAL_HEX(ESP_ERR_INVALID_ARG,
spi_flash_write_encrypted(start+1, fortyeight_bytes, 32));
esp_flash_write_encrypted(NULL, start + 1, fortyeight_bytes, 32));
TEST_ASSERT_EQUAL_HEX(ESP_ERR_INVALID_SIZE,
spi_flash_write_encrypted(start, fortyeight_bytes, 15));
esp_flash_write_encrypted(NULL, start, fortyeight_bytes, 15));
/* ensure nothing happened to the flash yet */
verify_erased_flash(start, 0x20);
@ -73,9 +72,9 @@ TEST_CASE("test 16 byte encrypted writes", "[flash_encryption][test_env=UT_T1_Fl
test_encrypted_write(start, fortyeight_bytes, 0x20);
verify_erased_flash(start + 0x20, 0x20);
/* Slip in an unaligned spi_flash_read_encrypted() test */
/* Slip in an unaligned esp_flash_read_encrypted() test */
uint8_t buf[0x10];
spi_flash_read_encrypted(start+0x10, buf, 0x10);
esp_flash_read_encrypted(NULL, start+0x10, buf, 0x10);
TEST_ASSERT_EQUAL_HEX8_ARRAY(fortyeight_bytes+0x10, buf, 16);
/* Write 16 bytes unaligned */
@ -100,10 +99,10 @@ static void test_encrypted_write(size_t offset, const uint8_t *data, size_t leng
uint8_t readback[length];
printf("encrypt %d bytes at 0x%x\n", length, offset);
TEST_ASSERT_EQUAL_HEX(ESP_OK,
spi_flash_write_encrypted(offset, data, length));
esp_flash_write_encrypted(NULL, offset, data, length));
TEST_ASSERT_EQUAL_HEX(ESP_OK,
spi_flash_read_encrypted(offset, readback, length));
esp_flash_read_encrypted(NULL, offset, readback, length));
TEST_ASSERT_EQUAL_HEX8_ARRAY(data, readback, length);
}
@ -118,13 +117,13 @@ TEST_CASE("test read & write random encrypted data", "[flash_encryption][test_en
setup_tests();
esp_err_t err = spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE);
esp_err_t err = esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE);
TEST_ESP_OK(err);
//initialize the buffer to compare
uint8_t *cmp_buf = heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
assert(((intptr_t)cmp_buf % 4) == 0);
err = spi_flash_read_encrypted(start, cmp_buf, SPI_FLASH_SEC_SIZE);
err = esp_flash_read_encrypted(NULL, start, cmp_buf, SPI_FLASH_SEC_SIZE);
TEST_ESP_OK(err);
srand(789);
@ -148,7 +147,7 @@ TEST_CASE("test read & write random encrypted data", "[flash_encryption][test_en
}
printf("write %d bytes to 0x%08x...\n", len, start + offset);
err = spi_flash_write_encrypted(start + offset, data_buf, len);
err = esp_flash_write_encrypted(NULL, start + offset, data_buf, len);
TEST_ESP_OK(err);
memcpy(cmp_buf + offset, data_buf, len);
@ -162,7 +161,7 @@ TEST_CASE("test read & write random encrypted data", "[flash_encryption][test_en
len = SPI_FLASH_SEC_SIZE - offset;
}
err = spi_flash_read_encrypted(start + offset, data_buf, len);
err = esp_flash_read_encrypted(NULL, start + offset, data_buf, len);
TEST_ESP_OK(err);
printf("compare %d bytes at 0x%08x...\n", len, start + offset);
@ -174,8 +173,6 @@ TEST_CASE("test read & write random encrypted data", "[flash_encryption][test_en
free(cmp_buf);
}
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
static char TAG[] = "flash_encrypt_test";
static const char plainttext_data[] = "$$$$#### Welcome! This is flash encryption test, ..., ..., hello_world. &&&&***";
@ -198,7 +195,7 @@ TEST_CASE("test 16 byte encrypted writes (esp_flash)", "[esp_flash_enc][flash_en
setup_tests();
TEST_ASSERT_EQUAL_HEX(ESP_OK,
spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE));
esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE));
uint8_t fortyeight_bytes[0x30]; // 0, 1, 2, 3, 4... 47
for(int i = 0; i < sizeof(fortyeight_bytes); i++) {
@ -245,7 +242,7 @@ TEST_CASE("test read & write encrypted data(32 bytes alianed address)", "[esp_fl
{
setup_tests();
TEST_ESP_OK(spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE));
start = (start + 31) & (~31); // round up to 32 byte boundary
ESP_LOG_BUFFER_HEXDUMP(TAG, plainttext_data, sizeof(plainttext_data), ESP_LOG_INFO);
@ -270,7 +267,7 @@ TEST_CASE("test read & write encrypted data(32 bytes alianed address)", "[esp_fl
TEST_CASE("test read & write encrypted data(16 bytes alianed but 32 bytes unaligned)", "[esp_flash_enc][flash_encryption][test_env=UT_T1_FlashEncryption]")
{
setup_tests();
TEST_ESP_OK(spi_flash_erase_sector(start/SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE));
do {
start++;
} while ((start % 16) != 0);
@ -327,5 +324,5 @@ TEST_CASE("test read & write encrypted data with large buffer(n*64+32+16)", "[es
TEST_ASSERT_EQUAL_HEX8_ARRAY(buf, large_const_buffer, sizeof(large_const_buffer));
free(buf);
}
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#endif // CONFIG_SECURE_FLASH_ENC_ENABLED

View File

@ -15,10 +15,10 @@
#include <unity.h>
#include <test_utils.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <esp_log.h>
#include "esp_rom_spiflash.h"
#include "../cache_utils.h"
#include "esp_private/cache_utils.h"
#include "soc/timer_periph.h"
static const uint8_t large_const_buffer[16400] = {
@ -34,13 +34,13 @@ static const uint8_t large_const_buffer[16400] = {
static void test_write_large_buffer(const uint8_t *source, size_t length);
TEST_CASE("Test spi_flash_write large const buffer", "[spi_flash][esp_flash]")
TEST_CASE("Test flash write large const buffer", "[spi_flash][esp_flash]")
{
// buffer in flash
test_write_large_buffer(large_const_buffer, sizeof(large_const_buffer));
}
TEST_CASE("Test spi_flash_write large RAM buffer", "[spi_flash][esp_flash]")
TEST_CASE("Test flash write large RAM buffer", "[spi_flash][esp_flash]")
{
// buffer in RAM
uint8_t *source_buf = malloc(sizeof(large_const_buffer));
@ -60,12 +60,12 @@ static void test_write_large_buffer(const uint8_t *source, size_t length)
uint8_t *buf = malloc(length);
TEST_ASSERT_NOT_NULL(buf);
ESP_ERROR_CHECK( spi_flash_erase_range(part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE-1)) );
TEST_ESP_OK( esp_flash_erase_region(NULL, part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE-1)) );
// note writing to unaligned address
ESP_ERROR_CHECK( spi_flash_write(part->address + 1, source, length) );
TEST_ESP_OK( esp_flash_write(NULL, source, part->address + 1, length) );
ESP_ERROR_CHECK( spi_flash_read(part->address + 1, buf, length) );
TEST_ESP_OK( esp_flash_read(NULL, buf, part->address + 1, length) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(source, buf, length);
@ -74,12 +74,11 @@ static void test_write_large_buffer(const uint8_t *source, size_t length)
// check nothing was written at beginning or end
uint8_t ends[8];
ESP_ERROR_CHECK( spi_flash_read(part->address, ends, sizeof(ends)) );
TEST_ESP_OK( esp_flash_read(NULL, ends, part->address, sizeof(ends)) );
TEST_ASSERT_EQUAL_HEX8(0xFF, ends[0]);
TEST_ASSERT_EQUAL_HEX8(source[0] , ends[1]);
ESP_ERROR_CHECK( spi_flash_read(part->address + length, ends, sizeof(ends)) );
TEST_ESP_OK( esp_flash_read(NULL, ends, part->address + length, sizeof(ends)) );
TEST_ASSERT_EQUAL_HEX8(source[length-1], ends[0]);
TEST_ASSERT_EQUAL_HEX8(0xFF, ends[1]);
TEST_ASSERT_EQUAL_HEX8(0xFF, ends[2]);

View File

@ -6,7 +6,7 @@
#include <freertos/semphr.h>
#include <unity.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <esp_attr.h>
#include <esp_partition.h>
#include <esp_flash_encrypt.h>
@ -28,9 +28,9 @@ static spi_flash_mmap_handle_t handle1, handle2, handle3;
static esp_err_t spi_flash_read_maybe_encrypted(size_t src_addr, void *des_addr, size_t size)
{
if (!esp_flash_encryption_enabled()) {
return spi_flash_read(src_addr, des_addr, size);
return esp_flash_read(NULL, des_addr, src_addr, size);
} else {
return spi_flash_read_encrypted(src_addr, des_addr, size);
return esp_flash_read_encrypted(NULL, src_addr, des_addr, size);
}
}
@ -39,9 +39,9 @@ static esp_err_t spi_flash_read_maybe_encrypted(size_t src_addr, void *des_addr,
static esp_err_t spi_flash_write_maybe_encrypted(size_t des_addr, const void *src_addr, size_t size)
{
if (!esp_flash_encryption_enabled()) {
return spi_flash_write(des_addr, src_addr, size);
return esp_flash_write(NULL, src_addr, des_addr, size);
} else {
return spi_flash_write_encrypted(des_addr, src_addr, size);
return esp_flash_write_encrypted(NULL, des_addr, src_addr, size);
}
}
@ -78,7 +78,7 @@ static void setup_mmap_tests(void)
uint32_t sector_offs = abs_sector * SPI_FLASH_SEC_SIZE;
bool sector_needs_write = false;
ESP_ERROR_CHECK( spi_flash_read_maybe_encrypted(sector_offs, buffer, sizeof(buffer)) );
TEST_ESP_OK( spi_flash_read_maybe_encrypted(sector_offs, buffer, sizeof(buffer)) );
for (uint32_t word = 0; word < 1024; ++word) {
uint32_t val = rand();
@ -92,8 +92,8 @@ static void setup_mmap_tests(void)
}
/* Only rewrite the sector if it has changed */
if (sector_needs_write) {
ESP_ERROR_CHECK( spi_flash_erase_sector((uint16_t) abs_sector) );
ESP_ERROR_CHECK( spi_flash_write_maybe_encrypted(sector_offs, (const uint8_t *) buffer, sizeof(buffer)) );
TEST_ESP_OK( esp_flash_erase_region(NULL, (uint16_t) abs_sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE) );
TEST_ESP_OK( spi_flash_write_maybe_encrypted(sector_offs, (const uint8_t *) buffer, sizeof(buffer)) );
}
}
}
@ -105,7 +105,7 @@ TEST_CASE("Can mmap into data address space", "[spi_flash][mmap]")
printf("Mapping %x (+%x)\n", start, end - start);
const void *ptr1;
ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1);
spi_flash_mmap_dump();
@ -123,7 +123,7 @@ TEST_CASE("Can mmap into data address space", "[spi_flash][mmap]")
}
printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000);
const void *ptr2;
ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
TEST_ESP_OK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2);
TEST_ASSERT_EQUAL_HEX32(start - 0x10000, spi_flash_cache2phys(ptr2));
@ -133,7 +133,7 @@ TEST_CASE("Can mmap into data address space", "[spi_flash][mmap]")
printf("Mapping %x (+%x)\n", start, 0x10000);
const void *ptr3;
ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) );
TEST_ESP_OK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) );
printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3);
TEST_ASSERT_EQUAL_HEX32(start, spi_flash_cache2phys(ptr3));
@ -172,7 +172,7 @@ TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
printf("Mapping %x (+%x)\n", start, end - start);
spi_flash_mmap_handle_t handle1;
const void *ptr1;
ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_INST, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_INST, &ptr1, &handle1) );
printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1);
spi_flash_mmap_dump();
@ -189,7 +189,7 @@ TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000);
spi_flash_mmap_handle_t handle2;
const void *ptr2;
ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_INST, &ptr2, &handle2) );
TEST_ESP_OK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_INST, &ptr2, &handle2) );
printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2);
TEST_ASSERT_EQUAL_HEX32(start - 0x10000, spi_flash_cache2phys(ptr2));
@ -200,7 +200,7 @@ TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
printf("Mapping %x (+%x)\n", start, 0x10000);
spi_flash_mmap_handle_t handle3;
const void *ptr3;
ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_INST, &ptr3, &handle3) );
TEST_ESP_OK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_INST, &ptr3, &handle3) );
printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3);
TEST_ASSERT_EQUAL_HEX32(start, spi_flash_cache2phys(ptr3));
@ -246,7 +246,7 @@ TEST_CASE("Can mmap unordered pages into contiguous memory", "[spi_flash][mmap]"
spi_flash_mmap_handle_t handle1;
const void *ptr1;
ESP_ERROR_CHECK( spi_flash_mmap_pages(pages, nopages, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap_pages(pages, nopages, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1);
spi_flash_mmap_dump();
@ -278,10 +278,10 @@ TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash][mmap]")
TEST_IGNORE_MESSAGE("flash encryption enabled, spi_flash_write_encrypted() test won't pass as-is");
}
ESP_ERROR_CHECK( spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE) );
TEST_ESP_OK( esp_flash_erase_region(NULL, start, SPI_FLASH_SEC_SIZE) );
/* map erased test region to ptr1 */
ESP_ERROR_CHECK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
printf("mmap_res ptr1: handle=%d ptr=%p\n", handle1, ptr1);
/* verify it's all 0xFF */
@ -296,14 +296,14 @@ TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash][mmap]")
/* write flash region to 0xEE */
uint8_t buf[test_size];
memset(buf, 0xEE, test_size);
ESP_ERROR_CHECK( spi_flash_write(start, buf, test_size) );
TEST_ESP_OK( esp_flash_write(NULL, buf, start, test_size) );
/* re-map the test region at ptr1.
this is a fresh mmap call so should trigger a cache flush,
ensuring we see the updated flash.
*/
ESP_ERROR_CHECK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
printf("mmap_res ptr1 #2: handle=%d ptr=%p\n", handle1, ptr1);
/* assert that ptr1 now maps to the new values on flash,
@ -322,7 +322,7 @@ TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash][mm
printf("Mapping %x (+%x)\n", start, end - start);
const void *ptr1;
ESP_ERROR_CHECK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, end - start, SPI_FLASH_MMAP_DATA, &ptr1, &handle1) );
printf("mmap_res: handle=%d ptr=%p\n", handle1, ptr1);
spi_flash_mmap_dump();
@ -339,12 +339,14 @@ TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash][mm
}
}
uint32_t free_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
uint32_t flash_pages = spi_flash_get_chip_size() / SPI_FLASH_MMU_PAGE_SIZE;
uint32_t flash_size;
TEST_ESP_OK(esp_flash_get_size(NULL, &flash_size));
uint32_t flash_pages = flash_size / SPI_FLASH_MMU_PAGE_SIZE;
free_pages = (free_pages > flash_pages) ? flash_pages : free_pages;
printf("Mapping %x (+%x)\n", 0, free_pages * SPI_FLASH_MMU_PAGE_SIZE);
const void *ptr2;
ESP_ERROR_CHECK( spi_flash_mmap(0, free_pages * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
TEST_ESP_OK( spi_flash_mmap(0, free_pages * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) );
printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2);
spi_flash_mmap_dump();
@ -409,7 +411,7 @@ TEST_CASE("mmap consistent with phys2cache/cache2phys", "[spi_flash][mmap]")
TEST_ASSERT_EQUAL_HEX(SPI_FLASH_CACHE2PHYS_FAIL, spi_flash_cache2phys(ptr));
ESP_ERROR_CHECK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr, &handle1) );
TEST_ESP_OK( spi_flash_mmap(start, test_size, SPI_FLASH_MMAP_DATA, &ptr, &handle1) );
TEST_ASSERT_NOT_NULL(ptr);
TEST_ASSERT_NOT_EQUAL(0, handle1);

View File

@ -1,7 +1,7 @@
#include <string.h>
#include "unity.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_ota_ops.h"
#if CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS || CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS
@ -16,18 +16,18 @@ static const char *data = "blah blah blah";
TEST_CASE("can't overwrite bootloader", TEST_TAGS)
{
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_write(0x1000, data, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_write(0x0FF8, data, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_write(0x1400, data, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_erase_range(0x8000, 0x2000));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_erase_range(0x7000, 0x2000));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_write(NULL, data, 0x1000, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_write(NULL, data, 0x0FF8, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_write(NULL, data, 0x1400, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_erase_region(NULL, 0x8000, 0x2000));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_erase_region(NULL, 0x7000, 0x2000));
}
TEST_CASE("can't overwrite current running app", TEST_TAGS)
{
const esp_partition_t *p = esp_ota_get_running_partition();
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_write(p->address + 1024, data, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, spi_flash_erase_range(p->address + 4096, 8192));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_write(NULL, data, p->address + 1024, strlen(data)));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_flash_erase_region(NULL, p->address + 4096, 8192));
}
#endif // FAILS || ABORTS

View File

@ -123,7 +123,8 @@ TEST_CASE("Test esp_partition_get_sha256() that it can handle a big partition",
spi_flash_mmap_handle_t handle;
uint8_t sha256[32] = { 0 };
size_t size_flash_chip = spi_flash_get_chip_size();
uint32_t size_flash_chip;
esp_flash_get_size(NULL, &size_flash_chip);
printf("size_flash_chip = %d bytes\n", size_flash_chip);

View File

@ -14,8 +14,8 @@
#include <unity.h>
#include <test_utils.h>
#include <esp_spi_flash.h>
#include "../cache_utils.h"
#include <spi_flash_mmap.h>
#include "esp_private/cache_utils.h"
#include "soc/timer_periph.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
@ -69,7 +69,6 @@ static int cmp_or_dump(const void *a, const void *b, size_t len)
return r;
}
static void IRAM_ATTR test_read(int src_off, int dst_off, int len)
{
uint32_t src_buf[16];
@ -78,7 +77,7 @@ static void IRAM_ATTR test_read(int src_off, int dst_off, int len)
fprintf(stderr, "src=%d dst=%d len=%d\n", src_off, dst_off, len);
memset(src_buf, 0xAA, sizeof(src_buf));
fill(((char *) src_buf) + src_off, src_off, len);
ESP_ERROR_CHECK(spi_flash_erase_sector((start + src_off) / SPI_FLASH_SEC_SIZE));
ESP_ERROR_CHECK(esp_flash_erase_region(NULL, (start + src_off) & ~(0x10000 - 1), SPI_FLASH_SEC_SIZE));
spi_flash_disable_interrupts_caches_and_other_cpu();
esp_rom_spiflash_result_t rc = esp_rom_spiflash_write(start, src_buf, sizeof(src_buf));
spi_flash_enable_interrupts_caches_and_other_cpu();
@ -86,7 +85,7 @@ static void IRAM_ATTR test_read(int src_off, int dst_off, int len)
memset(dst_buf, 0x55, sizeof(dst_buf));
memset(dst_gold, 0x55, sizeof(dst_gold));
fill(dst_gold + dst_off, src_off, len);
ESP_ERROR_CHECK(spi_flash_read(start + src_off, dst_buf + dst_off, len));
ESP_ERROR_CHECK(esp_flash_read(NULL, dst_buf + dst_off, start + src_off, len));
TEST_ASSERT_EQUAL_INT(cmp_or_dump(dst_buf, dst_gold, sizeof(dst_buf)), 0);
}
@ -209,7 +208,7 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len)
memset(src_buf, 0x55, sizeof(src_buf));
fill(src_buf + src_off, src_off, len);
// Fills with 0xff
ESP_ERROR_CHECK(spi_flash_erase_sector((start + dst_off) / SPI_FLASH_SEC_SIZE));
ESP_ERROR_CHECK(esp_flash_erase_region(NULL, (start + src_off) & ~(0x10000 - 1), SPI_FLASH_SEC_SIZE));
memset(dst_gold, 0xff, sizeof(dst_gold));
if (len > 0) {
int pad_left_off = (dst_off & ~3U);
@ -220,7 +219,7 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len)
}
fill(dst_gold + dst_off, src_off, len);
}
ESP_ERROR_CHECK(spi_flash_write(start + dst_off, src_buf + src_off, len));
ESP_ERROR_CHECK(esp_flash_write(NULL, src_buf + src_off, start + dst_off, len));
fix_rom_func();
@ -232,7 +231,7 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len)
TEST_ASSERT_EQUAL_INT(cmp_or_dump(dst_buf, dst_gold, sizeof(dst_buf)), 0);
}
TEST_CASE("Test spi_flash_write", "[spi_flash][esp_flash]")
TEST_CASE("Test esp_flash_write", "[spi_flash][esp_flash]")
{
setup_tests();
#if CONFIG_SPI_FLASH_MINIMAL_TEST
@ -288,19 +287,19 @@ TEST_CASE("Test spi_flash_write", "[spi_flash][esp_flash]")
#define TEST_SOC_IRAM_ADDR (SOC_IRAM_LOW + 0x8000)
#define TEST_SOC_RTC_IRAM_ADDR (SOC_RTC_IRAM_LOW)
#define TEST_SOC_RTC_DRAM_ADDR (SOC_RTC_DRAM_LOW)
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IROM_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IRAM_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK0_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK1_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK2_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK3_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_IRAM_ADDR, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_DRAM_ADDR, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_IROM_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_IRAM_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_CACHE_RAM_BANK0_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_CACHE_RAM_BANK1_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_CACHE_RAM_BANK2_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_CACHE_RAM_BANK3_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_RTC_IRAM_ADDR, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) TEST_SOC_RTC_DRAM_ADDR, start, 16));
#else
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40000000, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40070000, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40078000, 16));
ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40080000, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) 0x40000000, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) 0x40070000, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) 0x40078000, start, 16));
ESP_ERROR_CHECK(esp_flash_write(NULL, (char *) 0x40080000, start, 16));
#endif
}
@ -314,15 +313,15 @@ TEST_CASE("spi_flash_read can read into buffer in external RAM", "[spi_flash]")
uint8_t* buf_int = (uint8_t*) heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(buf_int);
TEST_ESP_OK(spi_flash_read(0x1000, buf_int, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(spi_flash_read(0x1000, buf_ext, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_read(NULL, buf_int, 0x1000, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_read(NULL, buf_ext, 0x1000, SPI_FLASH_SEC_SIZE));
TEST_ASSERT_EQUAL(0, memcmp(buf_ext, buf_int, SPI_FLASH_SEC_SIZE));
free(buf_ext);
free(buf_int);
}
TEST_CASE("spi_flash_write can write from external RAM buffer", "[spi_flash]")
TEST_CASE("esp_flash_write can write from external RAM buffer", "[spi_flash]")
{
uint32_t* buf_ext = (uint32_t*) heap_caps_malloc(SPI_FLASH_SEC_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(buf_ext);
@ -339,11 +338,11 @@ TEST_CASE("spi_flash_write can write from external RAM buffer", "[spi_flash]")
/* Write to flash from buf_ext */
const esp_partition_t *part = get_test_data_partition();
TEST_ESP_OK(spi_flash_erase_range(part->address, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(spi_flash_write(part->address, buf_ext, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_erase_region(NULL, part->address & ~(0x10000 - 1), SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_write(NULL, buf_ext, part->address, SPI_FLASH_SEC_SIZE));
/* Read back to buf_int and compare */
TEST_ESP_OK(spi_flash_read(part->address, buf_int, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_read(NULL, buf_int, part->address, SPI_FLASH_SEC_SIZE));
TEST_ASSERT_EQUAL(0, memcmp(buf_ext, buf_int, SPI_FLASH_SEC_SIZE));
free(buf_ext);
@ -364,10 +363,10 @@ TEST_CASE("spi_flash_read less than 16 bytes into buffer in external RAM", "[spi
}
const esp_partition_t *part = get_test_data_partition();
TEST_ESP_OK(spi_flash_erase_range(part->address, SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(spi_flash_write(part->address, data_8, MIN_BLOCK_SIZE));
TEST_ESP_OK(spi_flash_read(part->address, buf_ext_8, MIN_BLOCK_SIZE));
TEST_ESP_OK(spi_flash_read(part->address, buf_int_8, MIN_BLOCK_SIZE));
TEST_ESP_OK(esp_flash_erase_region(NULL, part->address & ~(0x10000 - 1), SPI_FLASH_SEC_SIZE));
TEST_ESP_OK(esp_flash_write(NULL, data_8, part->address, MIN_BLOCK_SIZE));
TEST_ESP_OK(esp_flash_read(NULL, buf_ext_8, part->address, MIN_BLOCK_SIZE));
TEST_ESP_OK(esp_flash_read(NULL, buf_int_8, part->address, MIN_BLOCK_SIZE));
TEST_ASSERT_EQUAL(0, memcmp(buf_ext_8, data_8, MIN_BLOCK_SIZE));
TEST_ASSERT_EQUAL(0, memcmp(buf_int_8, data_8, MIN_BLOCK_SIZE));

View File

@ -5,7 +5,7 @@
#include <freertos/semphr.h>
#include <unity.h>
#include <esp_spi_flash.h>
#include <spi_flash_mmap.h>
#include <esp_attr.h>
#include "esp_intr_alloc.h"
#include "test_utils.h"
@ -47,7 +47,7 @@ static void flash_test_task(void *arg)
const uint32_t sector = start / SPI_FLASH_SEC_SIZE + ctx->offset;
printf("t%d\n", sector);
printf("es%d\n", sector);
if (spi_flash_erase_sector(sector) != ESP_OK) {
if (esp_flash_erase_region(NULL, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE) != ESP_OK) {
ctx->fail = true;
printf("Erase failed\r\n");
xSemaphoreGive(ctx->done);
@ -59,7 +59,7 @@ static void flash_test_task(void *arg)
uint32_t val = 0xabcd1234;
for (uint32_t offset = 0; offset < SPI_FLASH_SEC_SIZE; offset += 4) {
if (spi_flash_write(sector * SPI_FLASH_SEC_SIZE + offset, (const uint8_t *) &val, 4) != ESP_OK) {
if (esp_flash_write(NULL, (const uint8_t *) &val, sector * SPI_FLASH_SEC_SIZE + offset, 4) != ESP_OK) {
printf("Write failed at offset=%d\r\n", offset);
ctx->fail = true;
break;
@ -71,7 +71,7 @@ static void flash_test_task(void *arg)
uint32_t val_read;
for (uint32_t offset = 0; offset < SPI_FLASH_SEC_SIZE; offset += 4) {
if (spi_flash_read(sector * SPI_FLASH_SEC_SIZE + offset, (uint8_t *) &val_read, 4) != ESP_OK) {
if (esp_flash_read(NULL, (uint8_t *) &val_read, sector * SPI_FLASH_SEC_SIZE + offset, 4) != ESP_OK) {
printf("Read failed at offset=%d\r\n", offset);
ctx->fail = true;
break;
@ -151,7 +151,7 @@ static uint32_t measure_erase(const esp_partition_t* part)
time_meas_ctx_t time_ctx = {.name = "erase", .len = total_len};
time_measure_start(&time_ctx);
esp_err_t err = spi_flash_erase_range(part->address, total_len);
esp_err_t err = esp_flash_erase_region(NULL, part->address, total_len);
TEST_ESP_OK(err);
return time_measure_end(&time_ctx);
}
@ -170,7 +170,7 @@ static uint32_t measure_write(const char* name, const esp_partition_t* part, con
while (len) {
int len_write = MIN(seg_len, len);
esp_err_t err = spi_flash_write(part->address + offset, data_to_write + offset, len_write);
esp_err_t err = esp_flash_write(NULL, data_to_write + offset, part->address + offset, len_write);
TEST_ESP_OK(err);
offset += len_write;
@ -192,7 +192,7 @@ static uint32_t measure_read(const char* name, const esp_partition_t* part, uint
while (len) {
int len_read = MIN(seg_len, len);
esp_err_t err = spi_flash_read(part->address + offset, data_read + offset, len_read);
esp_err_t err = esp_flash_read(NULL, data_read + offset, part->address + offset, len_read);
TEST_ESP_OK(err);
offset += len_read;
@ -294,7 +294,7 @@ TEST_CASE("spi_flash deadlock with high priority busy-waiting task", "[spi_flash
for (int i = 0; i < 1000; i++) {
uint32_t dummy;
TEST_ESP_OK(spi_flash_read(0, &dummy, sizeof(dummy)));
TEST_ESP_OK(esp_flash_read(NULL, &dummy, 0, sizeof(dummy)));
}
arg.done = true;

View File

@ -9,7 +9,7 @@
#include "spiffs_nucleus.h"
#include "esp_log.h"
#include "esp_partition.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_image_format.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

View File

@ -6,7 +6,9 @@
#include "esp_log.h"
#include "SPI_Flash.h"
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_flash.h"
static const char *TAG = "spi_flash";
SPI_Flash::SPI_Flash()
@ -15,12 +17,14 @@ SPI_Flash::SPI_Flash()
size_t SPI_Flash::chip_size()
{
return spi_flash_get_chip_size();
uint32_t chip_size;
esp_flash_get_size(NULL, &chip_size);
return chip_size;
}
esp_err_t SPI_Flash::erase_sector(size_t sector)
{
esp_err_t result = spi_flash_erase_sector(sector);
esp_err_t result = esp_flash_erase_region(NULL, sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);;
if (result == ESP_OK) {
ESP_LOGV(TAG, "erase_sector - sector=0x%08x, result=0x%08x", sector, result);
} else {
@ -32,7 +36,7 @@ esp_err_t SPI_Flash::erase_range(size_t start_address, size_t size)
{
size = (size + SPI_FLASH_SEC_SIZE - 1) / SPI_FLASH_SEC_SIZE;
size = size * SPI_FLASH_SEC_SIZE;
esp_err_t result = spi_flash_erase_range(start_address, size);
esp_err_t result = esp_flash_erase_region(NULL, start_address, size);
if (result == ESP_OK) {
ESP_LOGV(TAG, "erase_range - start_address=0x%08x, size=0x%08x, result=0x%08x", start_address, size, result);
} else {
@ -43,7 +47,7 @@ esp_err_t SPI_Flash::erase_range(size_t start_address, size_t size)
esp_err_t SPI_Flash::write(size_t dest_addr, const void *src, size_t size)
{
esp_err_t result = spi_flash_write(dest_addr, src, size);
esp_err_t result = esp_flash_write(NULL, src, dest_addr, size);
if (result == ESP_OK) {
ESP_LOGV(TAG, "write - dest_addr=0x%08x, size=0x%08x, result=0x%08x", dest_addr, size, result);
} else {
@ -54,7 +58,7 @@ esp_err_t SPI_Flash::write(size_t dest_addr, const void *src, size_t size)
esp_err_t SPI_Flash::read(size_t src_addr, void *dest, size_t size)
{
esp_err_t result = spi_flash_read(src_addr, dest, size);
esp_err_t result = esp_flash_read(NULL, dest, src_addr, size);
if (result == ESP_OK) {
ESP_LOGV(TAG, "read - src_addr=0x%08x, size=0x%08x, result=0x%08x", src_addr, size, result);
} else {

View File

@ -7,7 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include "esp_spi_flash.h"
#include "spi_flash_mmap.h"
#include "esp_partition.h"
#include "wear_levelling.h"
#include "WL_Flash.h"

View File

@ -206,7 +206,7 @@ INPUT = \
$(PROJECT_PATH)/components/spi_flash/include/esp_flash.h \
$(PROJECT_PATH)/components/spi_flash/include/esp_flash_spi_init.h \
$(PROJECT_PATH)/components/spi_flash/include/esp_partition.h \
$(PROJECT_PATH)/components/spi_flash/include/esp_spi_flash.h \
$(PROJECT_PATH)/components/spi_flash/include/spi_flash_mmap.h \
$(PROJECT_PATH)/components/spiffs/include/esp_spiffs.h \
$(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb.h \
$(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb_types.h \

View File

@ -1034,7 +1034,7 @@ For example, in the ``foo/CMakeLists.txt`` file::
add_library(foo bar.c fizz.cpp buzz.cpp)
if(ESP_PLATFORM)
# On ESP-IDF, bar.c needs to include esp_spi_flash.h from the spi_flash component
# On ESP-IDF, bar.c needs to include esp_flash.h from the spi_flash component
target_link_libraries(foo PRIVATE idf::spi_flash)
endif()

View File

@ -19,10 +19,9 @@ Different from the API before IDF v4.0, the functionality of `esp_flash_*` APIs
Flash APIs after ESP-IDF v4.0 are no longer *atomic*. If a write operation occurs during another on-going read operation, and the flash addresses of both operations overlap, the data returned from the read operation may contain both old data and new data (that was updated written by the write operation).
.. note::
Kconfig option :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` can be used to switch ``spi_flash_*`` functions back to the implementation before ESP-IDF v4.0. However, the code size may get bigger if you use the new API and the old API at the same time.
Encrypted reads and writes use the old implementation, even if :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` is not enabled. As such, encrypted flash operations are only supported with the main flash chip (and not with other flash chips, that is on SPI1 with different CS, or on other SPI buses). Reading through cache is only supported on the main flash, which is determined by the HW.
Encrypted flash operations are only supported with the main flash chip (and not with other flash chips, that is on SPI1 with different CS, or on other SPI buses). Reading through cache is only supported on the main flash, which is determined by the HW.
Support for Features of Flash Chips
-----------------------------------
@ -138,7 +137,7 @@ This component provides API functions to enumerate partitions found in the parti
- :cpp:func:`esp_partition_next` shifts the iterator to the next found partition.
- :cpp:func:`esp_partition_iterator_release` releases iterator returned by ``esp_partition_find``.
- :cpp:func:`esp_partition_find_first` is a convenience function which returns the structure describing the first partition found by ``esp_partition_find``.
- :cpp:func:`esp_partition_read`, :cpp:func:`esp_partition_write`, :cpp:func:`esp_partition_erase_range` are equivalent to :cpp:func:`spi_flash_read`, :cpp:func:`spi_flash_write`, :cpp:func:`spi_flash_erase_range`, but operate within partition boundaries.
- :cpp:func:`esp_partition_read`, :cpp:func:`esp_partition_write`, :cpp:func:`esp_partition_erase_range` are equivalent to :cpp:func:`esp_flash_read`, :cpp:func:`esp_flash_write`, :cpp:func:`esp_flash_erase_region`, but operate within partition boundaries.
.. note::
Application code should mostly use these ``esp_partition_*`` API functions instead of lower level ``esp_flash_*`` API functions. Partition table API functions do bounds checking and calculate correct offsets in flash, based on data stored in a partition table.
@ -164,7 +163,7 @@ Note that some pages are used to map the application itself into memory, so the
Reading data from flash using a memory mapped region is the only way to decrypt contents of flash when :doc:`flash encryption </security/flash-encryption>` is enabled. Decryption is performed at the hardware level.
Memory mapping API are declared in ``esp_spi_flash.h`` and ``esp_partition.h``:
Memory mapping API are declared in ``spi_flash_mmap.h`` and ``esp_partition.h``:
- :cpp:func:`spi_flash_mmap` maps a region of physical flash addresses into instruction space or data space of the CPU.
- :cpp:func:`spi_flash_munmap` unmaps previously mapped region.
@ -273,7 +272,7 @@ API Reference - SPI Flash
.. include-build-file:: inc/esp_flash_spi_init.inc
.. include-build-file:: inc/esp_flash.inc
.. include-build-file:: inc/esp_spi_flash.inc
.. include-build-file:: inc/spi_flash_mmap.inc
.. include-build-file:: inc/spi_flash_types.inc
.. include-build-file:: inc/esp_flash_err.inc

View File

@ -32,6 +32,33 @@ ENUM type ``esp_flash_speed_t`` has been deprecated. From now on, you can direct
// Other members
};
Breaking changes in legacy APIs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to make spi_flash driver more stable, legacy spi_flash driver is removed on v5.0. Legacy spi_flash driver refers to default spi_flash driver since v3.0 and spi_flash driver with configuration option ``CONFIG_SPI_FLASH_USE_LEGACY_IMPL`` switched on on v4.0 series. The major breaking change is legacy spi_flash driver is not supported on new version anymore. Therefore, the configuration option ``CONFIG_SPI_FLASH_USE_LEGACY_IMPL`` is removed. After that, following functions will no longer exist. But meanwhile, you can use our new APIs instead.
+---------------------------------+-------------------------------+
| Removed items | Replacement |
+=================================+===============================+
| ``spi_flash_erase_sector()`` | ``esp_flash_erase_region`` |
+---------------------------------+-------------------------------+
| ``spi_flash_erase_range()`` | ``esp_flash_erase_region`` |
+---------------------------------+-------------------------------+
| ``spi_flash_write`` | ``esp_flash_write`` |
+---------------------------------+-------------------------------+
| ``spi_flash_read()`` | ``esp_flash_read`` |
+---------------------------------+-------------------------------+
| ``spi_flash_write_encrypted()`` | ``esp_flash_write_encrypted`` |
+---------------------------------+-------------------------------+
| ``spi_flash_read_encrypted`` | ``esp_flash_read_encrypted`` |
+---------------------------------+-------------------------------+
.. note::
New functions with prefix ``esp_flash`` accept an additional ``esp_flash_t*`` parameter. You can simply set it to NULL means that the function will operate the main flash(``esp_flash_default_chip``)
Header ``esp_spi_flash.h`` has been deprecated, system functions are no longer public. To make use of flash memory mapping APIs, you should include ``spi_flash_mmap.h`` instead.
ADC
---

View File

@ -1034,7 +1034,7 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的
add_library(foo bar.c fizz.cpp buzz.cpp)
if(ESP_PLATFORM)
# 在 ESP-IDF 中、 bar.c 需要包含 spi_flash 组件中的 esp_spi_flash.h
# 在 ESP-IDF 中、 bar.c 需要包含 spi_flash 组件中的 esp_flash.h
target_link_libraries(foo PRIVATE idf::spi_flash)
endif()

View File

@ -19,10 +19,9 @@ spi_flash 组件提供外部 flash 数据读取、写入、擦除和内存映射
ESP-IDF V4.0 之后的 flash API 不再是 *原子* 的。因此,如果读操作执行过程中发生写操作,且读操作和写操作的 flash 地址出现重叠,读操作返回的数据可能会包含旧数据和新数据 (新数据为写操作更新产生的数据)。
.. note::
Kconfig 选项 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` 可将 ``spi_flash_*`` 函数切换至 ESP-IDF V4.0 之前的实现。但是,如果同时使用新旧 API代码量可能会增多。
即使未启用 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL`,加密读取和加密写入操作也均使用旧实现。因此,仅有主 flash 芯片支持加密操作,外接(经 SPI1 使用其他不同片选访问,或经其它 SPI 总线访问)的 flash 芯片则不支持加密操作。硬件的限制也决定了仅有主 flash 支持从 cache 当中读取。
仅有主 flash 芯片支持加密操作,外接(经 SPI1 使用其他不同片选访问,或经其它 SPI 总线访问)的 flash 芯片则不支持加密操作。硬件的限制也决定了仅有主 flash 支持从 cache 当中读取。
Flash 功能支持情况
-----------------------------------
@ -138,7 +137,7 @@ ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序
- :cpp:func:`esp_partition_next`:将迭代器移至下一个找到的分区;
- :cpp:func:`esp_partition_iterator_release`:释放 ``esp_partition_find`` 中返回的迭代器;
- :cpp:func:`esp_partition_find_first`:返回描述 ``esp_partition_find`` 中找到的第一个分区的结构;
- :cpp:func:`esp_partition_read`:cpp:func:`esp_partition_write`:cpp:func:`esp_partition_erase_range` 等同于 :cpp:func:`spi_flash_read`、:cpp:func:`spi_flash_write`:cpp:func:`spi_flash_erase_range`,但在分区边界内执行。
- :cpp:func:`esp_partition_read`:cpp:func:`esp_partition_write`:cpp:func:`esp_partition_erase_range` 等同于 :cpp:func:`esp_flash_read`、:cpp:func:`esp_flash_write`:cpp:func:`esp_flash_erase_region`,但在分区边界内执行。
.. note::
请在应用程序代码中使用上述 ``esp_partition_*`` API 函数,而非低层级的 ``esp_flash_*`` API 函数。分区表 API 函数根据存储在分区表中的数据,进行边界检查并计算在 flash 中的正确偏移量。
@ -164,7 +163,7 @@ Flash 在 {IDF_TARGET_CACHE_SIZE} 页进行映射。内存映射硬件既可将
启用 :doc:`Flash 加密 </security/flash-encryption>` 时,使用内存映射区域从 flash 读取数据是解密 flash 的唯一方法,解密需在硬件层进行。
内存映射 API 在 ``esp_spi_flash.h````esp_partition.h`` 中声明:
内存映射 API 在 ``spi_flash_mmap.h````esp_partition.h`` 中声明:
- :cpp:func:`spi_flash_mmap`:将 flash 物理地址区域映射到 CPU 指令空间或数据空间;
- :cpp:func:`spi_flash_munmap`:取消上述区域的映射;
@ -273,7 +272,7 @@ SPI Flash API 参考
.. include-build-file:: inc/esp_flash_spi_init.inc
.. include-build-file:: inc/esp_flash.inc
.. include-build-file:: inc/esp_spi_flash.inc
.. include-build-file:: inc/spi_flash_mmap.inc
.. include-build-file:: inc/spi_flash_types.inc
.. include-build-file:: inc/esp_flash_err.inc

View File

@ -977,7 +977,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -968,7 +968,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -1113,7 +1113,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -981,7 +981,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -968,7 +968,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -1113,7 +1113,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -967,7 +967,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -1113,7 +1113,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

View File

@ -981,7 +981,6 @@ CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set
# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set
# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set
# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set
# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set
CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y

Some files were not shown because too many files have changed in this diff Show More