Merge branch 'test/add_cache2phys_xip_tests' into 'master'

fix(mmap): fixed spi_flash_phys2cache return addr in PSRAM issue

See merge request espressif/esp-idf!31083
This commit is contained in:
Michael (XIAO Xufeng) 2024-09-18 23:53:47 +08:00
commit ed92c2c226
33 changed files with 144 additions and 89 deletions

View File

@ -1,7 +0,0 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/app_update/test_apps:
disable:
- if: IDF_TARGET in ["esp32c61"]
temporary: true
reason: target esp32c61 is not supported yet # TODO: [ESP32C61] IDF-9245

View File

@ -1,26 +0,0 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import re
import pytest
from pytest_embedded import Dut
DEFAULT_TIMEOUT = 20
TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n')
def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None:
for stage in range(1, stages + 1):
dut.write(str(test_case_num))
dut.expect(TEST_SUBMENU_PATTERN_PYTEST, timeout=DEFAULT_TIMEOUT)
dut.write(str(stage))
if stage != stages:
dut.expect_exact('Press ENTER to see the list of tests.')
@pytest.mark.supported_targets
# TODO: [ESP32C61] IDF-9245, IDF-9247, IDF-10983
@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep')
@pytest.mark.generic
def test_app_update(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=90)

View File

@ -0,0 +1,12 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/app_update/test_apps:
enable:
- if: CONFIG_NAME == "defaults" and IDF_TARGET != "linux"
- if: CONFIG_NAME == "xip_psram" and IDF_TARGET in ["esp32s2", "esp32s3", "esp32p4"]
# S2 doesn't have ROM for flash
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and IDF_TARGET in ["esp32s3", "esp32p4"]
disable:
- if: IDF_TARGET in ["esp32c61"]
temporary: true
reason: target esp32c61 is not supported yet # TODO: [ESP32C61] IDF-9245

View File

@ -1,4 +1,4 @@
idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver spi_flash
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver spi_flash esp_psram
WHOLE_ARCHIVE)

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.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(&not_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);
}

View File

@ -0,0 +1,52 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import re
import pytest
from pytest_embedded import Dut
DEFAULT_TIMEOUT = 20
TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n')
@pytest.mark.supported_targets
@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='C5 has not supported deep sleep') # TODO: [ESP32C5] IDF-8640, IDF-10317
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'defaults',
],
indirect=True,
)
def test_app_update(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=90)
@pytest.mark.supported_targets
# TODO: [ESP32C61] IDF-9245, IDF-9247, IDF-10983
@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep')
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'xip_psram',
],
indirect=True,
)
def test_app_update_xip_psram(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=90)
@pytest.mark.supported_targets
@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='C5 has not supported deep sleep') # TODO: [ESP32C5] IDF-8640, IDF-10317
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'xip_psram_with_rom_impl',
],
indirect=True,
)
def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=90)

View File

@ -0,0 +1,2 @@
# don't delete.
# used for CI to compile a default config when 'sdkconfig.ci.xxxx' is exist

View File

@ -1,2 +1,2 @@
CONFIG_IDF_TARGET="esp32c5"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y

View File

@ -0,0 +1,3 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
CONFIG_SPI_FLASH_ROM_IMPL=y

View File

