Skip to content

Commit d0aabd3

Browse files
committed
Merge branch 'fix/fix_xip_psram_ptr_check' into 'master'
psram: fixed psram ptr check issue under xip_psram condition for ESP32P4 Closes IDFGH-15338, IDFGH-15340, and IDF-12458 See merge request espressif/esp-idf!39405
2 parents bc93cee + 7a6cd63 commit d0aabd3

File tree

7 files changed

+53
-38
lines changed

7 files changed

+53
-38
lines changed

components/esp_psram/system_layer/esp_psram.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,17 +471,17 @@ bool IRAM_ATTR esp_psram_check_ptr_addr(const void *p)
471471
return true;
472472
}
473473

474-
#if CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2
475-
if (mmu_psram_check_ptr_addr_in_rodata_alignment_gap(p)) {
474+
#if CONFIG_SPIRAM_RODATA
475+
if (mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(p)) {
476476
return true;
477477
}
478-
#endif /* CONFIG_SPIRAM_RODATA && !CONFIG_IDF_TARGET_ESP32S2 */
478+
#endif
479479

480-
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED
481-
if (mmu_psram_check_ptr_addr_in_instruction_alignment_gap(p)) {
480+
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
481+
if (mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(p)) {
482482
return true;
483483
}
484-
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && SOC_MMU_DI_VADDR_SHARED */
484+
#endif
485485

486486
return false;
487487
}

components/esp_psram/test_apps/psram/main/test_psram.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -140,6 +140,18 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram"
140140
TEST_ESP_OK(gptimer_disable(gptimer));
141141
TEST_ESP_OK(gptimer_del_timer(gptimer));
142142
}
143+
144+
TEST_CASE("test esp_psram_check_ptr_addr with xip rodata and instruction region", "[psram]")
145+
{
146+
bool on_psram = false;
147+
148+
on_psram = esp_psram_check_ptr_addr(s_get_partition);
149+
TEST_ASSERT(on_psram);
150+
151+
on_psram = esp_psram_check_ptr_addr(s_test_buf);
152+
TEST_ASSERT(on_psram);
153+
}
154+
143155
#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
144156

145157
TEST_CASE("test psram unaligned access", "[psram]")

components/esp_psram/xip_impl/include/esp_private/mmu_psram_flash.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ size_t mmu_psram_get_text_segment_length(void);
5656
void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_size);
5757

5858
/**
59-
* @brief Check if the pointer is in the instruction alignment gap
59+
* @brief Check if the pointer is in the xip psram instruction region
6060
*
6161
* @param[in] p Pointer to check
6262
*
63-
* @return true if the pointer is in the instruction alignment gap, false otherwise
63+
* @return true if the pointer is in the instruction region, false otherwise
6464
*/
65-
bool mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p);
65+
bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p);
6666

6767
/**
6868
* @brief Copy Flash texts to PSRAM
@@ -101,13 +101,13 @@ size_t mmu_psram_get_rodata_segment_length(void);
101101
esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
102102

103103
/**
104-
* @brief Check if the pointer is in the rodata alignment gap
104+
* @brief Check if the pointer is in the xip psram rodata region
105105
*
106106
* @param[in] p Pointer to check
107107
*
108-
* @return true if the pointer is in the rodata alignment gap, false otherwise
108+
* @return true if the pointer is in the rodata region, false otherwise
109109
*/
110-
bool mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p);
110+
bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p);
111111
#endif //#if CONFIG_SPIRAM_RODATA
112112

113113
/*----------------------------------------------------------------------------

components/esp_psram/xip_impl/mmu_psram_flash.c

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#endif
3434

3535
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
36+
#define ALIGN_DOWN_BY(num, align) ((num) & (~((align) - 1)))
3637

3738
/*----------------------------------------------------------------------------
3839
Part 1 APIs (See @Backgrounds on top of this file)
@@ -44,10 +45,22 @@ const static char *TAG = "mmu_psram";
4445
//TODO IDF-4387
4546
static uint32_t page0_mapped = 0;
4647
static uint32_t page0_page = INVALID_PHY_PAGE;
48+
49+
/**
50+
* 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.
51+
* 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.
52+
*
53+
* This means `extern int _instruction_reserved_start;` can be unaligned to 4 bytes, whereas using `char` can solve this issue.
54+
*
55+
* As we only use these symbol address, we declare them as `char` here
56+
*/
57+
extern char _instruction_reserved_start;
58+
extern char _instruction_reserved_end;
59+
extern char _rodata_reserved_start;
60+
extern char _rodata_reserved_end;
4761
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
4862

4963
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
50-
extern char _instruction_reserved_end;
5164
#define INSTRUCTION_ALIGNMENT_GAP_START ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, 4)
5265
#define INSTRUCTION_ALIGNMENT_GAP_END ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE)
5366

