Merge branch 'bugfix/esp32s2_flash_mmap_cache2phys_phys2cache' into 'master'

flash mmap: fix bug for cache2phys and phys2cache on esp32s2

See merge request espressif/esp-idf!8526
This commit is contained in:
Jiang Jiang Jian 2020-05-27 20:20:46 +08:00
commit 1056d2a1b7
10 changed files with 189 additions and 5 deletions

View file

@ -199,6 +199,15 @@ void IRAM_ATTR call_start_cpu0(void)
}
#endif
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
extern void instruction_flash_page_info_init(void);
instruction_flash_page_info_init();
#endif
#if CONFIG_SPIRAM_RODATA
extern void rodata_flash_page_info_init(void);
rodata_flash_page_info_init();
#endif
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
extern void esp_spiram_enable_instruction_access(void);
esp_spiram_enable_instruction_access();

View file

@ -91,6 +91,54 @@ void esp_spiram_writeback_cache(void);
*/
esp_err_t esp_spiram_reserve_dma_pool(size_t size);
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
extern int _instruction_reserved_start, _instruction_reserved_end;
/**
* @brief Get the start page number of the instruction in SPI flash
*
* @return start page number
*/
uint32_t instruction_flash_start_page_get(void);
/**
* @brief Get the end page number of the instruction in SPI flash
*
* @return end page number
*/
uint32_t instruction_flash_end_page_get(void);
/**
* @brief Get the offset of instruction from SPI flash to SPI RAM
*
* @return instruction offset
*/
int instruction_flash2spiram_offset(void);
#endif
#if CONFIG_SPIRAM_RODATA
extern int _rodata_reserved_start, _rodata_reserved_end;
/**
* @brief Get the start page number of the rodata in SPI flash
*
* @return start page number
*/
uint32_t rodata_flash_start_page_get(void);
/**
* @brief Get the end page number of the rodata in SPI flash
*
* @return end page number
*/
uint32_t rodata_flash_end_page_get(void);
/**
* @brief Get the offset number of rodata from SPI flash to SPI RAM
*
* @return rodata offset
*/
int rodata_flash2spiram_offset(void);
#endif
#ifdef __cplusplus
}
#endif

View file

