mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 18:57:19 +02:00
fix(psram): fixed psram ptr check under xip_psram condition
Closes https://github.com/espressif/esp-idf/pull/15999 Closes https://github.com/espressif/esp-idf/issues/15997
This commit is contained in:
@ -66,7 +66,6 @@ extern uint8_t _rodata_reserved_end;
|
|||||||
#endif /* CONFIG_SPIRAM_RODATA */
|
#endif /* CONFIG_SPIRAM_RODATA */
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
extern uint8_t _instruction_reserved_start;
|
|
||||||
extern uint8_t _instruction_reserved_end;
|
extern uint8_t _instruction_reserved_end;
|
||||||
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS */
|
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS */
|
||||||
|
|
||||||
@ -472,23 +471,17 @@ bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_SPIRAM_RODATA
|
||||||
if (mmu_psram_check_ptr_addr_in_rodata_alignment_gap(p)) {
|
if (mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(p)) {
|
||||||
return true;
|
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)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED */
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
if ((intptr_t)p >= (uint32_t)&_instruction_reserved_start && (intptr_t)p < (uint32_t)&_instruction_reserved_end) {
|
if (mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(p)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS */
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -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
|
* 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_disable(gptimer));
|
||||||
TEST_ESP_OK(gptimer_del_timer(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
|
#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
TEST_CASE("test psram unaligned access", "[psram]")
|
TEST_CASE("test psram unaligned access", "[psram]")
|
||||||
|
@ -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);
|
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
|
* @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
|
* @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);
|
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
|
* @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
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
#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)
|
Part 1 APIs (See @Backgrounds on top of this file)
|
||||||
@ -44,10 +45,22 @@ const static char *TAG = "mmu_psram";
|
|||||||
//TODO IDF-4387
|
//TODO IDF-4387
|
||||||
static uint32_t page0_mapped = 0;
|
static uint32_t page0_mapped = 0;
|
||||||
static uint32_t page0_page = INVALID_PHY_PAGE;
|
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
|
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#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_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)
|
#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;
|
*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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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
|
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
#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_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)
|
#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;
|
*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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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)
|
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-------------------------------------//
|
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
static uint32_t instruction_in_spiram;
|
static uint32_t instruction_in_spiram;
|
||||||
|
@ -127,11 +127,12 @@ void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t
|
|||||||
*gap_end = INSTRUCTION_ALIGNMENT_GAP_END;
|
*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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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;
|
*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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user