diff --git a/components/esp_psram/system_layer/esp_psram.c b/components/esp_psram/system_layer/esp_psram.c index c0358902e5..e39fab0e8b 100644 --- a/components/esp_psram/system_layer/esp_psram.c +++ b/components/esp_psram/system_layer/esp_psram.c @@ -471,17 +471,17 @@ bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p) return true; } -#if CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2 - if (mmu_psram_check_ptr_addr_in_rodata_alignment_gap(p)) { +#if CONFIG_SPIRAM_RODATA + if (mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(p)) { return true; } -#endif /* CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2 */ +#endif -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED - if (mmu_psram_check_ptr_addr_in_instruction_alignment_gap(p)) { +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + if (mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(p)) { return true; } -#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED */ +#endif return false; } diff --git a/components/esp_psram/test_apps/psram/main/test_psram.c b/components/esp_psram/test_apps/psram/main/test_psram.c index d93e3cf83c..3ce5bc9c7d 100644 --- a/components/esp_psram/test_apps/psram/main/test_psram.c +++ b/components/esp_psram/test_apps/psram/main/test_psram.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -140,6 +140,18 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram" TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); } + +TEST_CASE("test esp_psram_check_ptr_addr with xip rodata and instruction region", "[psram]") +{ + bool on_psram = false; + + on_psram = esp_psram_check_ptr_addr(s_get_partition); + TEST_ASSERT(on_psram); + + on_psram = esp_psram_check_ptr_addr(s_test_buf); + TEST_ASSERT(on_psram); +} + #endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA TEST_CASE("test psram unaligned access", "[psram]") diff --git a/components/esp_psram/xip_impl/include/esp_private/mmu_psram_flash.h b/components/esp_psram/xip_impl/include/esp_private/mmu_psram_flash.h index a1fbcf0f4b..37392c39d0 100644 --- a/components/esp_psram/xip_impl/include/esp_private/mmu_psram_flash.h +++ b/components/esp_psram/xip_impl/include/esp_private/mmu_psram_flash.h @@ -56,13 +56,13 @@ size_t mmu_psram_get_text_segment_length(void); void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_size); /** - * @brief Check if the pointer is in the instruction alignment gap + * @brief Check if the pointer is in the xip psram instruction region * * @param[in] p Pointer to check * - * @return true if the pointer is in the instruction alignment gap, false otherwise + * @return true if the pointer is in the instruction region, false otherwise */ -bool mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p); +bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p); /** * @brief Copy Flash texts to PSRAM @@ -101,13 +101,13 @@ size_t mmu_psram_get_rodata_segment_length(void); esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page); /** - * @brief Check if the pointer is in the rodata alignment gap + * @brief Check if the pointer is in the xip psram rodata region * * @param[in] p Pointer to check * - * @return true if the pointer is in the rodata alignment gap, false otherwise + * @return true if the pointer is in the rodata region, false otherwise */ -bool mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p); +bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p); #endif //#if CONFIG_SPIRAM_RODATA /*---------------------------------------------------------------------------- diff --git a/components/esp_psram/xip_impl/mmu_psram_flash.c b/components/esp_psram/xip_impl/mmu_psram_flash.c index c33c9f26e0..9f415f706f 100644 --- a/components/esp_psram/xip_impl/mmu_psram_flash.c +++ b/components/esp_psram/xip_impl/mmu_psram_flash.c @@ -33,6 +33,7 @@ #endif #define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN_BY(num, align) ((num) & (~((align) - 1))) /*---------------------------------------------------------------------------- Part 1 APIs (See @Backgrounds on top of this file) @@ -44,10 +45,22 @@ const static char *TAG = "mmu_psram"; //TODO IDF-4387 static uint32_t page0_mapped = 0; static uint32_t page0_page = INVALID_PHY_PAGE; + +/** + * If using `int`, then for CLANG, with enabled optimization when inlined function is provided with the address of external symbol, the two least bits of the constant used inside that function get cleared. + * Optimizer assumes that address of external symbol should be aligned to 4-bytes and therefore aligns constant value used for bitwise AND operation with that address. + * + * This means `extern int _instruction_reserved_start;` can be unaligned to 4 bytes, whereas using `char` can solve this issue. + * + * As we only use these symbol address, we declare them as `char` here + */ +extern char _instruction_reserved_start; +extern char _instruction_reserved_end; +extern char _rodata_reserved_start; +extern char _rodata_reserved_end; #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS -extern char _instruction_reserved_end; #define INSTRUCTION_ALIGNMENT_GAP_START ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, 4) #define INSTRUCTION_ALIGNMENT_GAP_END ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE) @@ -71,11 +84,12 @@ void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_end = INSTRUCTION_ALIGNMENT_GAP_END; } -bool IRAM_ATTR mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p) +bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p) { - if ((intptr_t)p >= INSTRUCTION_ALIGNMENT_GAP_START && (intptr_t)p < INSTRUCTION_ALIGNMENT_GAP_END) { + if ((intptr_t)p >= ALIGN_DOWN_BY((uint32_t)&_instruction_reserved_start, CONFIG_MMU_PAGE_SIZE) && (intptr_t)p < ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE)) { return true; } + return false; } @@ -116,7 +130,6 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS #if CONFIG_SPIRAM_RODATA -extern char _rodata_reserved_end; #define RODATA_ALIGNMENT_GAP_START ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, 4) #define RODATA_ALIGNMENT_GAP_END ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE) @@ -142,11 +155,12 @@ void mmu_psram_get_rodata_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_ *gap_end = RODATA_ALIGNMENT_GAP_END; } -bool IRAM_ATTR mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p) +bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p) { - if ((intptr_t)p >= RODATA_ALIGNMENT_GAP_START && (intptr_t)p < RODATA_ALIGNMENT_GAP_END) { + if ((intptr_t)p >= ALIGN_DOWN_BY((uint32_t)&_rodata_reserved_start, CONFIG_MMU_PAGE_SIZE) && (intptr_t)p < ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE)) { return true; } + return false; } @@ -192,19 +206,6 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si /*---------------------------------------------------------------------------- Part 2 APIs (See @Backgrounds on top of this file) -------------------------------------------------------------------------------*/ -/** - * If using `int`, then for CLANG, with enabled optimization when inlined function is provided with the address of external symbol, the two least bits of the constant used inside that function get cleared. - * Optimizer assumes that address of external symbol should be aligned to 4-bytes and therefore aligns constant value used for bitwise AND operation with that address. - * - * This means `extern int _instruction_reserved_start;` can be unaligned to 4 bytes, whereas using `char` can solve this issue. - * - * As we only use these symbol address, we declare them as `char` here - */ -extern char _instruction_reserved_start; -extern char _instruction_reserved_end; -extern char _rodata_reserved_start; -extern char _rodata_reserved_end; - //------------------------------------Copy Flash .text to PSRAM-------------------------------------// #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS static uint32_t instruction_in_spiram; diff --git a/components/esp_psram/xip_impl/mmu_psram_flash_v2.c b/components/esp_psram/xip_impl/mmu_psram_flash_v2.c index 3f9f583254..2ce08c853b 100644 --- a/components/esp_psram/xip_impl/mmu_psram_flash_v2.c +++ b/components/esp_psram/xip_impl/mmu_psram_flash_v2.c @@ -127,11 +127,12 @@ void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_end = INSTRUCTION_ALIGNMENT_GAP_END; } -bool IRAM_ATTR mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p) +bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p) { - if ((intptr_t)p >= INSTRUCTION_ALIGNMENT_GAP_START && (intptr_t)p < INSTRUCTION_ALIGNMENT_GAP_END) { + if ((intptr_t)p >= ALIGN_DOWN_BY((uint32_t)&_instruction_reserved_start, CONFIG_MMU_PAGE_SIZE) && (intptr_t)p < ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE)) { return true; } + return false; } @@ -188,11 +189,12 @@ void mmu_psram_get_rodata_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_ *gap_end = RODATA_ALIGNMENT_GAP_END; } -bool IRAM_ATTR mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p) +bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p) { - if ((intptr_t)p >= RODATA_ALIGNMENT_GAP_START && (intptr_t)p < RODATA_ALIGNMENT_GAP_END) { + if ((intptr_t)p >= ALIGN_DOWN_BY((uint32_t)&_rodata_reserved_start, CONFIG_MMU_PAGE_SIZE) && (intptr_t)p < ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE)) { return true; } + return false; } diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c index 6ac5a10e4c..bbaceef188 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c @@ -252,7 +252,7 @@ static void vPortTLSPointersDelCb( void *pxTCB ) if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set /* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */ if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) { - ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]); + ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]); abort(); } diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c index e151f0f505..e5dbf8238c 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c @@ -714,7 +714,7 @@ static void vPortTLSPointersDelCb( void *pxTCB ) if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set /* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */ if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) { - ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]); + ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]); abort(); }