@ -251,6 +251,7 @@ SECTIONS
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
.flash.rodata : ALIGN(0x10)
{
_rodata_reserved_start = ABSOLUTE(.);
_rodata_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
@ -308,12 +309,14 @@ SECTIONS
*(.tbss)
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.);
. = ALIGN(4);
} >default_rodata_seg
.flash.text :
{
_stext = .;
_instruction_reserved_start = ABSOLUTE(.);
_text_start = ABSOLUTE(.);
mapping[flash_text]
@ -324,6 +327,7 @@ SECTIONS
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_instruction_reserved_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is

View file

@ -161,6 +161,18 @@ static uint32_t page0_page = INVALID_PHY_PAGE;
static uint32_t instrcution_in_spiram = 0;
static uint32_t rodata_in_spiram = 0;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
static int instr_flash2spiram_offs = 0;
static uint32_t instr_start_page = 0;
static uint32_t instr_end_page = 0;
#endif
#if CONFIG_SPIRAM_RODATA
static int rodata_flash2spiram_offs = 0;
static uint32_t rodata_start_page = 0;
static uint32_t rodata_end_page = 0;
#endif
uint32_t esp_spiram_instruction_access_enabled(void)
{
return instrcution_in_spiram;
@ -171,6 +183,7 @@ uint32_t esp_spiram_rodata_access_enabled(void)
return rodata_in_spiram;
}
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
esp_err_t esp_spiram_enable_instruction_access(void)
{
uint32_t pages_in_flash = 0;
@ -181,12 +194,19 @@ esp_err_t esp_spiram_enable_instruction_access(void)
return ESP_FAIL;
}
ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE;
uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t));
mmu_value &= MMU_ADDRESS_MASK;
instr_flash2spiram_offs = mmu_value - pages_for_flash;
ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs);
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, pages_for_flash, &page0_page);
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, pages_for_flash, &page0_page);
instrcution_in_spiram = 1;
return ESP_OK;
}
#endif
#if CONFIG_SPIRAM_RODATA
esp_err_t esp_spiram_enable_rodata_access(void)
{
uint32_t pages_in_flash = 0;
@ -201,6 +221,11 @@ esp_err_t esp_spiram_enable_rodata_access(void)
}
ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE;
uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t));
mmu_value &= MMU_ADDRESS_MASK;
rodata_flash2spiram_offs = mmu_value - pages_for_flash;
ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, rodata_flash2spiram_offs);
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, pages_for_flash, &page0_page);
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, pages_for_flash, &page0_page);
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, pages_for_flash, &page0_page);
@ -208,6 +233,61 @@ esp_err_t esp_spiram_enable_rodata_access(void)
rodata_in_spiram = 1;
return ESP_OK;
}
#endif
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
void instruction_flash_page_info_init(void)
{
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE;
uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE;
instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t));
instr_start_page &= MMU_ADDRESS_MASK;
instr_end_page = instr_start_page + instr_page_cnt - 1;
}
uint32_t IRAM_ATTR instruction_flash_start_page_get(void)
{
return instr_start_page;
}
uint32_t IRAM_ATTR instruction_flash_end_page_get(void)
{
return instr_end_page;
}
int IRAM_ATTR instruction_flash2spiram_offset(void)
{
return instr_flash2spiram_offs;
}
#endif
#if CONFIG_SPIRAM_RODATA
void rodata_flash_page_info_init(void)
{
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - SOC_DROM_LOW + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE;
uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE;
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t));
rodata_start_page &= MMU_ADDRESS_MASK;
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
}
uint32_t IRAM_ATTR rodata_flash_start_page_get(void)
{
return rodata_start_page;
}
uint32_t IRAM_ATTR rodata_flash_end_page_get(void)
{
return rodata_end_page;
}
int IRAM_ATTR rodata_flash2spiram_offset(void)
{
return rodata_flash2spiram_offs;
}
#endif
esp_err_t esp_spiram_init(void)
{

View file

@ -467,11 +467,11 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
uint32_t instruction_use_spiram = 0;
uint32_t rodata_use_spiram = 0;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
extern uint32_t esp_spiram_instruction_access_enabled();
extern uint32_t esp_spiram_instruction_access_enabled(void);
instruction_use_spiram = esp_spiram_instruction_access_enabled();
#endif
#if CONFIG_SPIRAM_RODATA
extern uint32_t esp_spiram_rodata_access_enabled();
extern uint32_t esp_spiram_rodata_access_enabled(void);
rodata_use_spiram = esp_spiram_rodata_access_enabled();
#endif

View file

@ -378,15 +378,26 @@ uint32_t spi_flash_cache2phys(const void *cached)
{
intptr_t c = (intptr_t)cached;
size_t cache_page;
int offset = 0;
if (c >= VADDR1_START_ADDR && c < VADDR1_FIRST_USABLE_ADDR) {
/* IRAM address, doesn't map to flash */
return SPI_FLASH_CACHE2PHYS_FAIL;
} else if (c < VADDR1_FIRST_USABLE_ADDR) {
/* expect cache is in DROM */
cache_page = (c - VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + DROM0_PAGES_START;
#if CONFIG_SPIRAM_RODATA
if (c >= (uint32_t)&_rodata_reserved_start && c <= (uint32_t)&_rodata_reserved_end) {
offset = rodata_flash2spiram_offset();
}
#endif
} else {
/* expect cache is in IROM */
cache_page = (c - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (c >= (uint32_t)&_instruction_reserved_start && c <= (uint32_t)&_instruction_reserved_end) {
offset = instruction_flash2spiram_offset();
}
#endif
}
if (cache_page >= PAGES_LIMIT) {
@ -398,7 +409,7 @@ uint32_t spi_flash_cache2phys(const void *cached)
/* page is not mapped */
return SPI_FLASH_CACHE2PHYS_FAIL;
}
uint32_t phys_offs = (phys_page & MMU_ADDR_MASK)* SPI_FLASH_MMU_PAGE_SIZE;
uint32_t phys_offs = ((phys_page & MMU_ADDR_MASK) + offset) * SPI_FLASH_MMU_PAGE_SIZE;
return phys_offs | (c & (SPI_FLASH_MMU_PAGE_SIZE-1));
}
@ -422,7 +433,24 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me
spi_flash_disable_interrupts_caches_and_other_cpu();
DPORT_INTERRUPT_DISABLE();
for (int i = start; i < end; i++) {
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) {
uint32_t mmu_value = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
if (mmu_value & MMU_ACCESS_SPIRAM) {
mmu_value += instruction_flash2spiram_offset();
mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
}
}
#endif
#if CONFIG_SPIRAM_RODATA
if (phys_page >= rodata_flash_start_page_get() && phys_page <= rodata_flash_start_page_get()) {
if (mmu_value & MMU_ACCESS_SPIRAM) {
mmu_value += rodata_flash2spiram_offset();
mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH;
}
}
#endif
if (mmu_value == PAGE_IN_FLASH(phys_page)) {
i -= page_delta;
intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i);
DPORT_INTERRUPT_RESTORE();

View file

@ -539,7 +539,7 @@ UT_034:
UT_035:
extends: .unit_test_s2_template
parallel: 34
parallel: 36
tags:
- ESP32S2_IDF
- UT_T1_1

View file

@ -0,0 +1,5 @@
TEST_COMPONENTS=spi_flash
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=n
CONFIG_IDF_TARGET="esp32s2"

View file

@ -0,0 +1,5 @@
TEST_COMPONENTS=spi_flash
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y
CONFIG_IDF_TARGET="esp32s2"

View file

@ -0,0 +1,5 @@
TEST_COMPONENTS=spi_flash
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=n
CONFIG_SPIRAM_RODATA=y
CONFIG_IDF_TARGET="esp32s2"