@@ -71,11 +84,12 @@ void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t
7184
*gap_end = INSTRUCTION_ALIGNMENT_GAP_END;
7285
}
7386

74-
bool IRAM_ATTR mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p)
87+
bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p)
7588
{
76-
if ((intptr_t)p >= INSTRUCTION_ALIGNMENT_GAP_START && (intptr_t)p < INSTRUCTION_ALIGNMENT_GAP_END) {
89+
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)) {
7790
return true;
7891
}
92+
7993
return false;
8094
}
8195

@@ -116,7 +130,6 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size
116130
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
117131

118132
#if CONFIG_SPIRAM_RODATA
119-
extern char _rodata_reserved_end;
120133
#define RODATA_ALIGNMENT_GAP_START ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, 4)
121134
#define RODATA_ALIGNMENT_GAP_END ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE)
122135

@@ -142,11 +155,12 @@ void mmu_psram_get_rodata_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_
142155
*gap_end = RODATA_ALIGNMENT_GAP_END;
143156
}
144157

145-
bool IRAM_ATTR mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p)
158+
bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p)
146159
{
147-
if ((intptr_t)p >= RODATA_ALIGNMENT_GAP_START && (intptr_t)p < RODATA_ALIGNMENT_GAP_END) {
160+
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)) {
148161
return true;
149162
}
163+
150164
return false;
151165
}
152166

@@ -192,19 +206,6 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si
192206
/*----------------------------------------------------------------------------
193207
Part 2 APIs (See @Backgrounds on top of this file)
194208
-------------------------------------------------------------------------------*/
195-
/**
196-
* 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.
197-
* 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.
198-
*
199-
* This means `extern int _instruction_reserved_start;` can be unaligned to 4 bytes, whereas using `char` can solve this issue.
200-
*
201-
* As we only use these symbol address, we declare them as `char` here
202-
*/
203-
extern char _instruction_reserved_start;
204-
extern char _instruction_reserved_end;
205-
extern char _rodata_reserved_start;
206-
extern char _rodata_reserved_end;
207-
208209
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
209210
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
210211
static uint32_t instruction_in_spiram;

components/esp_psram/xip_impl/mmu_psram_flash_v2.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,12 @@ void mmu_psram_get_instruction_alignment_gap_info(uint32_t *gap_start, uint32_t
127127
*gap_end = INSTRUCTION_ALIGNMENT_GAP_END;
128128
}
129129

130-
bool IRAM_ATTR mmu_psram_check_ptr_addr_in_instruction_alignment_gap(const void *p)
130+
bool mmu_psram_check_ptr_addr_in_xip_psram_instruction_region(const void *p)
131131
{
132-
if ((intptr_t)p >= INSTRUCTION_ALIGNMENT_GAP_START && (intptr_t)p < INSTRUCTION_ALIGNMENT_GAP_END) {
132+
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)) {
133133
return true;
134134
}
135+
135136
return false;
136137
}
137138

@@ -188,11 +189,12 @@ void mmu_psram_get_rodata_alignment_gap_info(uint32_t *gap_start, uint32_t *gap_
188189
*gap_end = RODATA_ALIGNMENT_GAP_END;
189190
}
190191

191-
bool IRAM_ATTR mmu_psram_check_ptr_addr_in_rodata_alignment_gap(const void *p)
192+
bool mmu_psram_check_ptr_addr_in_xip_psram_rodata_region(const void *p)
192193
{
193-
if ((intptr_t)p >= RODATA_ALIGNMENT_GAP_START && (intptr_t)p < RODATA_ALIGNMENT_GAP_END) {
194+
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)) {
194195
return true;
195196
}
197+
196198
return false;
197199
}
198200

components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static void vPortTLSPointersDelCb( void *pxTCB )
252252
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
253253
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
254254
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
255-
ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
255+
ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
256256
abort();
257257
}
258258

components/freertos/FreeRTOS-Kernel/portable/riscv/port.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ static void vPortTLSPointersDelCb( void *pxTCB )
714714
if ( pvThreadLocalStoragePointersDelCallback[ x ] != NULL ) { //If del cb is set
715715
/* In case the TLSP deletion callback has been overwritten by a TLS pointer, gracefully abort. */
716716
if ( !esp_ptr_executable( pvThreadLocalStoragePointersDelCallback[ x ] ) ) {
717-
ESP_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
717+
ESP_EARLY_LOGE("FreeRTOS", "Fatal error: TLSP deletion callback at index %d overwritten with non-excutable pointer %p", x, pvThreadLocalStoragePointersDelCallback[ x ]);
718718
abort();
719719
}
720720

0 commit comments

Comments
 (0)