@ -270,38 +270,6 @@ uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
return len / CONFIG_MMU_PAGE_SIZE;
}
const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory)
{
esp_err_t ret = ESP_FAIL;
void *ptr = NULL;
mmu_target_t target = MMU_TARGET_FLASH0;
__attribute__((unused)) uint32_t phys_page = phys_offs / CONFIG_MMU_PAGE_SIZE;
#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
target = MMU_TARGET_PSRAM0;
phys_offs -= instruction_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
}
#endif
#if CONFIG_SPIRAM_RODATA
if (phys_page >= rodata_flash_start_page_get() && phys_page <= rodata_flash_start_page_get()) {
target = MMU_TARGET_PSRAM0;
phys_offs -= rodata_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
}
#endif
#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
mmu_vaddr_t type = (memory == SPI_FLASH_MMAP_DATA) ? MMU_VADDR_DATA : MMU_VADDR_INSTRUCTION;
ret = esp_mmu_paddr_to_vaddr(phys_offs, target, type, &ptr);
if (ret == ESP_ERR_NOT_FOUND) {
return NULL;
}
assert(ret == ESP_OK);
return (const void *)ptr;
}
static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_addr, const void **out_ptr)
{
*out_ptr = NULL;
@ -398,4 +366,36 @@ size_t spi_flash_cache2phys(const void *cached)
return paddr + offset * CONFIG_MMU_PAGE_SIZE;
}
const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory)
{
esp_err_t ret = ESP_FAIL;
void *ptr = NULL;
mmu_target_t target = MMU_TARGET_FLASH0;
__attribute__((unused)) uint32_t phys_page = phys_offs / CONFIG_MMU_PAGE_SIZE;
#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
target = MMU_TARGET_PSRAM0;
phys_offs -= instruction_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
}
#endif
#if CONFIG_SPIRAM_RODATA
if (phys_page >= rodata_flash_start_page_get() && phys_page <= rodata_flash_start_page_get()) {
target = MMU_TARGET_PSRAM0;
phys_offs -= rodata_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
}
#endif
#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
mmu_vaddr_t type = (memory == SPI_FLASH_MMAP_DATA) ? MMU_VADDR_DATA : MMU_VADDR_INSTRUCTION;
ret = esp_mmu_paddr_to_vaddr(phys_offs, target, type, &ptr);
if (ret == ESP_ERR_NOT_FOUND) {
return NULL;
}
assert(ret == ESP_OK);
return (const void *)ptr;
}
#endif //!CONFIG_SPI_FLASH_ROM_IMPL || CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA

View File

@ -30,6 +30,11 @@ components/spi_flash/test_apps/flash_mmap:
depends_components:
- esp_mm
- spi_flash
enable:
- if: CONFIG_NAME in ["release", "rom_impl"] and IDF_TARGET != "linux"
- if: CONFIG_NAME == "xip_psram" and IDF_TARGET in ["esp32s2", "esp32s3", "esp32p4"]
# S2 doesn't have ROM for flash
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and IDF_TARGET in ["esp32s3", "esp32p4"]
components/spi_flash/test_apps/flash_suspend:
disable:

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "esp_log.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
@ -517,3 +518,14 @@ TEST_CASE("no stale data read post mmap and write partition", "[spi_flash][mmap]
TEST_ASSERT_EQUAL(0, memcmp(buf, read_data, sizeof(buf)));
#endif
}
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);
}

View File

@ -1,5 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, 0x9000, 0x6000,
factory, 0, 0, 0x10000, 1M
flash_test, data, fat, , 528K
flash_test, data, fat, 0x10000, 528K
# This partition is placed to this weird address intentionally to test spi_flash_cache2phys
factory, 0, 0, 0xF0000, 1M

1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, 0x9000, 0x6000,
4 factory, 0, 0, 0x10000, 1M flash_test, data, fat, 0x10000, 528K
5 flash_test, data, fat, , 528K # This partition is placed to this weird address intentionally to test spi_flash_cache2phys
6 factory, 0, 0, 0xF0000, 1M

View File

@ -34,21 +34,20 @@ def test_flash_mmap_rom_impl(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=30)
XIP_CONFIGS = [
pytest.param('xip_psram_esp32s2', marks=[pytest.mark.esp32s2]),
pytest.param('xip_psram_esp32s3', marks=[pytest.mark.esp32s3]),
pytest.param('xip_psram_esp32c5', marks=[pytest.mark.esp32c5]),
pytest.param('xip_psram_esp32c61', marks=[pytest.mark.esp32c61]),
]
@pytest.mark.supported_targets
@pytest.mark.generic
@pytest.mark.parametrize('config', XIP_CONFIGS, indirect=True)
@pytest.mark.parametrize(
'config',
[
'xip_psram',
],
indirect=True,
)
def test_flash_mmap_xip_psram(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=30)
@pytest.mark.esp32s3
@pytest.mark.supported_targets
@pytest.mark.generic
@pytest.mark.parametrize(
'config',

View File

@ -1,2 +1,2 @@
CONFIG_IDF_TARGET="esp32c61"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y

View File

@ -1,3 +0,0 @@
CONFIG_IDF_TARGET="esp32s2"
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y

View File

@ -1,3 +0,0 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y

View File

@ -1,4 +1,3 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
CONFIG_SPI_FLASH_ROM_IMPL=y