From 6183b555aa180b8b94759cc8b33bce5cba76d579 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 3 Jul 2023 11:41:32 +0800 Subject: [PATCH 1/2] fix(flash_mmap): fixed limited free I/D pages on ESP32S3, C2, C3 --- components/esp_rom/CMakeLists.txt | 4 +++ .../esp_rom/esp32c2/Kconfig.soc_caps.in | 4 +++ components/esp_rom/esp32c2/esp_rom_caps.h | 1 + .../esp_rom/esp32c3/Kconfig.soc_caps.in | 4 +++ components/esp_rom/esp32c3/esp_rom_caps.h | 1 + .../esp_rom/esp32h2/Kconfig.soc_caps.in | 4 +++ components/esp_rom/esp32h2/esp_rom_caps.h | 1 + .../esp_rom/esp32s3/Kconfig.soc_caps.in | 4 +++ components/esp_rom/esp32s3/esp_rom_caps.h | 1 + components/esp_rom/linker.lf | 2 ++ components/esp_rom/patches/esp_rom_mmap.c | 36 +++++++++++++++++++ .../soc/esp32c2/include/soc/ext_mem_defs.h | 2 +- .../soc/esp32c3/include/soc/ext_mem_defs.h | 2 +- .../soc/esp32h2/include/soc/ext_mem_defs.h | 2 +- components/soc/esp32s2/include/soc/mmu.h | 1 + .../soc/esp32s3/include/soc/ext_mem_defs.h | 2 +- components/soc/esp32s3/include/soc/mmu.h | 1 + components/spi_flash/flash_mmap.c | 13 +++++++ 18 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 components/esp_rom/patches/esp_rom_mmap.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 9a20457d3e..75200e16c8 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -45,6 +45,10 @@ if(CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG) list(APPEND sources "patches/esp_rom_cache_writeback_esp32s3.S") endif() +if(CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE) + list(APPEND sources "patches/esp_rom_mmap.c") +endif() + idf_component_register(SRCS ${sources} INCLUDE_DIRS ${include_dirs} PRIV_REQUIRES ${private_required_comp} diff --git a/components/esp_rom/esp32c2/Kconfig.soc_caps.in b/components/esp_rom/esp32c2/Kconfig.soc_caps.in index d676d6ce03..1806ced68a 100644 --- a/components/esp_rom/esp32c2/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c2/Kconfig.soc_caps.in @@ -42,3 +42,7 @@ config ESP_ROM_HAS_HEAP_TLSF config ESP_ROM_TLSF_CHECK_PATCH bool default y + +config ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE + bool + default y diff --git a/components/esp_rom/esp32c2/esp_rom_caps.h b/components/esp_rom/esp32c2/esp_rom_caps.h index 60706ac706..9d39e43bae 100644 --- a/components/esp_rom/esp32c2/esp_rom_caps.h +++ b/components/esp_rom/esp32c2/esp_rom_caps.h @@ -16,3 +16,4 @@ #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library #define ESP_ROM_TLSF_CHECK_PATCH (1) // ROM does not contain the patch of tlsf_check() +#define ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE (1) // ROM needs to set cache MMU size according to instruction and rodata for flash mmap diff --git a/components/esp_rom/esp32c3/Kconfig.soc_caps.in b/components/esp_rom/esp32c3/Kconfig.soc_caps.in index dddaa79ade..e234513ad4 100644 --- a/components/esp_rom/esp32c3/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c3/Kconfig.soc_caps.in @@ -46,3 +46,7 @@ config ESP_ROM_NEEDS_SWSETUP_WORKAROUND config ESP_ROM_HAS_ETS_PRINTF_BUG bool default y + +config ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE + bool + default y diff --git a/components/esp_rom/esp32c3/esp_rom_caps.h b/components/esp_rom/esp32c3/esp_rom_caps.h index 1b1c468bbf..d2b5005b06 100644 --- a/components/esp_rom/esp32c3/esp_rom_caps.h +++ b/components/esp_rom/esp32c3/esp_rom_caps.h @@ -17,3 +17,4 @@ #define ESP_ROM_GET_CLK_FREQ (1) // Get clk frequency with rom function `ets_get_cpu_frequency` #define ESP_ROM_NEEDS_SWSETUP_WORKAROUND (1) // ROM uses 32-bit time_t. A workaround is required to prevent printf functions from crashing #define ESP_ROM_HAS_ETS_PRINTF_BUG (1) // ROM has ets_printf bug when disable the ROM log either by eFuse or RTC storage register +#define ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE (1) // ROM needs to set cache MMU size according to instruction and rodata for flash mmap diff --git a/components/esp_rom/esp32h2/Kconfig.soc_caps.in b/components/esp_rom/esp32h2/Kconfig.soc_caps.in index 90b876658a..1164062b62 100644 --- a/components/esp_rom/esp32h2/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32h2/Kconfig.soc_caps.in @@ -42,3 +42,7 @@ config ESP_ROM_GET_CLK_FREQ config ESP_ROM_HAS_ETS_PRINTF_BUG bool default y + +config ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE + bool + default y diff --git a/components/esp_rom/esp32h2/esp_rom_caps.h b/components/esp_rom/esp32h2/esp_rom_caps.h index a416990d2a..f72ae90ceb 100644 --- a/components/esp_rom/esp32h2/esp_rom_caps.h +++ b/components/esp_rom/esp32h2/esp_rom_caps.h @@ -16,3 +16,4 @@ #define ESP_ROM_HAS_ERASE_0_REGION_BUG (1) // ROM has esp_flash_erase_region(size=0) bug #define ESP_ROM_GET_CLK_FREQ (1) // Get clk frequency with rom function `ets_get_cpu_frequency` #define ESP_ROM_HAS_ETS_PRINTF_BUG (1) // ROM has ets_printf bug when disable the ROM log either by eFuse or RTC storage register +#define ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE (1) // ROM needs to set cache MMU size according to instruction and rodata for flash mmap diff --git a/components/esp_rom/esp32s3/Kconfig.soc_caps.in b/components/esp_rom/esp32s3/Kconfig.soc_caps.in index ca74bc46ac..b628b8d2a7 100644 --- a/components/esp_rom/esp32s3/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32s3/Kconfig.soc_caps.in @@ -66,3 +66,7 @@ config ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG config ESP_ROM_HAS_CACHE_WRITEBACK_BUG bool default y + +config ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE + bool + default y diff --git a/components/esp_rom/esp32s3/esp_rom_caps.h b/components/esp_rom/esp32s3/esp_rom_caps.h index fe3c2bc391..9986389862 100644 --- a/components/esp_rom/esp32s3/esp_rom_caps.h +++ b/components/esp_rom/esp32s3/esp_rom_caps.h @@ -22,3 +22,4 @@ #define ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG (1) // ROM api Cache_Count_Flash_Pages will return unexpected value #define ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG (1) // ROM api Cache_Suspend_I/DCache and Cache_Freeze_I/DCache_Enable does not waiti #define ESP_ROM_HAS_CACHE_WRITEBACK_BUG (1) // ROM api Cache_WriteBack_Addr access cacheline being writen back may cause cache hit with wrong value. +#define ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE (1) // ROM needs to set cache MMU size according to instruction and rodata for flash mmap diff --git a/components/esp_rom/linker.lf b/components/esp_rom/linker.lf index b33d0c8286..cb618d04d5 100644 --- a/components/esp_rom/linker.lf +++ b/components/esp_rom/linker.lf @@ -11,3 +11,5 @@ entries: esp_rom_tlsf (noflash) if SOC_SYSTIMER_SUPPORTED = y: esp_rom_systimer (noflash) + if ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE = y: + esp_rom_mmap (noflash) diff --git a/components/esp_rom/patches/esp_rom_mmap.c b/components/esp_rom/patches/esp_rom_mmap.c new file mode 100644 index 0000000000..1d62c42c22 --- /dev/null +++ b/components/esp_rom/patches/esp_rom_mmap.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "soc/ext_mem_defs.h" + + +uint32_t Cache_Get_IROM_MMU_End(void) +{ +#if CONFIG_IDF_TARGET_ESP32S3 + return 0x800; +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 + return 0x200; +#elif CONFIG_IDF_TARGET_ESP32C2 + return 0x100; +#else + assert(false); +#endif +} + +uint32_t Cache_Get_DROM_MMU_End(void) +{ +#if CONFIG_IDF_TARGET_ESP32S3 + return 0x800; +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 + return 0x200; +#elif CONFIG_IDF_TARGET_ESP32C2 + return 0x100; +#else + assert(false); +#endif +} diff --git a/components/soc/esp32c2/include/soc/ext_mem_defs.h b/components/soc/esp32c2/include/soc/ext_mem_defs.h index 0333de5403..ed3902cb31 100644 --- a/components/soc/esp32c2/include/soc/ext_mem_defs.h +++ b/components/soc/esp32c2/include/soc/ext_mem_defs.h @@ -51,7 +51,7 @@ extern "C" { #define CACHE_IROM_MMU_END Cache_Get_IROM_MMU_End() #define CACHE_IROM_MMU_SIZE (CACHE_IROM_MMU_END - CACHE_IROM_MMU_START) -#define CACHE_DROM_MMU_START CACHE_IROM_MMU_END +#define CACHE_DROM_MMU_START 0 #define CACHE_DROM_MMU_END Cache_Get_DROM_MMU_End() #define CACHE_DROM_MMU_SIZE (CACHE_DROM_MMU_END - CACHE_DROM_MMU_START) diff --git a/components/soc/esp32c3/include/soc/ext_mem_defs.h b/components/soc/esp32c3/include/soc/ext_mem_defs.h index 3e10ac1f6b..7cea495ab8 100644 --- a/components/soc/esp32c3/include/soc/ext_mem_defs.h +++ b/components/soc/esp32c3/include/soc/ext_mem_defs.h @@ -49,7 +49,7 @@ extern "C" { #define CACHE_IROM_MMU_END Cache_Get_IROM_MMU_End() #define CACHE_IROM_MMU_SIZE (CACHE_IROM_MMU_END - CACHE_IROM_MMU_START) -#define CACHE_DROM_MMU_START CACHE_IROM_MMU_END +#define CACHE_DROM_MMU_START 0 #define CACHE_DROM_MMU_END Cache_Get_DROM_MMU_End() #define CACHE_DROM_MMU_SIZE (CACHE_DROM_MMU_END - CACHE_DROM_MMU_START) diff --git a/components/soc/esp32h2/include/soc/ext_mem_defs.h b/components/soc/esp32h2/include/soc/ext_mem_defs.h index 164d45d4f8..18427bca62 100644 --- a/components/soc/esp32h2/include/soc/ext_mem_defs.h +++ b/components/soc/esp32h2/include/soc/ext_mem_defs.h @@ -49,7 +49,7 @@ extern "C" { #define CACHE_IROM_MMU_END Cache_Get_IROM_MMU_End() #define CACHE_IROM_MMU_SIZE (CACHE_IROM_MMU_END - CACHE_IROM_MMU_START) -#define CACHE_DROM_MMU_START CACHE_IROM_MMU_END +#define CACHE_DROM_MMU_START 0 #define CACHE_DROM_MMU_END Cache_Get_DROM_MMU_End() #define CACHE_DROM_MMU_SIZE (CACHE_DROM_MMU_END - CACHE_DROM_MMU_START) diff --git a/components/soc/esp32s2/include/soc/mmu.h b/components/soc/esp32s2/include/soc/mmu.h index c1ef03b4c4..1400e65995 100644 --- a/components/soc/esp32s2/include/soc/mmu.h +++ b/components/soc/esp32s2/include/soc/mmu.h @@ -22,6 +22,7 @@ extern "C" { #define SOC_MMU_DROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t)) #define SOC_MMU_ADDR_MASK MMU_VALID_VAL_MASK #define SOC_MMU_PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH) +#define SOC_MMU_PAGE_IN_PSRAM(page) ((page) | MMU_ACCESS_SPIRAM) #define SOC_MMU_VADDR1_START_ADDR SOC_IROM_MASK_LOW #define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE ((SOC_MMU_VADDR1_FIRST_USABLE_ADDR - SOC_MMU_VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + SOC_MMU_IROM0_PAGES_START) #define SOC_MMU_VADDR0_START_ADDR SOC_DROM_LOW diff --git a/components/soc/esp32s3/include/soc/ext_mem_defs.h b/components/soc/esp32s3/include/soc/ext_mem_defs.h index 0260c7bb81..46a53fa080 100644 --- a/components/soc/esp32s3/include/soc/ext_mem_defs.h +++ b/components/soc/esp32s3/include/soc/ext_mem_defs.h @@ -48,7 +48,7 @@ extern "C" { #define CACHE_IROM_MMU_END Cache_Get_IROM_MMU_End() #define CACHE_IROM_MMU_SIZE (CACHE_IROM_MMU_END - CACHE_IROM_MMU_START) -#define CACHE_DROM_MMU_START CACHE_IROM_MMU_END +#define CACHE_DROM_MMU_START 0 #define CACHE_DROM_MMU_END Cache_Get_DROM_MMU_End() #define CACHE_DROM_MMU_SIZE (CACHE_DROM_MMU_END - CACHE_DROM_MMU_START) diff --git a/components/soc/esp32s3/include/soc/mmu.h b/components/soc/esp32s3/include/soc/mmu.h index 81aafdf4d3..599e9e43b1 100644 --- a/components/soc/esp32s3/include/soc/mmu.h +++ b/components/soc/esp32s3/include/soc/mmu.h @@ -22,6 +22,7 @@ extern "C" { #define SOC_MMU_DROM0_PAGES_END (CACHE_DROM_MMU_END / sizeof(uint32_t)) #define SOC_MMU_ADDR_MASK MMU_VALID_VAL_MASK #define SOC_MMU_PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH) +#define SOC_MMU_PAGE_IN_PSRAM(page) ((page) | MMU_ACCESS_SPIRAM) #define SOC_MMU_VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW #define SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE SOC_MMU_IROM0_PAGES_START #define SOC_MMU_VADDR0_START_ADDR (SOC_DROM_LOW + (SOC_MMU_DROM0_PAGES_START * SPI_FLASH_MMU_PAGE_SIZE)) diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index e5ee1250bc..7950be40fb 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -198,6 +198,13 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp for (pos = start; pos < start + page_count; ++pos, ++pageno) { int table_val = (int) mmu_ll_read_entry(MMU_TABLE_CORE0, pos); uint8_t refcnt = s_mmap_page_refcnt[pos]; + +#if !CONFIG_IDF_TARGET_ESP32 && SOC_SPIRAM_SUPPORTED + if (table_val == SOC_MMU_PAGE_IN_PSRAM(pages[pageno])) { + break; + } +#endif //#if !CONFIG_IDF_TARGET_ESP32 + if (refcnt != 0 && table_val != SOC_MMU_PAGE_IN_FLASH(pages[pageno])) { break; } @@ -219,6 +226,12 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp #if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32 uint32_t entry_app = mmu_ll_read_entry(MMU_TABLE_CORE1, i); #endif + if (s_mmap_page_refcnt[i] == 0) { + assert(mmu_ll_get_entry_is_invalid(MMU_TABLE_CORE0, i)); +#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32 + assert(mmu_ll_get_entry_is_invalid(MMU_TABLE_CORE1, i)); +#endif + } assert(s_mmap_page_refcnt[i] == 0 || (entry_pro == SOC_MMU_PAGE_IN_FLASH(pages[pageno]) #if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32 From 53b1c2a2e63aadd4d0b71de0898673f165722a5d Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 3 Jul 2023 11:46:51 +0800 Subject: [PATCH 2/2] test(flash_mmap): test flash mmap pages --- components/spi_flash/test/test_mmap.c | 4 + .../system/flash_mmap/CMakeLists.txt | 6 + tools/test_apps/system/flash_mmap/README.md | 7 + .../system/flash_mmap/main/CMakeLists.txt | 3 + .../system/flash_mmap/main/test_flash_mmap.c | 162 ++++++++++++++++++ .../system/flash_mmap/partitions.csv | 6 + .../system/flash_mmap/pytest_flash_mmap.py | 40 +++++ .../system/flash_mmap/sdkconfig.ci.f4r8 | 7 + .../system/flash_mmap/sdkconfig.ci.psram | 1 + .../system/flash_mmap/sdkconfig.ci.release | 3 + .../system/flash_mmap/sdkconfig.defaults | 5 + 11 files changed, 244 insertions(+) create mode 100644 tools/test_apps/system/flash_mmap/CMakeLists.txt create mode 100644 tools/test_apps/system/flash_mmap/README.md create mode 100644 tools/test_apps/system/flash_mmap/main/CMakeLists.txt create mode 100644 tools/test_apps/system/flash_mmap/main/test_flash_mmap.c create mode 100644 tools/test_apps/system/flash_mmap/partitions.csv create mode 100644 tools/test_apps/system/flash_mmap/pytest_flash_mmap.py create mode 100644 tools/test_apps/system/flash_mmap/sdkconfig.ci.f4r8 create mode 100644 tools/test_apps/system/flash_mmap/sdkconfig.ci.psram create mode 100644 tools/test_apps/system/flash_mmap/sdkconfig.ci.release create mode 100644 tools/test_apps/system/flash_mmap/sdkconfig.defaults diff --git a/components/spi_flash/test/test_mmap.c b/components/spi_flash/test/test_mmap.c index 609be13e30..7dc3e8d104 100644 --- a/components/spi_flash/test/test_mmap.c +++ b/components/spi_flash/test/test_mmap.c @@ -378,7 +378,9 @@ TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash][mmap]") uint32_t phys = spi_flash_cache2phys(esp_partition_find); TEST_ASSERT_NOT_EQUAL(SPI_FLASH_CACHE2PHYS_FAIL, phys); TEST_ASSERT_EQUAL_PTR(esp_partition_find, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_INST)); +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_DATA)); +#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 /* Read the flash @ 'phys' and compare it to the data we get via regular cache access */ spi_flash_read_maybe_encrypted(phys, buf, sizeof(buf)); @@ -394,7 +396,9 @@ TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash][mmap]") TEST_ASSERT_NOT_EQUAL(SPI_FLASH_CACHE2PHYS_FAIL, phys); TEST_ASSERT_EQUAL_PTR(&constant_data, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_DATA)); +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_INST)); +#endif /* Read the flash @ 'phys' and compare it to the data we get via normal cache access */ spi_flash_read_maybe_encrypted(phys, buf, sizeof(constant_data)); diff --git a/tools/test_apps/system/flash_mmap/CMakeLists.txt b/tools/test_apps/system/flash_mmap/CMakeLists.txt new file mode 100644 index 0000000000..3e939a6113 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(test_flash_mmap) diff --git a/tools/test_apps/system/flash_mmap/README.md b/tools/test_apps/system/flash_mmap/README.md new file mode 100644 index 0000000000..e066dc36d2 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/README.md @@ -0,0 +1,7 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | + +This project tests if Flash and PSRAM can work under different configurations. +To add new configuration, create one more sdkconfig.ci.NAME file in this directory. + +If you need to test for anything other than flash and psram, create another test project. diff --git a/tools/test_apps/system/flash_mmap/main/CMakeLists.txt b/tools/test_apps/system/flash_mmap/main/CMakeLists.txt new file mode 100644 index 0000000000..0c38cf0c9e --- /dev/null +++ b/tools/test_apps/system/flash_mmap/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "test_flash_mmap.c" + INCLUDE_DIRS "." + PRIV_REQUIRES unity spi_flash esp_partition) diff --git a/tools/test_apps/system/flash_mmap/main/test_flash_mmap.c b/tools/test_apps/system/flash_mmap/main/test_flash_mmap.c new file mode 100644 index 0000000000..a04a04fd24 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/main/test_flash_mmap.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_check.h" +#include "esp_attr.h" +#include "esp_flash.h" +#include "esp_partition.h" +#include "spi_flash_mmap.h" + +const static char *TAG = "MMAP_TEST"; + +#define TEST_BLOCK_SIZE CONFIG_MMU_PAGE_SIZE + +typedef struct test_block_info_ { + uint32_t vaddr; + spi_flash_mmap_handle_t handle; + LIST_ENTRY(test_block_info_) entries; +} test_block_info_t; + +static LIST_HEAD(test_block_list_head_, test_block_info_) test_block_head; +static DRAM_ATTR uint8_t sector_buf[TEST_BLOCK_SIZE]; + +static const esp_partition_t *s_get_partition(void) +{ + //Find the "storage1" partition defined in `partitions.csv` + const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1"); + if (!result) { + ESP_LOGE(TAG, "Can't find the partition, please define it correctly in `partitions.csv`"); + abort(); + } + return result; +} + + +static void s_fill_random_data(uint8_t *buffer, size_t size, int random_seed) +{ + srand(random_seed); + for (int i = 0 ; i < size; i++) { + buffer[i] = rand() % 0xff; + } +} + +static bool s_test_mmap_data_by_random(uint8_t *mblock_ptr, size_t size, int random_seed) +{ + srand(random_seed); + uint8_t *test_ptr = mblock_ptr; + + for (int i = 0; i < size; i++) { + uint8_t test_data = rand() % 0xff; + if(test_data != test_ptr[i]) { + printf("i: %d\n", i); + printf("test_data: %d\n", test_data); + printf("test_ptr[%d]: %d\n", i, test_ptr[i]); + printf("sector_buf[%d]: %d\n", i, sector_buf[i]); + ESP_EARLY_LOGE(TAG, "FAIL!!!!!!"); + return false; + } + } + return true; +} + +static void s_print_free_pages(void) +{ + uint32_t free_i_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_INST); + uint32_t free_d_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + printf("free_i_pages: 0d%"PRId32"\n", free_i_pages); + printf("free_d_pages: 0d%"PRId32"\n", free_d_pages); +} + +void app_main(void) +{ + //Get the partition used for SPI1 erase operation + const esp_partition_t *part = s_get_partition(); + ESP_LOGI(TAG, "found partition '%s' at offset 0x%"PRIx32" with size 0x%"PRIx32, part->label, part->address, part->size); + + //Erase whole region + TEST_ESP_OK(esp_flash_erase_region(part->flash_chip, part->address, part->size)); + + ESP_LOGI(TAG, "TEST_BLOCK_SIZE: 0x%x", TEST_BLOCK_SIZE); + s_print_free_pages(); + + uint32_t offset = 0; + int test_seed = 299; + while (1) { + s_fill_random_data(sector_buf, sizeof(sector_buf), test_seed); + ESP_LOGI(TAG, "rand seed: %d, write flash addr: %p...", test_seed, (void *)(part->address + offset)); + TEST_ESP_OK(esp_flash_write(part->flash_chip, sector_buf, (part->address + offset), sizeof(sector_buf))); + + test_seed++; + offset += TEST_BLOCK_SIZE; + + if (offset == part->size) { + break; + } + } + + esp_err_t ret = ESP_FAIL; + int count = 0; + LIST_INIT(&test_block_head); + + offset = 0; + test_seed = 299; + + while (1) { + test_block_info_t *block_info = heap_caps_calloc(1, sizeof(test_block_info_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + TEST_ASSERT(block_info && "no mem"); + + spi_flash_mmap_handle_t handle; + const void *ptr = NULL; + ret = spi_flash_mmap(part->address + offset, TEST_BLOCK_SIZE, SPI_FLASH_MMAP_DATA, &ptr, &handle); + if (ret == ESP_OK) { + ESP_LOGI(TAG, "ptr is %p", ptr); + + s_fill_random_data(sector_buf, sizeof(sector_buf), test_seed); + bool success = s_test_mmap_data_by_random((uint8_t *)ptr, sizeof(sector_buf), test_seed); + TEST_ASSERT(success); + } else if (ret == ESP_ERR_NOT_FOUND) { + free(block_info); + break; + } else { + ESP_LOGE(TAG, "ret: 0x%x", ret); + TEST_ASSERT(false); + } + + block_info->vaddr = (uint32_t)ptr; + block_info->handle = handle; + LIST_INSERT_HEAD(&test_block_head, block_info, entries); + count++; + test_seed++; + offset += TEST_BLOCK_SIZE; + + if (offset == part->size) { + break; + } + } + + ESP_LOGI(TAG, "no more free block / free flash size, finish test, test block size: 0x%x, count: 0d%d", TEST_BLOCK_SIZE, count); + s_print_free_pages(); + + test_block_info_t *block_to_free = LIST_FIRST(&test_block_head); + test_block_info_t *temp = NULL; + while (block_to_free) { + temp = block_to_free; + spi_flash_munmap(block_to_free->handle); + block_to_free = LIST_NEXT(block_to_free, entries); + free(temp); + } + s_print_free_pages(); + + printf("flash mmap test success\n"); +} diff --git a/tools/test_apps/system/flash_mmap/partitions.csv b/tools/test_apps/system/flash_mmap/partitions.csv new file mode 100644 index 0000000000..488c92b9f4 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/partitions.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage1, data, fat, , 896K, diff --git a/tools/test_apps/system/flash_mmap/pytest_flash_mmap.py b/tools/test_apps/system/flash_mmap/pytest_flash_mmap.py new file mode 100644 index 0000000000..105b366ab9 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/pytest_flash_mmap.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import os +import pathlib + +import pytest +from pytest_embedded import Dut + +# For F4R8 board (Quad Flash and Octal PSRAM) +MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*')] + + +@pytest.mark.esp32s3 +@pytest.mark.MSPI_F4R8 +@pytest.mark.parametrize('config', MSPI_F4R8_configs, indirect=True) +def test_mmap_flash4_psram8(dut: Dut) -> None: + dut.expect_exact('flash mmap test success', timeout=300) + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.parametrize('config', [ + 'psram', +], indirect=True) +def test_mmap_psram(dut: Dut) -> None: + dut.expect_exact('flash mmap test success', timeout=300) + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s3 +@pytest.mark.parametrize('config', [ + 'release', +], indirect=True) +def test_mmap(dut: Dut) -> None: + dut.expect_exact('flash mmap test success', timeout=300) diff --git a/tools/test_apps/system/flash_mmap/sdkconfig.ci.f4r8 b/tools/test_apps/system/flash_mmap/sdkconfig.ci.f4r8 new file mode 100644 index 0000000000..2d48b1a2e4 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/sdkconfig.ci.f4r8 @@ -0,0 +1,7 @@ +# F4R8, Flash 80M SDR, PSRAM 80M DDR + +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y diff --git a/tools/test_apps/system/flash_mmap/sdkconfig.ci.psram b/tools/test_apps/system/flash_mmap/sdkconfig.ci.psram new file mode 100644 index 0000000000..cc641ea603 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/sdkconfig.ci.psram @@ -0,0 +1 @@ +CONFIG_SPIRAM=y diff --git a/tools/test_apps/system/flash_mmap/sdkconfig.ci.release b/tools/test_apps/system/flash_mmap/sdkconfig.ci.release new file mode 100644 index 0000000000..3cff15d49e --- /dev/null +++ b/tools/test_apps/system/flash_mmap/sdkconfig.ci.release @@ -0,0 +1,3 @@ +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/tools/test_apps/system/flash_mmap/sdkconfig.defaults b/tools/test_apps/system/flash_mmap/sdkconfig.defaults new file mode 100644 index 0000000000..ad42538001 --- /dev/null +++ b/tools/test_apps/system/flash_mmap/sdkconfig.defaults @@ -0,0 +1,5 @@ +CONFIG_ESP_TASK_WDT_EN=n + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"