Merge branch 'feat/mmu_s31' into 'master'

mmu: s31 support for external mmu

Closes IDF-14669

See merge request espressif/esp-idf!47133
This commit is contained in:
Armando (Dou Yiwen)
2026-04-03 02:42:20 +00:00
24 changed files with 123 additions and 54 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -285,10 +285,8 @@ void bootloader_flash_hardware_init(void)
{
esp_rom_spiflash_attach(0, false);
//init cache hal
// cache_hal_init(); // IDF-14651
//reset mmu
// mmu_hal_init(); // IDF-14669
// init cache and mmu
bootloader_init_ext_mem();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
@@ -89,10 +89,8 @@ esp_err_t bootloader_init(void)
bootloader_print_banner();
#if !CONFIG_APP_BUILD_TYPE_RAM
//init cache hal
// cache_hal_init(); IDF-14651
//reset mmu
// mmu_hal_init(); IDF-14669
// init cache and mmu
bootloader_init_ext_mem();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
@@ -8,8 +8,8 @@ components/esp_hw_support/test_apps/host_test_linux:
components/esp_hw_support/test_apps/mspi:
disable:
- if: IDF_TARGET not in ["esp32s3", "esp32p4", "esp32c61", "esp32c5"]
- if: CONFIG_NAME == "120sdr_120sdr" and IDF_TARGET in ["esp32s3", "esp32p4"]
- if: IDF_TARGET not in ["esp32s3", "esp32p4", "esp32c61", "esp32c5", "esp32s31"]
- if: CONFIG_NAME == "120sdr_120sdr" and IDF_TARGET in ["esp32s3", "esp32p4", "esp32s31"]
components/esp_hw_support/test_apps/mspi_psram_with_dfs:
disable:
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | --------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-P4 | ESP32-S3 | ESP32-S31 |
| ----------------- | -------- | --------- | -------- | -------- | --------- |
This project tests if Flash and PSRAM can work under different configurations.
To add new configuration, create one more sdkconfig.ci.NAME file in this directory.
@@ -74,6 +74,19 @@ def test_flash_psram_120sdr_120sdr(dut: IdfDut) -> None:
dut.run_all_single_board_cases()
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'esp32s31_120sdr_200ddr',
],
indirect=True,
)
@idf_parametrize('target', ['esp32s31'], indirect=['target'])
def test_flash_psram_esp32s31(dut: IdfDut) -> None:
dut.run_all_single_board_cases()
@pytest.mark.parametrize(
'config',
[
@@ -86,6 +99,10 @@ def test_flash_psram_120sdr_120sdr(dut: IdfDut) -> None:
'target,markers',
[
# S3 has no flash support auto suspend, this test is not applicable
(
'esp32s31',
(pytest.mark.generic,),
),
(
'esp32p4',
(pytest.mark.generic,),
@@ -0,0 +1,10 @@
CONFIG_IDF_TARGET="esp32s31"
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y
#use 80 until 120 is supported TODO: IDF-14653
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
#CONFIG_SPI_FLASH_HPM_ENA=y
#CONFIG_BOOTLOADER_FLASH_DC_AWARE=y
@@ -10,8 +10,6 @@
#include "../ext_mem_layout.h"
#include "hal/mmu_types.h"
// TODO: Please check this file [ESP32S31] IDF-14669
/**
* The start addresses in this list should always be sorted from low to high, as MMU driver will need to
* coalesce adjacent regions
@@ -29,7 +27,7 @@ const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = {
.start = SOC_MMU_PSRAM_LINEAR_ADDRESS_LOW,
.end = SOC_MMU_PSRAM_LINEAR_ADDRESS_HIGH,
.size = SOC_BUS_SIZE(SOC_MMU_PSRAM_LINEAR),
.bus_id = CACHE_BUS_IBUS1 | CACHE_BUS_DBUS1,
.bus_id = CACHE_BUS_IBUS1 | CACHE_BUS_DBUS0,
.targets = MMU_TARGET_PSRAM0,
.caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT,
},
@@ -1,7 +1,3 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/esp_mm/test_apps/mm:
disable:
- if: IDF_TARGET in ["esp32s31"]
temporary: true
reason: not support yet # TODO: [ESP32S31] IDF-14669
+14 -4
View File
@@ -10,16 +10,26 @@ set(COMPONENTS main esp_psram)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mm_test)
string(JOIN "," ignore_refs)
if(CONFIG_SOC_MMU_PER_EXT_MEM_TARGET AND CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM)
# On SOC_MMU_PER_EXT_MEM_TARGET chips, when xip_psram, we need
# - _instruction_reserved_start, _instruction_reserved_end
# - _rodata_reserved_start, _rodata_reserved_end
# to do some calculation. As we don't access the addresses, so we disable this check
list(APPEND ignore_refs esp_mmu_map_init/*)
list(APPEND ignore_refs
esp_mmu_map_init/__func__*
esp_mmu_map_init/_instruction_reserved_start
esp_mmu_map_init/_instruction_reserved_end
s_reserve_irom_region/__func__*
s_reserve_irom_region/_instruction_reserved_start
s_reserve_irom_region/_instruction_reserved_end
s_reserve_drom_region/__func__*
s_reserve_drom_region/_rodata_reserved_start
s_reserve_drom_region/_rodata_reserved_end
)
endif()
list(JOIN ignore_refs "," ignore_refs_arg)
idf_build_get_property(elf EXECUTABLE)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
@@ -29,7 +39,7 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
find-refs
--from-sections=.iram0.text
--to-sections=.flash.text,.flash.rodata
--ignore-refs=${ignore_refs}
--ignore-refs=${ignore_refs_arg}
--exit-code
DEPENDS ${elf}
)
+2 -2
View File
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
@@ -43,7 +43,7 @@ const static char *TAG = "CACHE_TEST";
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61
#define TEST_SYNC_START (SOC_DRAM_PSRAM_ADDRESS_LOW + TEST_OFFSET)
#define TEST_SYNC_SIZE CONFIG_CACHE_L1_CACHE_SIZE
#elif CONFIG_IDF_TARGET_ESP32H4
#elif CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32S31
#define TEST_SYNC_START (SOC_DRAM_PSRAM_ADDRESS_LOW + TEST_OFFSET)
#define TEST_SYNC_SIZE CONFIG_CACHE_L1_DCACHE_SIZE
#endif
+19 -5
View File
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@@ -16,7 +16,6 @@ from pytest_embedded_idf.utils import idf_parametrize
indirect=True,
)
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration')
def test_mmap(dut: Dut) -> None:
dut.run_all_single_board_cases(group='mmu')
@@ -30,6 +29,7 @@ def test_mmap(dut: Dut) -> None:
('psram_release_esp32s2', 'esp32s2'),
('psram_release_esp32s3', 'esp32s3'),
('psram_release_esp32p4', 'esp32p4'),
('psram_release_esp32s31', 'esp32s31'),
],
indirect=['config', 'target'],
)
@@ -41,7 +41,14 @@ def test_mmap_psram(dut: Dut) -> None:
# mmu tests with xip_psram
@pytest.mark.generic
@idf_parametrize(
'config,target', [('xip_psram_esp32s2', 'esp32s2'), ('xip_psram_esp32s3', 'esp32s3')], indirect=['config', 'target']
'config,target',
[
('xip_psram_esp32s2', 'esp32s2'),
('xip_psram_esp32s3', 'esp32s3'),
('xip_psram_esp32p4', 'esp32p4'),
('xip_psram_esp32s31', 'esp32s31'),
],
indirect=['config', 'target'],
)
def test_mmap_xip_psram(dut: Dut) -> None:
dut.run_all_single_board_cases(group='mmu')
@@ -57,7 +64,6 @@ def test_mmap_xip_psram(dut: Dut) -> None:
indirect=True,
)
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration')
def test_cache(dut: Dut) -> None:
dut.run_all_single_board_cases(group='cache')
@@ -71,6 +77,7 @@ def test_cache(dut: Dut) -> None:
('psram_release_esp32s2', 'esp32s2'),
('psram_release_esp32s3', 'esp32s3'),
('psram_release_esp32p4', 'esp32p4'),
('psram_release_esp32s31', 'esp32s31'),
],
indirect=['config', 'target'],
)
@@ -81,7 +88,14 @@ def test_cache_psram(dut: Dut) -> None:
# cache tests with xip_psram
@pytest.mark.generic
@idf_parametrize(
'config,target', [('xip_psram_esp32s2', 'esp32s2'), ('xip_psram_esp32s3', 'esp32s3')], indirect=['config', 'target']
'config,target',
[
('xip_psram_esp32s2', 'esp32s2'),
('xip_psram_esp32s3', 'esp32s3'),
('xip_psram_esp32p4', 'esp32p4'),
('xip_psram_esp32s31', 'esp32s31'),
],
indirect=['config', 'target'],
)
def test_cache_xip_psram(dut: Dut) -> None:
dut.run_all_single_board_cases(group='cache')
@@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s31"
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_SPIRAM=y
@@ -0,0 +1,7 @@
CONFIG_IDF_TARGET="esp32s31"
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
@@ -12,8 +12,6 @@
* Restrict to simple macros with numeric values, and/or #if/#endif blocks.
*/
/* This file might not accurate, please check [ESP32S31] IDF-14669 */
#include "sdkconfig.h"
#include "ld.common"
@@ -0,0 +1,20 @@
menu "Cache config"
config CACHE_L1_ICACHE_SIZE
hex
default 0x4000
config CACHE_L1_DCACHE_SIZE
hex
default 0x10000
config CACHE_L1_ICACHE_LINE_SIZE
int
default 64
config CACHE_L1_DCACHE_LINE_SIZE
int
default 64
endmenu # Cache config
@@ -20,8 +20,6 @@
extern "C" {
#endif
// TODO: [ESP32S31] IDF-14669
#define MMU_LL_FLASH_MMU_ID 0
#define MMU_LL_PSRAM_MMU_ID 1
#define MMU_LL_FLASH_VADDR_TO_PSRAM_VADDR(flash_vaddr) ((flash_vaddr) + SOC_IRAM_FLASH_PSRAM_OFFSET)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -97,10 +97,12 @@ extern "C" {
* MMU Linear Address
*----------------------------------------------------------------------------*/
/**
* - 64KB MMU page size: the last 0xFFFF, which is the offset
* - 1024 MMU entries for flash, 1024 MMU entries for psram, needs 0xFFF to hold it.
* - 64KB MMU page size: the lower 0xFFFF bits are the page offset
* - Flash linear addresses start from 0x00000000, PSRAM linear addresses start from 0x08000000
* - The mask keeps the bits needed to distinguish flash and PSRAM linear ranges while discarding
* the upper virtual-address tag bits
*
* Therefore, 0x3F,FFFF
* Therefore, use 0x0FFFFFFF.
*/
#define SOC_MMU_LINEAR_ADDR_MASK 0xFFFFFFF
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -11,8 +11,6 @@
extern "C" {
#endif
// TODO: to be checked IDF-14669
#if !SOC_MMU_PAGE_SIZE
/**
* We define `SOC_MMU_PAGE_SIZE` in soc/CMakeLists.txt.
@@ -74,7 +72,7 @@ extern "C" {
* - For a PSRAM MMU entry:
* physical page number is BIT(0)~BIT(9), so value bits are 0x3ff
*/
#define SOC_MMU_FLASH_VALID_VAL_MASK 0x3ff
#define SOC_MMU_FLASH_VALID_VAL_MASK 0x7ff
#define SOC_MMU_PSRAM_VALID_VAL_MASK 0x3ff
/**
* Max MMU available paddr page num.
@@ -99,12 +97,14 @@ extern "C" {
* MMU Linear Address
*----------------------------------------------------------------------------*/
/**
* - 64KB MMU page size: the last 0xFFFF, which is the offset
* - 1024 MMU entries for flash, 1024 MMU entries for psram, needs 0xFFF to hold it.
* - 64KB MMU page size: the lower 0xFFFF bits are the page offset
* - Flash linear addresses start from 0x00000000, PSRAM linear addresses start from 0x10000000
* - The mask keeps the bits needed to distinguish flash and PSRAM linear ranges while discarding
* the upper virtual-address tag bits
*
* Therefore, 0x3F,FFFF
* Therefore, use 0x1FFFFFFF.
*/
#define SOC_MMU_LINEAR_ADDR_MASK 0x1FFFFFFF //distinguish between flash and psram addresses
#define SOC_MMU_LINEAR_ADDR_MASK 0x1FFFFFFF
/**
* - If high linear address isn't 0, this means MMU can recognize these addresses
@@ -134,8 +134,6 @@
#define XTAL_CLK_FREQ (40*1000000)
//}}
// TODO: to be checked IDF-14669
/* Overall memory map */
/* Note: We should not use MACROs similar in cache_memory.h
* those are defined during run-time. But the MACROs here
@@ -210,7 +210,6 @@
#define SOC_LEDC_CHANNEL_NUM (6)
/*-------------------------- MMU CAPS ----------------------------------------*/
// TODO: [ESP32S31] IDF-14669
#define SOC_MMU_PERIPH_NUM (2U)
#define SOC_MMU_LINEAR_ADDRESS_REGION_NUM (2U)
#define SOC_MMU_DI_VADDR_SHARED (1) /*!< D/I vaddr are shared */
@@ -78,7 +78,6 @@ components/spi_flash/test_apps/flash_mmap:
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and SOC_SPIRAM_XIP_SUPPORTED == 1 and IDF_TARGET != "esp32s2"
disable:
- if: IDF_TARGET == "esp32c61" and CONFIG_NAME == "xip_psram_with_rom_impl"
- if: IDF_TARGET == "esp32s31" # TODO: IDF-14669
temporary: true
reason: not supported yet # TODO: [ESP32C61] IDF-12784
@@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
@@ -26,3 +26,4 @@ no_runner_tags:
- esp32h2,jtag
- esp32p4,jtag
- esp32s2,usb_host_flash_disk
- esp32s31,generic,rev_default # TODO: IDF-14694