diff --git a/components/esp_hw_support/dma/gdma.c b/components/esp_hw_support/dma/gdma.c index 101ccf4d39..1d55e466d5 100644 --- a/components/esp_hw_support/dma/gdma.c +++ b/components/esp_hw_support/dma/gdma.c @@ -18,6 +18,7 @@ #include "esp_memory_utils.h" #include "esp_private/periph_ctrl.h" #include "gdma_priv.h" +#include "hal/cache_hal.h" static const char *TAG = "gdma"; @@ -290,6 +291,7 @@ esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_t ESP_GOTO_ON_FALSE((sram_alignment & (sram_alignment - 1)) == 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid sram alignment: %zu", sram_alignment); #if SOC_GDMA_SUPPORT_PSRAM + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); int block_size_index = 0; switch (psram_alignment) { case 64: // 64 Bytes alignment @@ -303,12 +305,13 @@ esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_t break; case 0: // no alignment is requirement block_size_index = GDMA_LL_EXT_MEM_BK_SIZE_16B; - psram_alignment = SOC_GDMA_PSRAM_MIN_ALIGN; // fall back to minimal alignment + psram_alignment = data_cache_line_size; // fall back to use the same size of the psram data cache line size break; default: ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid psram alignment: %zu", psram_alignment); break; } + ESP_GOTO_ON_FALSE(((psram_alignment % data_cache_line_size) == 0), ESP_ERR_INVALID_ARG, err, TAG, "psram alignment (%d)B should be multiple of the data cache line size (%d)B", psram_alignment, data_cache_line_size); #endif // #if SOC_GDMA_SUPPORT_PSRAM if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX) { diff --git a/components/esp_lcd/CMakeLists.txt b/components/esp_lcd/CMakeLists.txt index cb1cbc99e1..535aebda00 100644 --- a/components/esp_lcd/CMakeLists.txt +++ b/components/esp_lcd/CMakeLists.txt @@ -7,7 +7,7 @@ set(srcs "src/esp_lcd_common.c" "src/esp_lcd_panel_st7789.c" "src/esp_lcd_panel_ops.c") set(includes "include" "interface") -set(priv_requires "driver") +set(priv_requires "driver" "esp_mm") if(CONFIG_SOC_I2S_LCD_I80_VARIANT) list(APPEND srcs "src/esp_lcd_panel_io_i2s.c") diff --git a/components/esp_lcd/src/esp_lcd_panel_rgb.c b/components/esp_lcd/src/esp_lcd_panel_rgb.c index ae61c4f0cc..d3415fa701 100644 --- a/components/esp_lcd/src/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/src/esp_lcd_panel_rgb.c @@ -42,6 +42,7 @@ #include "hal/lcd_ll.h" #include "hal/gdma_ll.h" #include "rom/cache.h" +#include "esp_cache.h" #if CONFIG_LCD_RGB_ISR_IRAM_SAFE #define LCD_RGB_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED) @@ -798,7 +799,7 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int if (rgb_panel->flags.fb_in_psram && !rgb_panel->bb_size) { // CPU writes data to PSRAM through DCache, data in PSRAM might not get updated, so write back // Note that if we use a bounce buffer, the data gets read by the CPU as well so no need to write back - Cache_WriteBack_Addr((uint32_t)(flush_ptr), bytes_to_flush); + esp_cache_msync((void *)(flush_ptr), (size_t)bytes_to_flush, 0); } if (!rgb_panel->bb_size) { @@ -954,11 +955,7 @@ static IRAM_ATTR bool lcd_rgb_panel_fill_bounce_buffer(esp_rgb_panel_t *panel, u if (panel->flags.bb_invalidate_cache) { // We don't need the bytes we copied from the psram anymore // Make sure that if anything happened to have changed (because the line already was in cache) we write the data back. - Cache_WriteBack_Addr((uint32_t)&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], panel->bb_size); - // Invalidate the data. - // Note: possible race: perhaps something on the other core can squeeze a write between this and the writeback, - // in which case that data gets discarded. - Cache_Invalidate_Addr((uint32_t)&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], panel->bb_size); + esp_cache_msync(&panel->fbs[panel->bb_fb_index][panel->bounce_pos_px * bytes_per_pixel], (size_t)panel->bb_size, ESP_CACHE_MSYNC_FLAG_INVALIDATE); } } panel->bounce_pos_px += panel->bb_size / bytes_per_pixel; diff --git a/components/esp_mm/CMakeLists.txt b/components/esp_mm/CMakeLists.txt index 9c7bf0419e..50c086159a 100644 --- a/components/esp_mm/CMakeLists.txt +++ b/components/esp_mm/CMakeLists.txt @@ -9,16 +9,15 @@ set(srcs) if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) set(srcs "esp_mmu_map.c" - "port/${target}/ext_mem_layout.c") + "port/${target}/ext_mem_layout.c" + "esp_cache.c") + + if(CONFIG_IDF_TARGET_ESP32) + list(APPEND srcs "cache_esp32.c") + endif() endif() idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${includes} - PRIV_REQUIRES ${priv_requires}) - -if(NOT BOOTLOADER_BUILD) - if(CONFIG_SPIRAM) - # Use esp_psram for `esp_psram_extram_writeback_cache()` on ESP32 - idf_component_optional_requires(PRIVATE esp_psram) - endif() -endif() + PRIV_REQUIRES ${priv_requires} + LDFRAGMENTS linker.lf) diff --git a/components/esp_mm/cache_esp32.c b/components/esp_mm/cache_esp32.c new file mode 100644 index 0000000000..665023a82b --- /dev/null +++ b/components/esp_mm/cache_esp32.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "rom/cache.h" +#include "esp_private/esp_cache_esp32_private.h" + + +static cache_driver_t s_cache_drv = { + Cache_Flush, + NULL, +}; + + +void cache_register_writeback(cache_driver_t *func) +{ + s_cache_drv.cache_writeback_psram = func->cache_writeback_psram; +} + + +void cache_sync(void) +{ + if (s_cache_drv.cache_writeback_psram) { + s_cache_drv.cache_writeback_psram(); + } + + s_cache_drv.cache_flush(0); +#if !CONFIG_FREERTOS_UNICORE + s_cache_drv.cache_flush(1); +#endif // !CONFIG_FREERTOS_UNICORE +} diff --git a/components/esp_mm/esp_cache.c b/components/esp_mm/esp_cache.c new file mode 100644 index 0000000000..d66e235a2f --- /dev/null +++ b/components/esp_mm/esp_cache.c @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "esp_check.h" +#include "esp_log.h" +#include "soc/soc_caps.h" +#include "hal/mmu_hal.h" +#include "hal/cache_hal.h" +#include "esp_cache.h" +#include "esp_private/critical_section.h" + + +static const char *TAG = "cache"; + +#if SOC_CACHE_WRITEBACK_SUPPORTED +DEFINE_CRIT_SECTION_LOCK_STATIC(s_spinlock); + +void s_cache_freeze(void) +{ +#if SOC_CACHE_FREEZE_SUPPORTED + cache_hal_freeze(CACHE_TYPE_DATA | CACHE_TYPE_INSTRUCTION); +#endif + + /** + * For writeback supported, but the freeze not supported chip (Now only S2), + * as it's single core, the critical section is enough to prevent preemption from an non-IRAM ISR + */ +} + +void s_cache_unfreeze(void) +{ +#if SOC_CACHE_FREEZE_SUPPORTED + cache_hal_unfreeze(CACHE_TYPE_DATA | CACHE_TYPE_INSTRUCTION); +#endif + + /** + * Similarly, for writeback supported, but the freeze not supported chip (Now only S2), + * we don't need to do more + */ +} +#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED + + +esp_err_t esp_cache_msync(void *addr, size_t size, int flags) +{ + ESP_RETURN_ON_FALSE_ISR(addr, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + ESP_RETURN_ON_FALSE_ISR(mmu_hal_check_valid_ext_vaddr_region(0, (uint32_t)addr, size, MMU_VADDR_DATA), ESP_ERR_INVALID_ARG, TAG, "invalid address"); + +#if SOC_CACHE_WRITEBACK_SUPPORTED + if ((flags & ESP_CACHE_MSYNC_FLAG_UNALIGNED) == 0) { + esp_os_enter_critical_safe(&s_spinlock); + uint32_t data_cache_line_size = cache_hal_get_cache_line_size(CACHE_TYPE_DATA); + esp_os_exit_critical_safe(&s_spinlock); + + ESP_RETURN_ON_FALSE_ISR(((uint32_t)addr % data_cache_line_size) == 0, ESP_ERR_INVALID_ARG, TAG, "start address isn't aligned with the data cache line size (%d)B", data_cache_line_size); + ESP_RETURN_ON_FALSE_ISR((size % data_cache_line_size) == 0, ESP_ERR_INVALID_ARG, TAG, "size isn't aligned with the data cache line size (%d)B", data_cache_line_size); + ESP_RETURN_ON_FALSE_ISR((((uint32_t)addr + size) % data_cache_line_size) == 0, ESP_ERR_INVALID_ARG, TAG, "end address isn't aligned with the data cache line size (%d)B", data_cache_line_size); + } + + uint32_t vaddr = (uint32_t)addr; + + esp_os_enter_critical_safe(&s_spinlock); + s_cache_freeze(); + + cache_hal_writeback_addr(vaddr, size); + if (flags & ESP_CACHE_MSYNC_FLAG_INVALIDATE) { + cache_hal_invalidate_addr(vaddr, size); + } + + s_cache_unfreeze(); + esp_os_exit_critical_safe(&s_spinlock); +#endif + + return ESP_OK; +} diff --git a/components/esp_mm/esp_mmu_map.c b/components/esp_mm/esp_mmu_map.c index 29d158603e..c8ec6c6a8c 100644 --- a/components/esp_mm/esp_mmu_map.c +++ b/components/esp_mm/esp_mmu_map.c @@ -23,14 +23,8 @@ #include "hal/mmu_hal.h" #include "hal/mmu_ll.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/cache.h" -#endif #include "esp_private/cache_utils.h" -#if CONFIG_SPIRAM -#include "esp_private/esp_psram_extram.h" -#endif - +#include "esp_private/esp_cache_esp32_private.h" #include "esp_private/esp_mmu_map_private.h" #include "ext_mem_layout.h" #include "esp_mmu_map.h" @@ -333,29 +327,15 @@ esp_err_t esp_mmu_map_reserve_block_with_caps(size_t size, mmu_mem_caps_t caps, } -#if CONFIG_IDF_TARGET_ESP32 -/** - * On ESP32, due to hardware limitation, we don't have an - * easy way to sync between cache and external memory wrt - * certain range. So we do a full sync here - */ -static void IRAM_ATTR NOINLINE_ATTR s_cache_sync(void) -{ -#if CONFIG_SPIRAM - esp_psram_extram_writeback_cache(); -#endif //#if CONFIG_SPIRAM - Cache_Flush(0); -#if !CONFIG_FREERTOS_UNICORE - Cache_Flush(1); -#endif // !CONFIG_FREERTOS_UNICORE -} -#endif //#if CONFIG_IDF_TARGET_ESP32 - - static void IRAM_ATTR NOINLINE_ATTR s_do_cache_invalidate(uint32_t vaddr_start, uint32_t size) { #if CONFIG_IDF_TARGET_ESP32 - s_cache_sync(); + /** + * On ESP32, due to hardware limitation, we don't have an + * easy way to sync between cache and external memory wrt + * certain range. So we do a full sync here + */ + cache_sync(); #else //Other chips cache_hal_invalidate_addr(vaddr_start, size); #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_mm/include/esp_cache.h b/components/esp_mm/include/esp_cache.h new file mode 100644 index 0000000000..800e886569 --- /dev/null +++ b/components/esp_mm/include/esp_cache.h @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_err.h" +#include "esp_bit_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Cache msync flags + */ +/** + * @brief Do an invalidation with the values that just written + */ +#define ESP_CACHE_MSYNC_FLAG_INVALIDATE BIT(0) +/** + * @brief Allow writeback a block that are not aligned to the data cache line size + */ +#define ESP_CACHE_MSYNC_FLAG_UNALIGNED BIT(1) + + +/** + * @brief Memory sync between Cache and external memory + * + * - For cache writeback supported chips (you can refer to SOC_CACHE_WRITEBACK_SUPPORTED in soc_caps.h) + * - this API will do a writeback to synchronise between cache and the PSRAM + * - with ESP_CACHE_MSYNC_FLAG_INVALIDATE, this API will also invalidate the values that just written + * - note: although ESP32 is with PSRAM, but cache writeback isn't supported, so this API will do nothing on ESP32 + * - For other chips, this API will do nothing. The out-of-sync should be already dealt by the SDK + * + * This API is cache-safe and thread-safe + * + * @note You should not call this during any Flash operations (e.g. esp_flash APIs, nvs and some other APIs that are based on esp_flash APIs) + * @note If XIP_From_PSRAM is enabled (by enabling both CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA), you can call this API during Flash operations + * + * @param[in] Starting address to do the msync + * @param[in] Size to do the msync + * @param[in] Flags, see `ESP_CACHE_MSYNC_FLAG_x` + * + * @return + * - ESP_OK: + * - Successful msync + * - If this chip doesn't support cache writeback, if the input addr is a cache supported one, this API will return ESP_OK + * - ESP_ERR_INVALID_ARG: Invalid argument, not cache supported addr, see printed logs + */ +esp_err_t esp_cache_msync(void *addr, size_t size, int flags); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_mm/include/esp_private/esp_cache_esp32_private.h b/components/esp_mm/include/esp_private/esp_cache_esp32_private.h new file mode 100644 index 0000000000..a8642daf5c --- /dev/null +++ b/components/esp_mm/include/esp_private/esp_cache_esp32_private.h @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Private header for cache drivers, where cache functionality requires other components + * + * @note Now only esp32, can be applied to other similar chips + */ +typedef struct cache_driver_s cache_driver_t; + +/** + * @brief Cache driver + */ +struct cache_driver_s { + + /** + * @brief Cache flush + * + * @param[in] cpu_no CPU id + */ + void (*cache_flush)(int cpu_no); + + /** + * @brief Cache writeback to psram + */ + void (*cache_writeback_psram)(void); +}; + +/** + * @brief Register cache writeback + * + * @param[in] func Cache driver + */ +void cache_register_writeback(cache_driver_t *func); + +/** + * @brief Cache sync + * + * @note This API only do cache sync, but doesn't guarantee concurrent access to cache + * @note Do not use in your application + */ +void cache_sync(void); + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_mm/linker.lf b/components/esp_mm/linker.lf new file mode 100644 index 0000000000..a48fe34cbf --- /dev/null +++ b/components/esp_mm/linker.lf @@ -0,0 +1,9 @@ +[mapping:esp_mm] +archive: libesp_mm.a +entries: + + if APP_BUILD_TYPE_PURE_RAM_APP = n: + esp_cache (noflash) + + if IDF_TARGET_ESP32 = y: + cache_esp32 (noflash) diff --git a/components/esp_mm/test_apps/mmap/CMakeLists.txt b/components/esp_mm/test_apps/mm/CMakeLists.txt similarity index 89% rename from components/esp_mm/test_apps/mmap/CMakeLists.txt rename to components/esp_mm/test_apps/mm/CMakeLists.txt index 04ae1b20f5..1b3c447e12 100644 --- a/components/esp_mm/test_apps/mmap/CMakeLists.txt +++ b/components/esp_mm/test_apps/mm/CMakeLists.txt @@ -4,13 +4,13 @@ cmake_minimum_required(VERSION 3.16) set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(mmap_test) +project(mm_test) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py --rtl-dir ${CMAKE_BINARY_DIR}/esp-idf/esp_mm/ - --elf-file ${CMAKE_BINARY_DIR}/mmap_test.elf + --elf-file ${CMAKE_BINARY_DIR}/mm_test.elf find-refs --from-sections=.iram0.text --to-sections=.flash.text,.flash.rodata diff --git a/components/esp_mm/test_apps/mmap/README.md b/components/esp_mm/test_apps/mm/README.md similarity index 100% rename from components/esp_mm/test_apps/mmap/README.md rename to components/esp_mm/test_apps/mm/README.md diff --git a/components/esp_mm/test_apps/mm/main/CMakeLists.txt b/components/esp_mm/test_apps/mm/main/CMakeLists.txt new file mode 100644 index 0000000000..dc6dec0ada --- /dev/null +++ b/components/esp_mm/test_apps/mm/main/CMakeLists.txt @@ -0,0 +1,14 @@ +set(srcs "test_app_main.c") + +list(APPEND srcs "test_mmap.c") + +if(CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED) + list(APPEND srcs "test_cache_msync.c") +endif() + + +# In order for the cases defined by `TEST_CASE` to be linked into the final elf, +# the component can be registered as WHOLE_ARCHIVE +idf_component_register(SRCS ${srcs} + PRIV_REQUIRES test_utils spi_flash esp_mm driver esp_timer + WHOLE_ARCHIVE) diff --git a/components/esp_mm/test_apps/mm/main/test_app_main.c b/components/esp_mm/test_apps/mm/main/test_app_main.c new file mode 100644 index 0000000000..03bdfb96dc --- /dev/null +++ b/components/esp_mm/test_apps/mm/main/test_app_main.c @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_utils.h" +#include "esp_heap_caps.h" + +/** + * Hardware related tests, e.g. + * - traversing all vaddr range to check their attributes + * + * These tests need certain number of internal resources (heap memory), as they uses up the vaddr ranges + * On ESP32, it should be around 450 + * On ESP32S2, it should be around 600 + * On other chips, it should be around 400 + */ +#define TEST_MEMORY_LEAK_THRESHOLD (-650) + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + +void app_main(void) +{ + /* + _____ ___________ ___ ______ ___ ___ ______ _____ ___ + | ___/ ___| ___ \ | \/ || \/ ||_ _| ___/ ___|_ _| + | |__ \ `--.| |_/ / | . . || . . | | | | |__ \ `--. | | + | __| `--. \ __/ | |\/| || |\/| | | | | __| `--. \ | | + | |___/\__/ / | | | | || | | | | | | |___/\__/ / | | + \____/\____/\_| \_| |_/\_| |_/ \_/ \____/\____/ \_/ + */ + + printf(" _____ ___________ ___ ______ ___ ___ ______ _____ ___\r\n"); + printf("| ___/ ___| ___ \\ | \\/ || \\/ ||_ _| ___/ ___|_ _|\r\n"); + printf("| |__ \\ `--.| |_/ / | . . || . . | | | | |__ \\ `--. | |\r\n"); + printf("| __| `--. \\ __/ | |\\/| || |\\/| | | | | __| `--. \\ | |\r\n"); + printf("| |___/\\__/ / | | | | || | | | | | | |___/\\__/ / | |\r\n"); + printf("\\____/\\____/\\_| \\_| |_/\\_| |_/ \\_/ \\____/\\____/ \\_/\r\n"); + + + unity_run_menu(); +} diff --git a/components/esp_mm/test_apps/mm/main/test_cache_msync.c b/components/esp_mm/test_apps/mm/main/test_cache_msync.c new file mode 100644 index 0000000000..d87748d7fa --- /dev/null +++ b/components/esp_mm/test_apps/mm/main/test_cache_msync.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include +#include "inttypes.h" +#include "esp_log.h" +#include "esp_attr.h" +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_rom_sys.h" +#include "esp_memory_utils.h" +#include "esp_heap_caps.h" +#include "esp_mmu_map.h" +#include "esp_cache.h" +#include "esp_timer.h" +#include "esp_partition.h" +#include "esp_flash.h" + +const static char *TAG = "CACHE_TEST"; + +#define TEST_NUM 10 +#define TEST_BUF {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} + + +#if CONFIG_IDF_TARGET_ESP32S2 +#define TEST_SYNC_START 0x3F500000 +#define TEST_SYNC_SIZE 0xA80000 +#elif CONFIG_IDF_TARGET_ESP32S3 +#define TEST_SYNC_START 0x3C000000 +#define TEST_SYNC_SIZE 0x2000000 +#endif + + +#define RECORD_TIME_PREPARE() uint32_t __t1, __t2 +#define RECORD_TIME_START() do {__t1 = esp_cpu_get_cycle_count();} while(0) +#define RECORD_TIME_END(p_time) do{__t2 = esp_cpu_get_cycle_count(); p_time = (__t2 - __t1);} while(0) +#define GET_US_BY_CCOUNT(t) ((double)(t)/CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ) + +static const uint8_t s_test_buf[TEST_NUM] = TEST_BUF; +static DRAM_ATTR bool diff_res; +static DRAM_ATTR uint32_t s_check_times = 0; + +static void NOINLINE_ATTR IRAM_ATTR s_test_rodata_cb(void *arg) +{ + bool sync_flag = *(bool *)arg; + + if (sync_flag) { + uint8_t cmp_buf[TEST_NUM] = TEST_BUF; + for (int i = 0; i < TEST_NUM; i++) { + if (cmp_buf[i] != s_test_buf[i]) { + diff_res |= true; + } + } + + s_check_times++; + } +} + +/** + * This test tests if the esp_cache_msync() suspending CPU->Cache access is short enough + * 1. Register an IRAM callback, but access rodata inside the callback + * 2. esp_cache_msync() will suspend the CPU access to the cache + * 3. Therefore the rodata access in `s_test_rodata_cb()` should be blocked, most of the times + * 4. Note if the callback frequency is less, there might be few successful rodata access, as code execution needs time + */ +TEST_CASE("test cache msync short enough when suspending an ISR", "[cache]") +{ + uint32_t sync_time = 0; + uint32_t sync_time_us = 20; + RECORD_TIME_PREPARE(); + + //Do msync first, as the first writeback / invalidate takes long time, next msyncs will be shorter and they keep unchanged almost + RECORD_TIME_START(); + TEST_ESP_OK(esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE)); + RECORD_TIME_END(sync_time); + sync_time_us = GET_US_BY_CCOUNT(sync_time); + printf("first sync_time_us: %"PRId32"\n", sync_time_us); + + RECORD_TIME_START(); + TEST_ESP_OK(esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE)); + RECORD_TIME_END(sync_time); + sync_time_us = GET_US_BY_CCOUNT(sync_time); + printf("sync_time_us: %"PRId32"\n", sync_time_us); + + bool sync_flag = false; + esp_timer_handle_t timer; + const esp_timer_create_args_t oneshot_timer_args = { + .callback = &s_test_rodata_cb, + .arg = &sync_flag, + .dispatch_method = ESP_TIMER_ISR, + .name = "test_ro_suspend" + }; + TEST_ESP_OK(esp_timer_create(&oneshot_timer_args, &timer)); + + uint32_t period = sync_time_us / 2; + TEST_ESP_OK(esp_timer_start_periodic(timer, period)); + + RECORD_TIME_START(); + sync_flag = true; + TEST_ESP_OK(esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE | ESP_CACHE_MSYNC_FLAG_UNALIGNED)); + sync_flag = false; + RECORD_TIME_END(sync_time); + + TEST_ESP_OK(esp_timer_stop(timer)); + printf("s_check_times: %"PRId32"\n", s_check_times); + sync_time_us = GET_US_BY_CCOUNT(sync_time); + printf("sync time: %"PRId32" us\n", sync_time_us); + TEST_ASSERT((s_check_times < (sync_time_us / period))); + TEST_ASSERT(diff_res == false); + + ESP_LOGI(TAG, "Finish"); + TEST_ESP_OK(esp_timer_delete(timer)); +} + + +static void s_test_with_msync_cb(void *arg) +{ + (void)arg; + esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE); +} + +TEST_CASE("test cache msync short enough to be in an ISR", "[cache]") +{ + uint32_t sync_time = 0; + uint32_t sync_time_us = 200; + RECORD_TIME_PREPARE(); + + RECORD_TIME_START(); + TEST_ESP_OK(esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE | ESP_CACHE_MSYNC_FLAG_UNALIGNED)); + RECORD_TIME_END(sync_time); + sync_time_us = GET_US_BY_CCOUNT(sync_time); + printf("sync_time_us: %"PRId32"\n", sync_time_us); + + esp_timer_handle_t timer; + const esp_timer_create_args_t oneshot_timer_args = { + .callback = &s_test_with_msync_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_ISR, + .name = "test_ro_suspend" + }; + TEST_ESP_OK(esp_timer_create(&oneshot_timer_args, &timer)); + + uint32_t period = sync_time_us * 2; + TEST_ESP_OK(esp_timer_start_periodic(timer, period)); + + //1ms + esp_rom_delay_us(1000); + TEST_ESP_OK(esp_timer_stop(timer)); + + ESP_LOGI(TAG, "Finish"); + TEST_ESP_OK(esp_timer_delete(timer)); +} + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA +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; +} + +TEST_CASE("test cache msync work with Flash operation when XIP from PSRAM", "[cache]") +{ + uint32_t sync_time = 0; + RECORD_TIME_PREPARE(); + + RECORD_TIME_START(); + TEST_ESP_OK(esp_cache_msync((void *)TEST_SYNC_START, TEST_SYNC_SIZE, ESP_CACHE_MSYNC_FLAG_INVALIDATE)); + RECORD_TIME_END(sync_time); + uint32_t sync_time_us = GET_US_BY_CCOUNT(sync_time); + printf("sync_time_us: %"PRId32"\n", sync_time_us); + + //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_timer_handle_t timer; + const esp_timer_create_args_t oneshot_timer_args = { + .callback = &s_test_with_msync_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_ISR, + .name = "test_ro_suspend" + }; + TEST_ESP_OK(esp_timer_create(&oneshot_timer_args, &timer)); + + uint32_t period = sync_time_us * 2; + TEST_ESP_OK(esp_timer_start_periodic(timer, period)); + + ESP_ERROR_CHECK(esp_flash_erase_region(part->flash_chip, part->address, part->size)); + + TEST_ESP_OK(esp_timer_stop(timer)); + ESP_LOGI(TAG, "Finish"); + TEST_ESP_OK(esp_timer_delete(timer)); +} +#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA diff --git a/components/esp_mm/test_apps/mmap/main/test_mmap.c b/components/esp_mm/test_apps/mm/main/test_mmap.c similarity index 100% rename from components/esp_mm/test_apps/mmap/main/test_mmap.c rename to components/esp_mm/test_apps/mm/main/test_mmap.c diff --git a/components/esp_mm/test_apps/mmap/partitions.csv b/components/esp_mm/test_apps/mm/partitions.csv similarity index 100% rename from components/esp_mm/test_apps/mmap/partitions.csv rename to components/esp_mm/test_apps/mm/partitions.csv diff --git a/components/esp_mm/test_apps/mm/pytest_mmap.py b/components/esp_mm/test_apps/mm/pytest_mmap.py new file mode 100644 index 0000000000..7d725d080e --- /dev/null +++ b/components/esp_mm/test_apps/mm/pytest_mmap.py @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +# normal mmu tests +@pytest.mark.supported_targets +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +def test_mmap(dut: Dut) -> None: + dut.run_all_single_board_cases(group='mmu') + + +# mmu tests with psram enabled +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'psram_release', + ], + indirect=True, +) +def test_mmap_psram(dut: Dut) -> None: + dut.run_all_single_board_cases(group='mmu') + + +# mmu tests with xip_psram +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'xip_psram' + ], + indirect=True, +) +def test_mmap_xip_psram(dut: Dut) -> None: + dut.run_all_single_board_cases(group='mmu') + + +# normal cache tests +@pytest.mark.supported_targets +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'release', + ], + indirect=True, +) +def test_cache(dut: Dut) -> None: + dut.run_all_single_board_cases(group='cache') + + +# cache tests with psram enabled +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'psram_release', + ], + indirect=True, +) +def test_cache_psram(dut: Dut) -> None: + dut.run_all_single_board_cases(group='cache') + + +# cache tests with xip_psram +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'xip_psram' + ], + indirect=True, +) +def test_cache_xip_psram(dut: Dut) -> None: + dut.run_all_single_board_cases(group='cache') diff --git a/components/esp_mm/test_apps/mm/sdkconfig.ci.psram_release b/components/esp_mm/test_apps/mm/sdkconfig.ci.psram_release new file mode 100644 index 0000000000..36ed5eb72e --- /dev/null +++ b/components/esp_mm/test_apps/mm/sdkconfig.ci.psram_release @@ -0,0 +1,5 @@ +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +CONFIG_SPIRAM=y diff --git a/components/esp_mm/test_apps/mmap/sdkconfig.ci.release b/components/esp_mm/test_apps/mm/sdkconfig.ci.release similarity index 100% rename from components/esp_mm/test_apps/mmap/sdkconfig.ci.release rename to components/esp_mm/test_apps/mm/sdkconfig.ci.release diff --git a/components/esp_mm/test_apps/mm/sdkconfig.ci.xip_psram b/components/esp_mm/test_apps/mm/sdkconfig.ci.xip_psram new file mode 100644 index 0000000000..db8dcd96c2 --- /dev/null +++ b/components/esp_mm/test_apps/mm/sdkconfig.ci.xip_psram @@ -0,0 +1,7 @@ +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y diff --git a/components/esp_mm/test_apps/mm/sdkconfig.defaults b/components/esp_mm/test_apps/mm/sdkconfig.defaults new file mode 100644 index 0000000000..622d372a36 --- /dev/null +++ b/components/esp_mm/test_apps/mm/sdkconfig.defaults @@ -0,0 +1,11 @@ +CONFIG_ESP_TASK_WDT_EN=n + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" + +CONFIG_COMPILER_DUMP_RTL_FILES=y + +CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y + +CONFIG_HAL_ASSERTION_SILENT=y diff --git a/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt b/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt new file mode 100644 index 0000000000..39179513bb --- /dev/null +++ b/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt @@ -0,0 +1,20 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mmap_hw_test) + +if(CONFIG_COMPILER_DUMP_RTL_FILES) + add_custom_target(check_test_app_sections ALL + COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py + --rtl-dir ${CMAKE_BINARY_DIR}/esp-idf/esp_mm/ + --elf-file ${CMAKE_BINARY_DIR}/mmap_hw_test.elf + find-refs + --from-sections=.iram0.text + --to-sections=.flash.text,.flash.rodata + --exit-code + DEPENDS ${elf} + ) +endif() diff --git a/components/esp_mm/test_apps/mmap_hw/README.md b/components/esp_mm/test_apps/mmap_hw/README.md new file mode 100644 index 0000000000..a8b7833fa3 --- /dev/null +++ b/components/esp_mm/test_apps/mmap_hw/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_mm/test_apps/mmap/main/CMakeLists.txt b/components/esp_mm/test_apps/mmap_hw/main/CMakeLists.txt similarity index 89% rename from components/esp_mm/test_apps/mmap/main/CMakeLists.txt rename to components/esp_mm/test_apps/mmap_hw/main/CMakeLists.txt index a99935cb69..70398eea5a 100644 --- a/components/esp_mm/test_apps/mmap/main/CMakeLists.txt +++ b/components/esp_mm/test_apps/mmap_hw/main/CMakeLists.txt @@ -1,7 +1,6 @@ set(srcs "test_app_main.c") -list(APPEND srcs "test_mmap.c" - "test_mmap_hw.c") +list(APPEND srcs "test_mmap_hw.c") # In order for the cases defined by `TEST_CASE` to be linked into the final elf, diff --git a/components/esp_mm/test_apps/mmap/main/test_app_main.c b/components/esp_mm/test_apps/mmap_hw/main/test_app_main.c similarity index 100% rename from components/esp_mm/test_apps/mmap/main/test_app_main.c rename to components/esp_mm/test_apps/mmap_hw/main/test_app_main.c diff --git a/components/esp_mm/test_apps/mmap/main/test_mmap_hw.c b/components/esp_mm/test_apps/mmap_hw/main/test_mmap_hw.c similarity index 100% rename from components/esp_mm/test_apps/mmap/main/test_mmap_hw.c rename to components/esp_mm/test_apps/mmap_hw/main/test_mmap_hw.c diff --git a/components/esp_mm/test_apps/mmap_hw/partitions.csv b/components/esp_mm/test_apps/mmap_hw/partitions.csv new file mode 100644 index 0000000000..6b057cd354 --- /dev/null +++ b/components/esp_mm/test_apps/mmap_hw/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, , 512K, diff --git a/components/esp_mm/test_apps/mmap/pytest_mmap.py b/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py similarity index 90% rename from components/esp_mm/test_apps/mmap/pytest_mmap.py rename to components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py index 945b0b92b9..1590f48d51 100644 --- a/components/esp_mm/test_apps/mmap/pytest_mmap.py +++ b/components/esp_mm/test_apps/mmap_hw/pytest_mmap_hw.py @@ -14,5 +14,5 @@ from pytest_embedded import Dut ], indirect=True, ) -def test_mmap(dut: Dut) -> None: +def test_mmap_hw(dut: Dut) -> None: dut.run_all_single_board_cases(group='mmu', timeout=600) diff --git a/components/esp_mm/test_apps/mmap_hw/sdkconfig.ci.release b/components/esp_mm/test_apps/mmap_hw/sdkconfig.ci.release new file mode 100644 index 0000000000..22bd3f16c0 --- /dev/null +++ b/components/esp_mm/test_apps/mmap_hw/sdkconfig.ci.release @@ -0,0 +1,6 @@ +# set compilier optimization level +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y + +# we can silent the assertion to save the binary footprint +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/esp_mm/test_apps/mmap/sdkconfig.defaults b/components/esp_mm/test_apps/mmap_hw/sdkconfig.defaults similarity index 87% rename from components/esp_mm/test_apps/mmap/sdkconfig.defaults rename to components/esp_mm/test_apps/mmap_hw/sdkconfig.defaults index ee544f97f7..919fc46938 100644 --- a/components/esp_mm/test_apps/mmap/sdkconfig.defaults +++ b/components/esp_mm/test_apps/mmap_hw/sdkconfig.defaults @@ -1,4 +1,4 @@ -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" diff --git a/components/esp_psram/esp_psram.c b/components/esp_psram/esp_psram.c index 008d9a4533..3fe51e1782 100644 --- a/components/esp_psram/esp_psram.c +++ b/components/esp_psram/esp_psram.c @@ -32,6 +32,7 @@ #if CONFIG_IDF_TARGET_ESP32 #include "esp32/himem.h" #include "esp32/rom/cache.h" +#include "esp_private/esp_cache_esp32_private.h" #endif @@ -293,6 +294,15 @@ esp_err_t esp_psram_init(void) s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].size -= esp_himem_reserved_area_size() - 1; #endif + //will be removed, TODO: IDF-6944 +#if CONFIG_IDF_TARGET_ESP32 + cache_driver_t drv = { + NULL, + esp_psram_extram_writeback_cache, + }; + cache_register_writeback(&drv); +#endif + return ESP_OK; } diff --git a/components/hal/cache_hal.c b/components/hal/cache_hal.c index 41a58666e0..e21564fce1 100644 --- a/components/hal/cache_hal.c +++ b/components/hal/cache_hal.c @@ -15,22 +15,7 @@ #include "hal/mmu_hal.h" #include "hal/mmu_ll.h" #include "soc/soc_caps.h" - -#if CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32C2 -#include "esp32c2/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32H4 -#include "esp32h4/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32C6 -#include "esp32c6/rom/cache.h" -#elif CONFIG_IDF_TARGET_ESP32H2 -#include "esp32h2/rom/cache.h" -#endif +#include "rom/cache.h" /*------------------------------------------------------------------------------ * Unified Cache Control @@ -121,3 +106,63 @@ void cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size) HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION)); Cache_Invalidate_Addr(vaddr, size); } + +#if SOC_CACHE_WRITEBACK_SUPPORTED +void cache_hal_writeback_addr(uint32_t vaddr, uint32_t size) +{ + HAL_ASSERT(mmu_hal_check_valid_ext_vaddr_region(0, vaddr, size, MMU_VADDR_DATA)); + Cache_WriteBack_Addr(vaddr, size); +} +#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED + + +#if SOC_CACHE_FREEZE_SUPPORTED +void cache_hal_freeze(cache_type_t type) +{ +#if SOC_SHARED_IDCACHE_SUPPORTED + Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); +#else + if (type == CACHE_TYPE_DATA) { + Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY); + } else if (type == CACHE_TYPE_INSTRUCTION) { + Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); + } else { + Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); + Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY); + } +#endif +} + +void cache_hal_unfreeze(cache_type_t type) +{ +#if SOC_SHARED_IDCACHE_SUPPORTED + Cache_Freeze_ICache_Disable(); +#else + if (type == CACHE_TYPE_DATA) { + Cache_Freeze_DCache_Disable(); + } else if (type == CACHE_TYPE_INSTRUCTION) { + Cache_Freeze_ICache_Disable(); + } else { + Cache_Freeze_DCache_Disable(); + Cache_Freeze_ICache_Disable(); + } +#endif +} +#endif //#if SOC_CACHE_FREEZE_SUPPORTED + +uint32_t cache_hal_get_cache_line_size(cache_type_t type) +{ +#if SOC_SHARED_IDCACHE_SUPPORTED + return Cache_Get_ICache_Line_Size(); +#else + uint32_t size = 0; + if (type == CACHE_TYPE_DATA) { + size = Cache_Get_DCache_Line_Size(); + } else if (type == CACHE_TYPE_INSTRUCTION) { + size = Cache_Get_ICache_Line_Size(); + } else { + HAL_ASSERT(false); + } + return size; +#endif +} diff --git a/components/hal/include/hal/cache_hal.h b/components/hal/include/hal/cache_hal.h index c147aaf868..4887c939f3 100644 --- a/components/hal/include/hal/cache_hal.h +++ b/components/hal/include/hal/cache_hal.h @@ -15,11 +15,12 @@ extern "C" { /** * Cache init and cache hal context init - * */ void cache_hal_init(void); /** + * @brief Disable cache + * * Disable the ICache or DCache or both, all the items in the corresponding Cache(s) will be invalideated. * Next request to these items will trigger a transaction to the external memory (flash / psram) * @@ -30,6 +31,8 @@ void cache_hal_init(void); void cache_hal_disable(cache_type_t type); /** + * @brief Enable cache + * * Enable the ICache or DCache or both. * * @param type see `cache_type_t` @@ -37,6 +40,8 @@ void cache_hal_disable(cache_type_t type); void cache_hal_enable(cache_type_t type); /** + * @brief Invalidate cache supported addr + * * Invalidate a Cache item for either ICache or DCache. * * @param vaddr Start address of the region to be invalidated @@ -44,6 +49,47 @@ void cache_hal_enable(cache_type_t type); */ void cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size); +#if SOC_CACHE_WRITEBACK_SUPPORTED +/** + * @brief Writeback cache supported addr + * + * Writeback the DCache item to external memory + * + * @param vaddr Start address of the region to writeback + * @param size Size of the region to writeback + */ +void cache_hal_writeback_addr(uint32_t vaddr, uint32_t size); +#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED + +#if SOC_CACHE_FREEZE_SUPPORTED +/** + * @brief Freeze cache + * + * Freeze cache, CPU access to cache will be suspended, until the cache is unfrozen. + * + * @param type see `cache_type_t` + */ +void cache_hal_freeze(cache_type_t type); + +/** + * @brief Unfreeze cache + * + * Unfreeze cache, CPU access to cache will be restored + * + * @param type see `cache_type_t` + */ +void cache_hal_unfreeze(cache_type_t type); +#endif //#if SOC_CACHE_FREEZE_SUPPORTED + +/** + * @brief Get cache line size, in bytes + * + * @param type see `cache_type_t` + * + * @return cache line size, in bytes + */ +uint32_t cache_hal_get_cache_line_size(cache_type_t type); + #ifdef __cplusplus } #endif diff --git a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c index 83026a6274..b9899c3449 100644 --- a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c +++ b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -60,7 +60,6 @@ static esp_err_t crypto_shared_gdma_init(void) gdma_transfer_ability_t transfer_ability = { .sram_trans_align = 1, - .psram_trans_align = 16, }; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 0328fd0d11..1edba08f72 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -279,6 +279,10 @@ config SOC_SHARED_IDCACHE_SUPPORTED bool default y +config SOC_CACHE_FREEZE_SUPPORTED + bool + default y + config SOC_CPU_CORES_NUM int default 1 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 864b51f03a..08d8f5d649 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -121,6 +121,7 @@ /*-------------------------- CACHE CAPS --------------------------------------*/ #define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data +#define SOC_CACHE_FREEZE_SUPPORTED 1 /*-------------------------- CPU CAPS ----------------------------------------*/ #define SOC_CPU_CORES_NUM (1U) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 179bd709bf..2eceb915e7 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -239,6 +239,10 @@ config SOC_SHARED_IDCACHE_SUPPORTED bool default y +config SOC_CACHE_FREEZE_SUPPORTED + bool + default y + config SOC_CPU_CORES_NUM int default 1 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index da91974171..942e6c47ec 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -117,6 +117,7 @@ /*-------------------------- CACHE CAPS --------------------------------------*/ #define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data +#define SOC_CACHE_FREEZE_SUPPORTED 1 /*-------------------------- CPU CAPS ----------------------------------------*/ #define SOC_CPU_CORES_NUM (1U) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index ac943589ca..28e643ddf1 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -267,6 +267,10 @@ config SOC_BROWNOUT_RESET_SUPPORTED bool default y +config SOC_CACHE_WRITEBACK_SUPPORTED + bool + default y + config SOC_CP_DMA_MAX_BUFFER_SIZE int default 4095 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index ceb7465574..3a0db77320 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -122,6 +122,9 @@ /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #define SOC_BROWNOUT_RESET_SUPPORTED 1 +/*-------------------------- CACHE CAPS --------------------------------------*/ +#define SOC_CACHE_WRITEBACK_SUPPORTED 1 + /*-------------------------- CP-DMA CAPS -------------------------------------*/ #define SOC_CP_DMA_MAX_BUFFER_SIZE (4095) /*!< Maximum size of the buffer that can be attached to descriptor */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 27e2a891f0..4a1b43b728 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -307,6 +307,14 @@ config SOC_BROWNOUT_RESET_SUPPORTED bool default y +config SOC_CACHE_WRITEBACK_SUPPORTED + bool + default y + +config SOC_CACHE_FREEZE_SUPPORTED + bool + default y + config SOC_CPU_CORES_NUM int default 2 @@ -355,10 +363,6 @@ config SOC_GDMA_SUPPORT_PSRAM bool default y -config SOC_GDMA_PSRAM_MIN_ALIGN - int - default 16 - config SOC_GPIO_PORT int default 1 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 2681f1efac..2b7134fc42 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -117,6 +117,10 @@ /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #define SOC_BROWNOUT_RESET_SUPPORTED 1 +/*-------------------------- CACHE CAPS --------------------------------------*/ +#define SOC_CACHE_WRITEBACK_SUPPORTED 1 +#define SOC_CACHE_FREEZE_SUPPORTED 1 + /*-------------------------- CPU CAPS ----------------------------------------*/ #define SOC_CPU_CORES_NUM 2 #define SOC_CPU_INTR_NUM 32 @@ -141,7 +145,6 @@ #define SOC_GDMA_GROUPS (1) // Number of GDMA groups #define SOC_GDMA_PAIRS_PER_GROUP (5) // Number of GDMA pairs in each group #define SOC_GDMA_SUPPORT_PSRAM (1) // GDMA can access external PSRAM -#define SOC_GDMA_PSRAM_MIN_ALIGN (16) // Minimal alignment for PSRAM transaction /*-------------------------- GPIO CAPS ---------------------------------------*/ // ESP32-S3 has 1 GPIO peripheral