forked from espressif/esp-idf
Merge branch 'bugfix/cache2phys_xip_v5.0' into 'release/v5.0'
fix(mmap): fixed spi_flash_cache2phys return addr in PSRAM issue (v5.0) See merge request espressif/esp-idf!38051
This commit is contained in:
@@ -1012,7 +1012,7 @@ UT_S2_SDSPI:
|
|||||||
|
|
||||||
UT_C2:
|
UT_C2:
|
||||||
extends: .unit_test_esp32c2_template
|
extends: .unit_test_esp32c2_template
|
||||||
parallel: 23
|
parallel: 24
|
||||||
tags:
|
tags:
|
||||||
- ESP32C2_IDF
|
- ESP32C2_IDF
|
||||||
- UT_T1_1
|
- UT_T1_1
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "esp_log.h"
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <freertos/semphr.h>
|
#include <freertos/semphr.h>
|
||||||
@@ -113,3 +114,11 @@ TEST_CASE("esp_ota_get_partition_description", "[ota]")
|
|||||||
};
|
};
|
||||||
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, bootloader_common_get_partition_description(¬_app_pos, &app_desc1));
|
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, bootloader_common_get_partition_description(¬_app_pos, &app_desc1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("esp_ota_get_running_partition points to correct address", "[spi_flash]")
|
||||||
|
{
|
||||||
|
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, "factory");
|
||||||
|
const esp_partition_t* part = esp_ota_get_running_partition();
|
||||||
|
ESP_LOGI("running bin", "0x%p", (void*)part->address);
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(factory->address, part->address);
|
||||||
|
}
|
||||||
|
@@ -166,7 +166,8 @@ void instruction_flash_page_info_init(uint32_t psram_start_physical_page)
|
|||||||
instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
|
instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
instr_start_page = *((volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START));
|
uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
|
||||||
|
instr_start_page = *((volatile uint32_t *)(DR_REG_MMU_TABLE + instr_mmu_offset * 4));
|
||||||
#endif
|
#endif
|
||||||
instr_start_page &= MMU_VALID_VAL_MASK;
|
instr_start_page &= MMU_VALID_VAL_MASK;
|
||||||
instr_end_page = instr_start_page + instr_page_cnt - 1;
|
instr_end_page = instr_start_page + instr_page_cnt - 1;
|
||||||
@@ -219,7 +220,8 @@ void rodata_flash_page_info_init(uint32_t psram_start_physical_page)
|
|||||||
rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
|
rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
|
uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
|
||||||
|
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + rodata_mmu_offset * 4);
|
||||||
#endif
|
#endif
|
||||||
rodata_start_page &= MMU_VALID_VAL_MASK;
|
rodata_start_page &= MMU_VALID_VAL_MASK;
|
||||||
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
||||||
|
@@ -81,6 +81,8 @@ static LIST_HEAD(mmap_entries_head, mmap_entry_) s_mmap_entries_head =
|
|||||||
static uint8_t s_mmap_page_refcnt[SOC_MMU_REGIONS_COUNT * SOC_MMU_PAGES_PER_REGION] = {0};
|
static uint8_t s_mmap_page_refcnt[SOC_MMU_REGIONS_COUNT * SOC_MMU_PAGES_PER_REGION] = {0};
|
||||||
static uint32_t s_mmap_last_handle = 0;
|
static uint32_t s_mmap_last_handle = 0;
|
||||||
|
|
||||||
|
static uint32_t spi_flash_protected_read_mmu_entry(int index);
|
||||||
|
|
||||||
|
|
||||||
static void IRAM_ATTR spi_flash_mmap_init(void)
|
static void IRAM_ATTR spi_flash_mmap_init(void)
|
||||||
{
|
{
|
||||||
@@ -330,15 +332,6 @@ static void IRAM_ATTR NOINLINE_ATTR spi_flash_protected_mmap_init(void)
|
|||||||
spi_flash_enable_interrupts_caches_and_other_cpu();
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t IRAM_ATTR NOINLINE_ATTR spi_flash_protected_read_mmu_entry(int index)
|
|
||||||
{
|
|
||||||
uint32_t value;
|
|
||||||
spi_flash_disable_interrupts_caches_and_other_cpu();
|
|
||||||
value = mmu_ll_read_entry(MMU_TABLE_CORE0, index);
|
|
||||||
spi_flash_enable_interrupts_caches_and_other_cpu();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spi_flash_mmap_dump(void)
|
void spi_flash_mmap_dump(void)
|
||||||
{
|
{
|
||||||
spi_flash_protected_mmap_init();
|
spi_flash_protected_mmap_init();
|
||||||
@@ -374,6 +367,89 @@ uint32_t IRAM_ATTR spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **out_ptr)
|
||||||
|
{
|
||||||
|
int start[2], end[2];
|
||||||
|
|
||||||
|
*out_ptr = NULL;
|
||||||
|
|
||||||
|
/* SPI_FLASH_MMAP_DATA */
|
||||||
|
start[0] = SOC_MMU_DROM0_PAGES_START;
|
||||||
|
end[0] = SOC_MMU_DROM0_PAGES_END;
|
||||||
|
|
||||||
|
/* SPI_FLASH_MMAP_INST */
|
||||||
|
start[1] = SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE;
|
||||||
|
end[1] = SOC_MMU_IROM0_PAGES_END;
|
||||||
|
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
for (int i = start[j]; i < end[j]; i++) {
|
||||||
|
uint32_t entry_pro = mmu_ll_read_entry(MMU_TABLE_CORE0, i);
|
||||||
|
if (entry_pro == SOC_MMU_PAGE_IN_FLASH(phys_page)) {
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32
|
||||||
|
if (j == 0) { /* SPI_FLASH_MMAP_DATA */
|
||||||
|
*out_ptr = (const void *)(SOC_MMU_VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
|
||||||
|
} else { /* SPI_FLASH_MMAP_INST */
|
||||||
|
*out_ptr = (const void *)(SOC_MMU_VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1]));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validates if given flash address has corresponding cache mapping, if yes, flushes cache memories */
|
||||||
|
IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
/* align start_addr & length to full MMU pages */
|
||||||
|
uint32_t page_start_addr = start_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
||||||
|
length += (start_addr - page_start_addr);
|
||||||
|
length = (length + SPI_FLASH_MMU_PAGE_SIZE - 1) & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
||||||
|
for (uint32_t addr = page_start_addr; addr < page_start_addr + length; addr += SPI_FLASH_MMU_PAGE_SIZE) {
|
||||||
|
uint32_t page = addr / SPI_FLASH_MMU_PAGE_SIZE;
|
||||||
|
// TODO: IDF-4969
|
||||||
|
if (page >= 256) {
|
||||||
|
return false; /* invalid address */
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *vaddr = NULL;
|
||||||
|
if (is_page_mapped_in_cache(page, &vaddr)) {
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
#if CONFIG_SPIRAM
|
||||||
|
esp_psram_extram_writeback_cache();
|
||||||
|
#endif
|
||||||
|
Cache_Flush(0);
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
Cache_Flush(1);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
#else // CONFIG_IDF_TARGET_ESP32
|
||||||
|
if (vaddr != NULL) {
|
||||||
|
Cache_Invalidate_Addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif //!CONFIG_SPI_FLASH_ROM_IMPL
|
||||||
|
|
||||||
|
#if !CONFIG_SPI_FLASH_ROM_IMPL || CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||||
|
static uint32_t IRAM_ATTR NOINLINE_ATTR spi_flash_protected_read_mmu_entry(int index)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
spi_flash_disable_interrupts_caches_and_other_cpu();
|
||||||
|
value = mmu_ll_read_entry(MMU_TABLE_CORE0, index);
|
||||||
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//The ROM implementation returns physical address of the PSRAM when the .text or .rodata is in the PSRAM.
|
||||||
|
//Always patch it when SPIRAM_FETCH_INSTRUCTIONS or SPIRAM_RODATA is set.
|
||||||
size_t spi_flash_cache2phys(const void *cached)
|
size_t spi_flash_cache2phys(const void *cached)
|
||||||
{
|
{
|
||||||
intptr_t c = (intptr_t)cached;
|
intptr_t c = (intptr_t)cached;
|
||||||
@@ -461,74 +537,4 @@ const void *IRAM_ATTR spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memo
|
|||||||
spi_flash_enable_interrupts_caches_and_other_cpu();
|
spi_flash_enable_interrupts_caches_and_other_cpu();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif //!CONFIG_SPI_FLASH_ROM_IMPL || CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||||
static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **out_ptr)
|
|
||||||
{
|
|
||||||
int start[2], end[2];
|
|
||||||
|
|
||||||
*out_ptr = NULL;
|
|
||||||
|
|
||||||
/* SPI_FLASH_MMAP_DATA */
|
|
||||||
start[0] = SOC_MMU_DROM0_PAGES_START;
|
|
||||||
end[0] = SOC_MMU_DROM0_PAGES_END;
|
|
||||||
|
|
||||||
/* SPI_FLASH_MMAP_INST */
|
|
||||||
start[1] = SOC_MMU_PRO_IRAM0_FIRST_USABLE_PAGE;
|
|
||||||
end[1] = SOC_MMU_IROM0_PAGES_END;
|
|
||||||
|
|
||||||
for (int j = 0; j < 2; j++) {
|
|
||||||
for (int i = start[j]; i < end[j]; i++) {
|
|
||||||
uint32_t entry_pro = mmu_ll_read_entry(MMU_TABLE_CORE0, i);
|
|
||||||
if (entry_pro == SOC_MMU_PAGE_IN_FLASH(phys_page)) {
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32
|
|
||||||
if (j == 0) { /* SPI_FLASH_MMAP_DATA */
|
|
||||||
*out_ptr = (const void *)(SOC_MMU_VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
|
|
||||||
} else { /* SPI_FLASH_MMAP_INST */
|
|
||||||
*out_ptr = (const void *)(SOC_MMU_VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1]));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validates if given flash address has corresponding cache mapping, if yes, flushes cache memories */
|
|
||||||
IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
/* align start_addr & length to full MMU pages */
|
|
||||||
uint32_t page_start_addr = start_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
|
||||||
length += (start_addr - page_start_addr);
|
|
||||||
length = (length + SPI_FLASH_MMU_PAGE_SIZE - 1) & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
|
||||||
for (uint32_t addr = page_start_addr; addr < page_start_addr + length; addr += SPI_FLASH_MMU_PAGE_SIZE) {
|
|
||||||
uint32_t page = addr / SPI_FLASH_MMU_PAGE_SIZE;
|
|
||||||
// TODO: IDF-4969
|
|
||||||
if (page >= 256) {
|
|
||||||
return false; /* invalid address */
|
|
||||||
}
|
|
||||||
|
|
||||||
const void *vaddr = NULL;
|
|
||||||
if (is_page_mapped_in_cache(page, &vaddr)) {
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
|
||||||
#if CONFIG_SPIRAM
|
|
||||||
esp_psram_extram_writeback_cache();
|
|
||||||
#endif
|
|
||||||
Cache_Flush(0);
|
|
||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
|
||||||
Cache_Flush(1);
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
#else // CONFIG_IDF_TARGET_ESP32
|
|
||||||
if (vaddr != NULL) {
|
|
||||||
Cache_Invalidate_Addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE);
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
#endif // CONFIG_IDF_TARGET_ESP32
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif //!CONFIG_SPI_FLASH_ROM_IMPL
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "esp_log.h"
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <freertos/semphr.h>
|
#include <freertos/semphr.h>
|
||||||
@@ -475,4 +476,15 @@ TEST_CASE("no stale data read post mmap and write partition", "[spi_flash][mmap]
|
|||||||
esp_partition_munmap(handle);
|
esp_partition_munmap(handle);
|
||||||
TEST_ASSERT_EQUAL(0, memcmp(buf, read_data, sizeof(buf)));
|
TEST_ASSERT_EQUAL(0, memcmp(buf, read_data, sizeof(buf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("spi_flash_cache2phys points to correct address", "[spi_flash]")
|
||||||
|
{
|
||||||
|
//_rodata_start, which begins with appdesc, is always the first segment of the bin.
|
||||||
|
extern int _rodata_start;
|
||||||
|
size_t addr = spi_flash_cache2phys(&_rodata_start);
|
||||||
|
|
||||||
|
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, "factory");
|
||||||
|
ESP_LOGI("running bin", "0x%p", (void*)addr);
|
||||||
|
TEST_ASSERT_HEX32_WITHIN(CONFIG_MMU_PAGE_SIZE/2, factory->address + CONFIG_MMU_PAGE_SIZE/2, addr);
|
||||||
|
}
|
||||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2)
|
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2)
|
||||||
|
Reference in New Issue
Block a user