From 9be8dccef55eea8837bbbad2878b41e03ae0c2e7 Mon Sep 17 00:00:00 2001 From: armando Date: Thu, 10 Jul 2025 14:17:07 +0800 Subject: [PATCH] feat(psram): psram support on h4 --- .../test_apps/.build-test-rules.yml | 1 + .../test_apps/esp_common/pytest_esp_common.py | 37 +- ...p_psram_esp32p4 => sdkconfig.ci.xip_psram} | 1 - .../esp_common/sdkconfig.ci.xip_psram_esp32s2 | 8 - .../esp_common/sdkconfig.ci.xip_psram_esp32s3 | 8 - .../esp_psram/device/esp_psram_impl_ap_quad.c | 4 +- components/esp_psram/esp32h4/Kconfig.spiram | 78 +++ .../esp_psram/test_apps/psram/README.md | 4 +- .../esp32h4/include/esp32h4/rom/spi_flash.h | 118 ++++ components/esp_system/ld/esp32h4/memory.ld.in | 5 + .../esp_system/ld/esp32h4/sections.ld.in | 39 ++ components/hal/esp32/include/hal/sdmmc_ll.h | 2 +- components/hal/esp32h4/include/hal/mspi_ll.h | 3 - .../hal/esp32h4/include/hal/psram_ctrlr_ll.h | 516 ++++++++++++++++++ components/hal/esp32p4/include/hal/sdmmc_ll.h | 2 +- components/hal/esp32s3/include/hal/sdmmc_ll.h | 2 +- .../esp32h4/include/soc/Kconfig.soc_caps.in | 12 + components/soc/esp32h4/include/soc/soc_caps.h | 6 +- .../soc/esp32h4/register/soc/spi_mem_c_reg.h | 101 ++++ .../esp32h4/register/soc/spi_mem_c_struct.h | 186 ++++++- examples/system/xip_from_psram/README.md | 4 +- 21 files changed, 1075 insertions(+), 62 deletions(-) rename components/esp_common/test_apps/esp_common/{sdkconfig.ci.xip_psram_esp32p4 => sdkconfig.ci.xip_psram} (88%) delete mode 100644 components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 delete mode 100644 components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 create mode 100644 components/esp_psram/esp32h4/Kconfig.spiram create mode 100644 components/hal/esp32h4/include/hal/psram_ctrlr_ll.h diff --git a/components/esp_common/test_apps/.build-test-rules.yml b/components/esp_common/test_apps/.build-test-rules.yml index c52d810e15..eea2257c6a 100644 --- a/components/esp_common/test_apps/.build-test-rules.yml +++ b/components/esp_common/test_apps/.build-test-rules.yml @@ -4,3 +4,4 @@ components/esp_common/test_apps/esp_common: disable: - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 - if: CONFIG_NAME == "psram_noinit" and SOC_SPIRAM_SUPPORTED != 1 + - if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED != 1 diff --git a/components/esp_common/test_apps/esp_common/pytest_esp_common.py b/components/esp_common/test_apps/esp_common/pytest_esp_common.py index 726657be42..95f4d1036d 100644 --- a/components/esp_common/test_apps/esp_common/pytest_esp_common.py +++ b/components/esp_common/test_apps/esp_common/pytest_esp_common.py @@ -5,6 +5,7 @@ from typing import Any import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -27,7 +28,7 @@ def test_esp_common(dut: Dut) -> None: ], indirect=True, ) -@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target']) def test_esp_attr_psram_noinit(dut: Dut) -> None: dut.run_all_single_board_cases() @@ -39,7 +40,7 @@ def test_esp_attr_psram_noinit(dut: Dut) -> None: ['psram_noinit'], indirect=True, ) -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target']) def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None: case_tester.run_all_multi_stage_cases() @@ -53,7 +54,7 @@ def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None: ], indirect=True, ) -@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target']) def test_esp_attr_psram(dut: Dut) -> None: dut.run_all_single_board_cases() @@ -62,33 +63,9 @@ def test_esp_attr_psram(dut: Dut) -> None: @pytest.mark.generic @pytest.mark.parametrize( 'config', - ['xip_psram_esp32s2'], + ['xip_psram'], indirect=True, ) -@idf_parametrize('target', ['esp32s2'], indirect=['target']) -def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None: - dut.run_all_single_board_cases() - - -# psram attr tests with xip_psram -@pytest.mark.generic -@pytest.mark.parametrize( - 'config', - ['xip_psram_esp32s3'], - indirect=True, -) -@idf_parametrize('target', ['esp32s3'], indirect=['target']) -def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None: - dut.run_all_single_board_cases() - - -# psram attr tests with xip_psram -@pytest.mark.generic -@pytest.mark.parametrize( - 'config', - ['xip_psram_esp32p4'], - indirect=True, -) -@idf_parametrize('target', ['esp32p4'], indirect=['target']) -def test_esp_attr_xip_psram_esp32p4(dut: Dut) -> None: +@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_XIP_SUPPORTED == 1'), indirect=['target']) +def test_esp_attr_xip_psram(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram similarity index 88% rename from components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 rename to components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram index 5470efa120..7f182e7a5a 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram @@ -1,6 +1,5 @@ # For XiP PSRAM EXT_RAM_BSS_ATTR -CONFIG_IDF_TARGET="esp32p4" CONFIG_SPIRAM=y CONFIG_SPIRAM_XIP_FROM_PSRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 deleted file mode 100644 index 3c7418b55d..0000000000 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 +++ /dev/null @@ -1,8 +0,0 @@ -# For XiP PSRAM EXT_RAM_BSS_ATTR - -CONFIG_IDF_TARGET="esp32s2" -CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y -CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y -CONFIG_SPIRAM_RODATA=y -CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 deleted file mode 100644 index 53125cb9b8..0000000000 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 +++ /dev/null @@ -1,8 +0,0 @@ -# For XiP PSRAM EXT_RAM_BSS_ATTR - -CONFIG_IDF_TARGET="esp32s3" -CONFIG_SPIRAM=y -CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y -CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y -CONFIG_SPIRAM_RODATA=y -CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y diff --git a/components/esp_psram/device/esp_psram_impl_ap_quad.c b/components/esp_psram/device/esp_psram_impl_ap_quad.c index 82de38f55f..c28dde2fa4 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_quad.c +++ b/components/esp_psram/device/esp_psram_impl_ap_quad.c @@ -9,7 +9,6 @@ #include "esp_log.h" #include "esp_private/esp_psram_impl.h" #include "rom/spi_flash.h" -#include "rom/opi_flash.h" #include "esp_rom_gpio.h" #include "esp_rom_efuse.h" #include "hal/gpio_hal.h" @@ -294,7 +293,8 @@ static void s_config_psram_clock(bool init_state) } else { // This function can be extended if we have other psram frequency -#if (CONFIG_SPIRAM_SPEED == 80) +#if (CONFIG_SPIRAM_SPEED == 80) || (CONFIG_SPIRAM_SPEED == 48) + // IDF-13632, update 48M to 64M clock_conf = psram_ctrlr_ll_calculate_clock_reg(1); #elif (CONFIG_SPIRAM_SPEED == 40) clock_conf = psram_ctrlr_ll_calculate_clock_reg(2); diff --git a/components/esp_psram/esp32h4/Kconfig.spiram b/components/esp_psram/esp32h4/Kconfig.spiram new file mode 100644 index 0000000000..0dacd42afb --- /dev/null +++ b/components/esp_psram/esp32h4/Kconfig.spiram @@ -0,0 +1,78 @@ +config SPIRAM + bool "Support for external, SPI-connected RAM" + default "n" + help + This enables support for an external SPI RAM chip, connected in parallel with the + main SPI flash chip. + +menu "SPI RAM config" + depends on SPIRAM + + choice SPIRAM_MODE + prompt "Mode of SPI RAM chip in use" + default SPIRAM_MODE_QUAD + + config SPIRAM_MODE_QUAD + bool "Quad Mode PSRAM" + + endchoice + + choice SPIRAM_SPEED + prompt "Set RAM clock speed" + default SPIRAM_SPEED_48M + help + Select the speed for the SPI RAM chip. + + config SPIRAM_SPEED_48M + bool "48Mhz clock speed" + endchoice + + config SPIRAM_SPEED + int + default 48 if SPIRAM_SPEED_48M + default 64 if SPIRAM_SPEED_64M + + config SPIRAM_FETCH_INSTRUCTIONS + bool + help + Enable this option allows moving application's instruction segment from the SPI Flash to PSRAM + + config SPIRAM_RODATA + bool + help + Enable this option allows moving application's rodata segment from the SPI Flash to + PSRAM + + config SPIRAM_XIP_FROM_PSRAM + bool "Enable Executable in place from (XiP) from PSRAM feature (READ HELP)" + default n + select SPIRAM_FETCH_INSTRUCTIONS + select SPIRAM_RODATA + select SPIRAM_FLASH_LOAD_TO_PSRAM + help + If enabled, firmware in flash including instructions and data will be moved into PSRAM on startup, + firmware code will execute directly from PSRAM. + + With this option enabled, code that requires execution during an MSPI1 Flash operation + does not have to be placed in IRAM. Therefore codes that need to be executing during Flash + operations can continue working normally. + + This feature is useful for high throughput peripheral involved applications to improve + the performance during MSPI1 flash operations. + + config SPIRAM_FLASH_LOAD_TO_PSRAM + bool + help + This is a helper indicating this condition: + `CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32H4` + + config SPIRAM_ECC_ENABLE + bool "Enable PSRAM ECC" + default n + help + Enable MSPI Error-Correcting Code function when accessing PSRAM. + + If enabled, 1/8 of the PSRAM total size will be reserved for error-correcting code. + + source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here +endmenu diff --git a/components/esp_psram/test_apps/psram/README.md b/components/esp_psram/test_apps/psram/README.md index 6f2974f7f5..cd0b24f6cb 100644 --- a/components/esp_psram/test_apps/psram/README.md +++ b/components/esp_psram/test_apps/psram/README.md @@ -1,4 +1,4 @@ -| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- | -------- | This test app is used to test PSRAM diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h b/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h index 80b17ef3c0..4e1d435b09 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h @@ -455,6 +455,124 @@ uint16_t esp_rom_spiflash_common_cmd(esp_rom_spiflash_common_cmd_t *cmd); extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs; +typedef struct { + uint16_t cmd; /*!< Command value */ + uint16_t cmdBitLen; /*!< Command byte length*/ + uint32_t *addr; /*!< Point to address value*/ + uint32_t addrBitLen; /*!< Address byte length*/ + uint32_t *txData; /*!< Point to send data buffer*/ + uint32_t txDataBitLen; /*!< Send data byte length.*/ + uint32_t *rxData; /*!< Point to receive data buffer*/ + uint32_t rxDataBitLen; /*!< Receive Data byte length.*/ + uint32_t dummyBitLen; +} esp_rom_spi_cmd_t; + +// Definition of MX25UM25645G Octa Flash +// SPI status register +#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0 +#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1 +#define ESP_ROM_SPIFLASH_BP0 BIT2 +#define ESP_ROM_SPIFLASH_BP1 BIT3 +#define ESP_ROM_SPIFLASH_BP2 BIT4 +#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) +#define ESP_ROM_SPIFLASH_QE BIT9 + +#define FLASH_OP_MODE_RDCMD_DOUT 0x3B +#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000 +#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000 +#define ESP_ROM_FLASH_PAGE_SIZE 256 + +// FLASH commands +#define ROM_FLASH_CMD_RDID 0x9F +#define ROM_FLASH_CMD_WRSR 0x01 +#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_WREN 0x06 +#define ROM_FLASH_CMD_WRDI 0x04 +#define ROM_FLASH_CMD_RDSR 0x05 +#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_ERASE_SEC 0x20 +#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52 +#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8 +#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ +#define ROM_FLASH_CMD_RSTEN 0x66 +#define ROM_FLASH_CMD_RST 0x99 + +#define ROM_FLASH_CMD_SE4B 0x21 +#define ROM_FLASH_CMD_SE4B_OCT 0xDE21 +#define ROM_FLASH_CMD_BE4B 0xDC +#define ROM_FLASH_CMD_BE4B_OCT 0x23DC +#define ROM_FLASH_CMD_RSTEN_OCT 0x9966 +#define ROM_FLASH_CMD_RST_OCT 0x6699 + +#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC +#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE +#define ROM_FLASH_CMD_FSTRD4B 0x0C +#define ROM_FLASH_CMD_PP4B 0x12 +#define ROM_FLASH_CMD_PP4B_OCT 0xED12 + +#define ROM_FLASH_CMD_RDID_OCT 0x609F +#define ROM_FLASH_CMD_WREN_OCT 0xF906 +#define ROM_FLASH_CMD_RDSR_OCT 0xFA05 +#define ROM_FLASH_CMD_RDCR2 0x71 +#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71 +#define ROM_FLASH_CMD_WRCR2 0x72 +#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72 + +// Definitions for GigaDevice GD25LX256E Flash +#define ROM_FLASH_CMD_RDFSR_GD 0x70 +#define ROM_FLASH_CMD_RD_GD 0x03 +#define ROM_FLASH_CMD_RD4B_GD 0x13 +#define ROM_FLASH_CMD_FSTRD_GD 0x0B +#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C +#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B +#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C +#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB +#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC +#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD + +#define ROM_FLASH_CMD_PP_GD 0x02 +#define ROM_FLASH_CMD_PP4B_GD 0x12 +#define ROM_FLASH_CMD_PP_OOUT_GD 0x82 +#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84 +#define ROM_FLASH_CMD_PP_OIO_GD 0xC2 +#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E + +#define ROM_FLASH_CMD_SE_GD 0x20 +#define ROM_FLASH_CMD_SE4B_GD 0x21 +#define ROM_FLASH_CMD_BE32K_GD 0x52 +#define ROM_FLASH_CMD_BE32K4B_GD 0x5C +#define ROM_FLASH_CMD_BE64K_GD 0xD8 +#define ROM_FLASH_CMD_BE64K4B_GD 0xDC + +#define ROM_FLASH_CMD_EN4B_GD 0xB7 +#define ROM_FLASH_CMD_DIS4B_GD 0xE9 + +// spi user mode command config +/** + * @brief Config the spi user command + * @param spi_num spi port + * @param pcmd pointer to accept the spi command struct + */ +void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t* pcmd); + +/** + * @brief Start a spi user command sequence + * @param spi_num spi port + * @param rx_buf buffer pointer to receive data + * @param rx_len receive data length in byte + * @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1 + * @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission + */ +void esp_rom_spi_cmd_start(int spi_num, uint8_t* rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase); + +// set SPI read/write mode +/** + * @brief Set SPI operation mode + * @param spi_num spi port + * @param mode Flash Read Mode + */ +void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); + #ifdef __cplusplus } #endif diff --git a/components/esp_system/ld/esp32h4/memory.ld.in b/components/esp_system/ld/esp32h4/memory.ld.in index ac79824bb4..8d1855351a 100644 --- a/components/esp_system/ld/esp32h4/memory.ld.in +++ b/components/esp_system/ld/esp32h4/memory.ld.in @@ -64,6 +64,11 @@ MEMORY /* (See irom_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /** + * `extern_ram_seg` and `drom_seg` / `irom_seg` share the same bus and the address region. + * A dummy section is used to avoid overlap. See `.ext_ram.dummy` in `sections.ld.in` + */ + extern_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 } /* Heap ends at top of sram_seg */ diff --git a/components/esp_system/ld/esp32h4/sections.ld.in b/components/esp_system/ld/esp32h4/sections.ld.in index 9e5761b2c1..95eeef9be4 100644 --- a/components/esp_system/ld/esp32h4/sections.ld.in +++ b/components/esp_system/ld/esp32h4/sections.ld.in @@ -306,6 +306,45 @@ SECTIONS ALIGNED_SYMBOL(16, _heap_start) } > sram_seg + /* External RAM */ + /** + * This section is required to skip flash sections, because `extern_ram_seg` + * and `drom_seg` / `irom_seg` are on the same bus when app build use flash sections + */ + .ext_ram.dummy (NOLOAD): + { + . = ORIGIN(extern_ram_seg); + . = . + (_rodata_reserved_end - _flash_rodata_dummy_start); + . = ALIGN (_esp_mmu_page_size); + } > extern_ram_seg + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + /* This section holds .ext_ram.bss data, and will be put in PSRAM */ + .ext_ram.bss (NOLOAD) : + { + _ext_ram_bss_start = ABSOLUTE(.); + + mapping[extern_ram] + + ALIGNED_SYMBOL(4, _ext_ram_bss_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + #include "elf_misc.ld.in" } diff --git a/components/hal/esp32/include/hal/sdmmc_ll.h b/components/hal/esp32/include/hal/sdmmc_ll.h index 7c94bded11..46ca405084 100644 --- a/components/hal/esp32/include/hal/sdmmc_ll.h +++ b/components/hal/esp32/include/hal/sdmmc_ll.h @@ -144,7 +144,7 @@ static inline void sdmmc_ll_reset_register(int group_id) * @brief Select SDMMC clock source * * @param hw hardware instance address - * @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t` + * @param clk_src clock source, see valid sources in type `soc_periph_sdmmc_clk_src_t` */ static inline void sdmmc_ll_select_clk_source(sdmmc_dev_t *hw, soc_periph_sdmmc_clk_src_t clk_src) { diff --git a/components/hal/esp32h4/include/hal/mspi_ll.h b/components/hal/esp32h4/include/hal/mspi_ll.h index df1face1d5..9ac94c7d13 100644 --- a/components/hal/esp32h4/include/hal/mspi_ll.h +++ b/components/hal/esp32h4/include/hal/mspi_ll.h @@ -32,9 +32,6 @@ extern "C" { #endif -//Timing tuning not applied, and flash has its own clock source. Can change flash clock source -#define MSPI_TIMING_LL_FLASH_CLK_SRC_CHANGEABLE 1 - /************************** MSPI pll clock configurations **************************/ /* * @brief Select FLASH clock source diff --git a/components/hal/esp32h4/include/hal/psram_ctrlr_ll.h b/components/hal/esp32h4/include/hal/psram_ctrlr_ll.h new file mode 100644 index 0000000000..5a04e3b2bb --- /dev/null +++ b/components/hal/esp32h4/include/hal/psram_ctrlr_ll.h @@ -0,0 +1,516 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include +#include +#include "hal/assert.h" +#include "hal/misc.h" +#include "soc/spi_mem_struct.h" +#include "soc/spi_mem_reg.h" +#include "soc/clk_tree_defs.h" +#include "rom/spi_flash.h" +#include "hal/psram_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PSRAM_CTRLR_LL_MSPI_ID_0 0 +#define PSRAM_CTRLR_LL_MSPI_ID_1 1 + +#define PSRAM_LL_CS_SEL SPI_MEM_CS1_DIS_M +#define PSRAM_CTRLR_LL_PMS_REGION_NUMS 4 +#define PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE (1<<0) +#define PSRAM_CTRLR_LL_PMS_ATTR_READABLE (1<<1) + +/** + * @brief PSRAM enum for cs id. + */ +typedef enum { + PSRAM_LL_CS_ID_0 = 0, + PSRAM_LL_CS_ID_1 = 1, +} psram_ll_cs_id_t; + +/** + * @brief PSRAM ECC mode + */ +typedef enum { + PSRAM_LL_ECC_MODE_16TO17 = 0, + PSRAM_LL_ECC_MODE_16TO18 = 1, +} psram_ll_ecc_mode_t; + +/** + * @brief Set PSRAM write cmd + * + * @param mspi_id mspi_id + * @param cmd_bitlen command bitlen + * @param cmd_val command value + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_wr_cmd(uint32_t mspi_id, uint32_t cmd_bitlen, uint32_t cmd_val) +{ + (void)mspi_id; + HAL_ASSERT(cmd_bitlen > 0); + SPIMEM0.mem_cache_sctrl.mem_cache_sram_usr_wcmd = 1; + SPIMEM0.mem_sram_dwr_cmd.mem_cache_sram_usr_wr_cmd_bitlen = cmd_bitlen - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(SPIMEM0.mem_sram_dwr_cmd, mem_cache_sram_usr_wr_cmd_value, cmd_val); +} + +/** + * @brief Set PSRAM read cmd + * + * @param mspi_id mspi_id + * @param cmd_bitlen command bitlen + * @param cmd_val command value + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_rd_cmd(uint32_t mspi_id, uint32_t cmd_bitlen, uint32_t cmd_val) +{ + (void)mspi_id; + HAL_ASSERT(cmd_bitlen > 0); + SPIMEM0.mem_cache_sctrl.mem_cache_sram_usr_rcmd = 1; + SPIMEM0.mem_sram_drd_cmd.mem_cache_sram_usr_rd_cmd_bitlen = cmd_bitlen - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(SPIMEM0.mem_sram_drd_cmd, mem_cache_sram_usr_rd_cmd_value, cmd_val); +} + +/** + * @brief Set PSRAM addr bitlen + * + * @param mspi_id mspi_id + * @param addr_bitlen address bitlen + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_addr_bitlen(uint32_t mspi_id, uint32_t addr_bitlen) +{ + (void)mspi_id; + HAL_ASSERT(addr_bitlen > 0); + SPIMEM0.mem_cache_sctrl.mem_sram_addr_bitlen = addr_bitlen - 1; +} + +/** + * @brief Set PSRAM read dummy + * + * @param mspi_id mspi_id + * @param dummy_n dummy number + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_rd_dummy(uint32_t mspi_id, uint32_t dummy_n) +{ + (void)mspi_id; + HAL_ASSERT(dummy_n > 0); + SPIMEM0.mem_cache_sctrl.mem_usr_rd_sram_dummy = 1; + SPIMEM0.mem_cache_sctrl.mem_sram_rdummy_cyclelen = dummy_n - 1; +} + +/** + * @brief Set PSRAM bus clock + * + * @param mspi_id mspi_id + * @param clock_conf Configuration value for psram clock + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_bus_clock(uint32_t mspi_id, uint32_t clock_conf) +{ + SPIMEM0.mem_sram_clk.val = clock_conf; +} + +/** + * @brief Set SPI1 bus clock to initialise PSRAM + * + * @param mspi_id mspi_id + * @param clock_conf Configuration value for psram clock + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_spi1_bus_clock(uint32_t mspi_id, uint32_t clock_conf) +{ + HAL_ASSERT(mspi_id == PSRAM_CTRLR_LL_MSPI_ID_1); + SPIMEM1.clock.val = clock_conf; +} + +/** + * Calculate spi_flash clock frequency division parameters for register. + * + * @param clkdiv frequency division factor + * + * @return Register setting for the given clock division factor. + */ +static inline uint32_t psram_ctrlr_ll_calculate_clock_reg(uint8_t clkdiv) +{ + uint32_t div_parameter; + // See comments of `clock` in `spi_mem_struct.h` + if (clkdiv == 1) { + div_parameter = (1 << 31); + } else { + div_parameter = ((clkdiv - 1) | (((clkdiv - 1) / 2 & 0xff) << 8 ) | (((clkdiv - 1) & 0xff) << 16)); + } + return div_parameter; +} + +/** + * Configure the psram read mode + * + * @param mspi_id mspi_id + * @param read_mode read mode + */ +static inline void psram_ctrlr_ll_set_read_mode(uint32_t mspi_id, psram_cmd_mode_t read_mode) +{ + typeof (SPIMEM0.mem_cache_sctrl) mem_cache_sctrl; + mem_cache_sctrl.val = SPIMEM0.mem_cache_sctrl.val; + + mem_cache_sctrl.val &= ~(SPI_MEM_USR_SRAM_DIO_M | SPI_MEM_USR_SRAM_QIO_M); + switch (read_mode) { + case PSRAM_HAL_CMD_SPI: + mem_cache_sctrl.mem_usr_sram_dio = 1; + break; + case PSRAM_HAL_CMD_QPI: + mem_cache_sctrl.mem_usr_sram_qio = 1; + break; + default: + abort(); + } + SPIMEM0.mem_cache_sctrl.val = mem_cache_sctrl.val; +} + +/** + * @brief Set CS setup + * + * @param mspi_id mspi_id + * @param setup_n cs setup time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_cs_setup(uint32_t mspi_id, uint32_t setup_n) +{ + (void)mspi_id; + HAL_ASSERT(setup_n > 0); + SPIMEM0.smem_ac.smem_cs_setup = 1; + SPIMEM0.smem_ac.smem_cs_setup_time = setup_n - 1; +} + +/** + * @brief Set CS hold + * + * @param mspi_id mspi_id + * @param hold_n cs hold time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_cs_hold(uint32_t mspi_id, uint32_t hold_n) +{ + (void)mspi_id; + HAL_ASSERT(hold_n > 0); + SPIMEM0.smem_ac.smem_cs_hold = 1; + SPIMEM0.smem_ac.smem_cs_hold_time = hold_n - 1; +} + +/** + * @brief Set CS hold delay + * + * @param mspi_id mspi_id + * @param hold_delay_n cs hold delay time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_cs_hold_delay(uint32_t mspi_id, uint32_t hold_delay_n) +{ + (void)mspi_id; + HAL_ASSERT(hold_delay_n > 0); + SPIMEM0.smem_ac.smem_cs_hold_delay = hold_delay_n - 1; +} + +/** + * @brief PSRAM common transaction + * + * See `spi_flash.h` for parameters + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_common_transaction_base(uint32_t mspi_id, esp_rom_spiflash_read_mode_t mode, + uint32_t cmd, uint32_t cmd_bitlen, + uint32_t addr, uint32_t addr_bitlen, + uint32_t dummy_bits, + uint8_t* mosi_data, uint32_t mosi_bitlen, + uint8_t* miso_data, uint32_t miso_bitlen, + uint32_t cs_mask, + bool is_write_erase_operation) +{ + esp_rom_spi_cmd_t conf = { + .cmd = cmd, + .cmdBitLen = cmd_bitlen, + .addr = &addr, + .addrBitLen = addr_bitlen, + .txData = (uint32_t *)mosi_data, + .txDataBitLen = mosi_bitlen, + .rxData = (uint32_t *)miso_data, + .rxDataBitLen = miso_bitlen, + .dummyBitLen = dummy_bits, + }; + esp_rom_spi_cmd_config(mspi_id, &conf); + esp_rom_spi_cmd_start(mspi_id, miso_data, miso_bitlen / 8, cs_mask, is_write_erase_operation); +} + +/** + * Select which pin to use for the psram + * + * @param mspi_id mspi_id + * @param cs_id cs_id for psram to use. + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_cs_pin(uint32_t mspi_id, psram_ll_cs_id_t cs_id) +{ + SPIMEM1.misc.cs0_dis = (cs_id == PSRAM_LL_CS_ID_0) ? 0 : 1; + SPIMEM1.misc.cs1_dis = (cs_id == PSRAM_LL_CS_ID_1) ? 0 : 1; +} + +/** + * Enable the psram quad command + * + * @param mspi_id mspi_id + * @param ena true if enable, otherwise false + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_quad_command(uint32_t mspi_id, bool ena) +{ + SPIMEM1.ctrl.fcmd_quad = ena; +} + +/*--------------------------------------------------------------- + ECC +---------------------------------------------------------------*/ +/** + * @brief Set ECC CS hold + * + * @param mspi_id mspi_id + * @param hold_n cs hold time + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_cs_hold(uint32_t mspi_id, uint32_t hold_n) +{ + HAL_ASSERT(hold_n > 0); + SPIMEM0.smem_ac.smem_ecc_cs_hold_time = hold_n - 1; +} + +/** + * @brief Set ECC mode + * + * @param mspi_id mspi_id + * @param mode ecc mode + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_ecc_mode(uint32_t mspi_id, psram_ll_ecc_mode_t mode) +{ + SPIMEM0.smem_ac.smem_ecc_16to18_byte_en = mode; +} + +/** + * @brief Set page size + * + * @param mspi_id mspi_id + * @param size page size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_page_size(uint32_t mspi_id, uint32_t size) +{ + uint32_t size_val = 0; + switch (size) { + case 256: + size_val = 0; + break; + case 512: + size_val = 1; + break; + case 1024: + size_val = 2; + break; + case 2048: + size_val = 3; + break; + default: + HAL_ASSERT(false); + break; + } + + SPIMEM0.smem_ecc_ctrl.smem_page_size = size_val; +} + +/** + * @brief Get page size + * + * @param mspi_id mspi_id + * + * @return page size + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_page_size(uint32_t mspi_id) +{ + (void)mspi_id; + uint32_t page_size = 0; + + uint32_t reg_val = SPIMEM0.smem_ecc_ctrl.smem_page_size; + switch(reg_val) { + case 0: + page_size = 256; + break; + case 1: + page_size = 512; + break; + case 2: + page_size = 1024; + break; + case 3: + page_size = 2048; + break; + default: + HAL_ASSERT(false); + } + + return page_size; +} + +/** + * @brief Skip page corner + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_skip_page_corner(uint32_t mspi_id, bool en) +{ + SPIMEM0.smem_ac.smem_ecc_skip_page_corner = en; +} + +/** + * @brief Enable splitting transactions + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_split_trans(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ac.smem_split_trans_en = en; +} + +/** + * @brief Enable ECC address conversion + * + * @param mspi_id mspi_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_ecc_addr_conversion(uint32_t mspi_id, bool en) +{ + (void)mspi_id; + SPIMEM0.smem_ecc_ctrl.smem_ecc_addr_en = en; +} + +/*--------------------------------------------------------------- + PMS +---------------------------------------------------------------*/ +/** + * @brief Enable PMS ECC + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param en enable / disable + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_enable_pms_region_ecc(uint32_t mspi_id, uint32_t region_id, bool en) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_ecc = en; +} + +/** + * @brief Set PMS attr + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param attr_mask attribute mask + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_attr(uint32_t mspi_id, uint32_t region_id, uint32_t attr_mask) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 0; + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 0; + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 1; + } + if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_READABLE) { + SPIMEM0.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 1; + } +} + +/** + * @brief Set PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param addr start addr + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id, uint32_t addr) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s = addr; +} + +/** + * @brief Set PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + * @param size size + */ +__attribute__((always_inline)) +static inline void psram_ctrlr_ll_set_pms_region_size(uint32_t mspi_id, uint32_t region_id, uint32_t size) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size = size; +} + +/** + * @brief Get PMS address + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_start_addr(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_addr[region_id].smem_pmsn_addr_s; +} + +/** + * @brief Get PMS size + * + * @param mspi_id mspi_id + * @param region_id region_id + */ +__attribute__((always_inline)) +static inline uint32_t psram_ctrlr_ll_get_pms_region_size(uint32_t mspi_id, uint32_t region_id) +{ + (void)mspi_id; + HAL_ASSERT(region_id < PSRAM_CTRLR_LL_PMS_REGION_NUMS); + return SPIMEM0.smem_pmsn_size[region_id].smem_pmsn_size; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32p4/include/hal/sdmmc_ll.h b/components/hal/esp32p4/include/hal/sdmmc_ll.h index 509793e3aa..0ef7ae5397 100644 --- a/components/hal/esp32p4/include/hal/sdmmc_ll.h +++ b/components/hal/esp32p4/include/hal/sdmmc_ll.h @@ -207,7 +207,7 @@ static inline void sdmmc_ll_enable_sdio_pll(sdmmc_dev_t *hw, bool en) * @brief Select SDMMC clock source * * @param hw hardware instance address - * @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t` + * @param clk_src clock source, see valid sources in type `soc_periph_sdmmc_clk_src_t` */ static inline void sdmmc_ll_select_clk_source(sdmmc_dev_t *hw, soc_periph_sdmmc_clk_src_t clk_src) { diff --git a/components/hal/esp32s3/include/hal/sdmmc_ll.h b/components/hal/esp32s3/include/hal/sdmmc_ll.h index 544000890c..02cdd22cf6 100644 --- a/components/hal/esp32s3/include/hal/sdmmc_ll.h +++ b/components/hal/esp32s3/include/hal/sdmmc_ll.h @@ -152,7 +152,7 @@ static inline void sdmmc_ll_reset_register(int group_id) * @brief Select SDMMC clock source * * @param hw hardware instance address - * @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t` + * @param clk_src clock source, see valid sources in type `soc_periph_sdmmc_clk_src_t` */ static inline void sdmmc_ll_select_clk_source(sdmmc_dev_t *hw, soc_periph_sdmmc_clk_src_t clk_src) { diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index d6002d5a56..dc300353cc 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -83,6 +83,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_SPIRAM_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_32M bool default y @@ -635,6 +639,14 @@ config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE bool default y +config SOC_SPIRAM_XIP_SUPPORTED + bool + default y + +config SOC_PSRAM_DMA_CAPABLE + bool + default y + config SOC_COEX_HW_PTI bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 526909536e..6a65e43b23 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -86,7 +86,7 @@ // #define SOC_ASSIST_DEBUG_SUPPORTED 1 // TODO: [ESP32H4] IDF-12310 #define SOC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 // TODO: [ESP32H4] IDF-12388 -// #define SOC_SPIRAM_SUPPORTED 1 // TODO: [ESP32H4] IDF-12351 +#define SOC_SPIRAM_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_32M 1 @@ -500,6 +500,10 @@ #define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1) +/*-------------------------- SPIRAM CAPS -------------------------------------*/ +#define SOC_SPIRAM_XIP_SUPPORTED 1 +#define SOC_PSRAM_DMA_CAPABLE 1 + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32h4/register/soc/spi_mem_c_reg.h b/components/soc/esp32h4/register/soc/spi_mem_c_reg.h index 233bd79206..8ffb108440 100644 --- a/components/soc/esp32h4/register/soc/spi_mem_c_reg.h +++ b/components/soc/esp32h4/register/soc/spi_mem_c_reg.h @@ -531,6 +531,107 @@ extern "C" { #define SPI_CLOSE_AXI_INF_EN_V 0x00000001U #define SPI_CLOSE_AXI_INF_EN_S 31 +/** SPI_MEM_CACHE_SCTRL_REG register + * SPI0 external RAM control register + * This register is only for internal debugging purposes. Do not use it in + * applications. + */ +#define SPI_MEM_CACHE_SCTRL_REG(i) (REG_SPI_MEM_BASE(i) + 0x40) +/** SPI_MEM_CACHE_USR_SADDR_4BYTE : HRO; bitpos: [0]; default: 0; + * For SPI0, In the external RAM mode, cache read flash with 4 bytes command, 1: + * enable, 0:disable. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_CACHE_USR_SADDR_4BYTE (BIT(0)) +#define SPI_MEM_CACHE_USR_SADDR_4BYTE_M (SPI_MEM_CACHE_USR_SADDR_4BYTE_V << SPI_MEM_CACHE_USR_SADDR_4BYTE_S) +#define SPI_MEM_CACHE_USR_SADDR_4BYTE_V 0x00000001U +#define SPI_MEM_CACHE_USR_SADDR_4BYTE_S 0 +/** SPI_MEM_USR_SRAM_DIO : HRO; bitpos: [1]; default: 0; + * For SPI0, In the external RAM mode, spi dual I/O mode enable, 1: enable, 0:disable + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_USR_SRAM_DIO (BIT(1)) +#define SPI_MEM_USR_SRAM_DIO_M (SPI_MEM_USR_SRAM_DIO_V << SPI_MEM_USR_SRAM_DIO_S) +#define SPI_MEM_USR_SRAM_DIO_V 0x00000001U +#define SPI_MEM_USR_SRAM_DIO_S 1 +/** SPI_MEM_USR_SRAM_QIO : HRO; bitpos: [2]; default: 0; + * For SPI0, In the external RAM mode, spi quad I/O mode enable, 1: enable, 0:disable + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_USR_SRAM_QIO (BIT(2)) +#define SPI_MEM_USR_SRAM_QIO_M (SPI_MEM_USR_SRAM_QIO_V << SPI_MEM_USR_SRAM_QIO_S) +#define SPI_MEM_USR_SRAM_QIO_V 0x00000001U +#define SPI_MEM_USR_SRAM_QIO_S 2 +/** SPI_MEM_USR_WR_SRAM_DUMMY : HRO; bitpos: [3]; default: 0; + * For SPI0, In the external RAM mode, it is the enable bit of dummy phase for write + * operations. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_USR_WR_SRAM_DUMMY (BIT(3)) +#define SPI_MEM_USR_WR_SRAM_DUMMY_M (SPI_MEM_USR_WR_SRAM_DUMMY_V << SPI_MEM_USR_WR_SRAM_DUMMY_S) +#define SPI_MEM_USR_WR_SRAM_DUMMY_V 0x00000001U +#define SPI_MEM_USR_WR_SRAM_DUMMY_S 3 +/** SPI_MEM_USR_RD_SRAM_DUMMY : HRO; bitpos: [4]; default: 1; + * For SPI0, In the external RAM mode, it is the enable bit of dummy phase for read + * operations. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_USR_RD_SRAM_DUMMY (BIT(4)) +#define SPI_MEM_USR_RD_SRAM_DUMMY_M (SPI_MEM_USR_RD_SRAM_DUMMY_V << SPI_MEM_USR_RD_SRAM_DUMMY_S) +#define SPI_MEM_USR_RD_SRAM_DUMMY_V 0x00000001U +#define SPI_MEM_USR_RD_SRAM_DUMMY_S 4 +/** SPI_MEM_CACHE_SRAM_USR_RCMD : HRO; bitpos: [5]; default: 1; + * For SPI0, In the external RAM mode cache read external RAM for user define command. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_CACHE_SRAM_USR_RCMD (BIT(5)) +#define SPI_MEM_CACHE_SRAM_USR_RCMD_M (SPI_MEM_CACHE_SRAM_USR_RCMD_V << SPI_MEM_CACHE_SRAM_USR_RCMD_S) +#define SPI_MEM_CACHE_SRAM_USR_RCMD_V 0x00000001U +#define SPI_MEM_CACHE_SRAM_USR_RCMD_S 5 +/** SPI_MEM_SRAM_RDUMMY_CYCLELEN : HRO; bitpos: [11:6]; default: 1; + * For SPI0, In the external RAM mode, it is the length in bits of read dummy phase. + * The register value shall be (bit_num-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_SRAM_RDUMMY_CYCLELEN 0x0000003FU +#define SPI_MEM_SRAM_RDUMMY_CYCLELEN_M (SPI_MEM_SRAM_RDUMMY_CYCLELEN_V << SPI_MEM_SRAM_RDUMMY_CYCLELEN_S) +#define SPI_MEM_SRAM_RDUMMY_CYCLELEN_V 0x0000003FU +#define SPI_MEM_SRAM_RDUMMY_CYCLELEN_S 6 +/** SPI_MEM_SRAM_ADDR_BITLEN : HRO; bitpos: [19:14]; default: 23; + * For SPI0, In the external RAM mode, it is the length in bits of address phase. The + * register value shall be (bit_num-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_SRAM_ADDR_BITLEN 0x0000003FU +#define SPI_MEM_SRAM_ADDR_BITLEN_M (SPI_MEM_SRAM_ADDR_BITLEN_V << SPI_MEM_SRAM_ADDR_BITLEN_S) +#define SPI_MEM_SRAM_ADDR_BITLEN_V 0x0000003FU +#define SPI_MEM_SRAM_ADDR_BITLEN_S 14 +/** SPI_MEM_CACHE_SRAM_USR_WCMD : HRO; bitpos: [20]; default: 1; + * For SPI0, In the external RAM mode cache write sram for user define command + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_CACHE_SRAM_USR_WCMD (BIT(20)) +#define SPI_MEM_CACHE_SRAM_USR_WCMD_M (SPI_MEM_CACHE_SRAM_USR_WCMD_V << SPI_MEM_CACHE_SRAM_USR_WCMD_S) +#define SPI_MEM_CACHE_SRAM_USR_WCMD_V 0x00000001U +#define SPI_MEM_CACHE_SRAM_USR_WCMD_S 20 +/** SPI_MEM_SRAM_OCT : HRO; bitpos: [21]; default: 0; + * reserved + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_SRAM_OCT (BIT(21)) +#define SPI_MEM_SRAM_OCT_M (SPI_MEM_SRAM_OCT_V << SPI_MEM_SRAM_OCT_S) +#define SPI_MEM_SRAM_OCT_V 0x00000001U +#define SPI_MEM_SRAM_OCT_S 21 +/** SPI_MEM_SRAM_WDUMMY_CYCLELEN : HRO; bitpos: [27:22]; default: 1; + * For SPI0, In the external RAM mode, it is the length in bits of write dummy phase. + * The register value shall be (bit_num-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_SRAM_WDUMMY_CYCLELEN 0x0000003FU +#define SPI_MEM_SRAM_WDUMMY_CYCLELEN_M (SPI_MEM_SRAM_WDUMMY_CYCLELEN_V << SPI_MEM_SRAM_WDUMMY_CYCLELEN_S) +#define SPI_MEM_SRAM_WDUMMY_CYCLELEN_V 0x0000003FU +#define SPI_MEM_SRAM_WDUMMY_CYCLELEN_S 22 + /** SPI_MEM_SRAM_CMD_REG register * SPI0 external RAM mode control register */ diff --git a/components/soc/esp32h4/register/soc/spi_mem_c_struct.h b/components/soc/esp32h4/register/soc/spi_mem_c_struct.h index cbfdb49acf..30c1d2bb56 100644 --- a/components/soc/esp32h4/register/soc/spi_mem_c_struct.h +++ b/components/soc/esp32h4/register/soc/spi_mem_c_struct.h @@ -323,6 +323,25 @@ typedef union { uint32_t val; } spi_mem_c_cache_fctrl_reg_t; +typedef union { + struct { + uint32_t usr_saddr_4byte : 1; /*For SPI0, In the external RAM mode, cache read flash with 4 bytes command, 1: enable, 0:disable.*/ + uint32_t mem_usr_sram_dio : 1; /*For SPI0, In the external RAM mode, spi dual I/O mode enable, 1: enable, 0:disable*/ + uint32_t mem_usr_sram_qio : 1; /*For SPI0, In the external RAM mode, spi quad I/O mode enable, 1: enable, 0:disable*/ + uint32_t usr_wr_sram_dummy : 1; /*For SPI0, In the external RAM mode, it is the enable bit of dummy phase for write operations.*/ + uint32_t mem_usr_rd_sram_dummy : 1; /*For SPI0, In the external RAM mode, it is the enable bit of dummy phase for read operations.*/ + uint32_t mem_cache_sram_usr_rcmd : 1; /*For SPI0, In the external RAM mode cache read external RAM for user define command.*/ + uint32_t mem_sram_rdummy_cyclelen : 6; /*For SPI0, In the external RAM mode, it is the length in bits of read dummy phase. The register value shall be (bit_num-1).*/ + uint32_t reserved12 : 2; /*reserved*/ + uint32_t mem_sram_addr_bitlen : 6; /*For SPI0, In the external RAM mode, it is the length in bits of address phase. The register value shall be (bit_num-1).*/ + uint32_t mem_cache_sram_usr_wcmd : 1; /*For SPI0, In the external RAM mode cache write sram for user define command*/ + uint32_t sram_oct : 1; /*reserved*/ + uint32_t sram_wdummy_cyclelen : 6; /*For SPI0, In the external RAM mode, it is the length in bits of write dummy phase. The register value shall be (bit_num-1).*/ + uint32_t reserved28 : 4; /*reserved*/ + }; + uint32_t val; +} spi_mem_c_cache_sctrl_reg_t; + /** Type of ddr register * SPI0 flash DDR mode control register */ @@ -437,6 +456,38 @@ typedef union { uint32_t val; } spi_mem_c_clock_reg_t; +/** Type of mem_sram_clk register + * SPI0 external RAM clock control register + */ +typedef union { + struct { + /** mem_sclkcnt_l : HRO; bitpos: [7:0]; default: 3; + * For SPI0 external RAM interface, it must be equal to spi_mem_c_clkcnt_N. + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_sclkcnt_l:8; + /** mem_sclkcnt_h : HRO; bitpos: [15:8]; default: 1; + * For SPI0 external RAM interface, it must be floor((spi_mem_c_clkcnt_N+1)/2-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_sclkcnt_h:8; + /** mem_sclkcnt_n : HRO; bitpos: [23:16]; default: 3; + * For SPI0 external RAM interface, it is the divider of spi_mem_c_clk. So spi_mem_c_clk + * frequency is system/(spi_mem_c_clkcnt_N+1) + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_sclkcnt_n:8; + uint32_t reserved_24:7; + /** mem_sclk_equ_sysclk : HRO; bitpos: [31]; default: 0; + * For SPI0 external RAM interface, 1: spi_mem_c_clk is equal to system 0: spi_mem_c_clk + * is divided from system clock. + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_sclk_equ_sysclk:1; + }; + uint32_t val; +} spi_mem_c_sram_clk_reg_t; + /** Type of clock_gate register * SPI0 clock gate register */ @@ -565,6 +616,135 @@ typedef union { uint32_t val; } spi_mem_c_sram_cmd_reg_t; +/** Type of mem_sram_drd_cmd register + * SPI0 external RAM DDR read command control register + */ +typedef union { + struct { + /** mem_cache_sram_usr_rd_cmd_value : HRO; bitpos: [15:0]; default: 0; + * For SPI0,When cache mode is enable it is the read command value of command phase + * for sram. + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_cache_sram_usr_rd_cmd_value:16; + uint32_t reserved_16:12; + /** mem_cache_sram_usr_rd_cmd_bitlen : HRO; bitpos: [31:28]; default: 0; + * For SPI0,When cache mode is enable it is the length in bits of command phase for + * sram. The register value shall be (bit_num-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_cache_sram_usr_rd_cmd_bitlen:4; + }; + uint32_t val; +} spi_mem_c_sram_drd_cmd_reg_t; + +/** Type of mem_sram_dwr_cmd register + * SPI0 external RAM DDR write command control register + */ +typedef union { + struct { + /** mem_cache_sram_usr_wr_cmd_value : HRO; bitpos: [15:0]; default: 0; + * For SPI0,When cache mode is enable it is the write command value of command phase + * for sram. + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_cache_sram_usr_wr_cmd_value:16; + uint32_t reserved_16:12; + /** mem_cache_sram_usr_wr_cmd_bitlen : HRO; bitpos: [31:28]; default: 0; + * For SPI0,When cache mode is enable it is the in bits of command phase for sram. + * The register value shall be (bit_num-1). + * This field is only for internal debugging purposes. Do not use it in applications. + */ + uint32_t mem_cache_sram_usr_wr_cmd_bitlen:4; + }; + uint32_t val; +} spi_mem_c_sram_dwr_cmd_reg_t; + +/** Type of smem_ddr register + * SPI0 external RAM DDR mode control register + */ +typedef union { + struct { + /** smem_ddr_en : HRO; bitpos: [0]; default: 0; + * 1: in DDR mode, 0 in SDR mode + */ + uint32_t smem_ddr_en:1; + /** smem_var_dummy : HRO; bitpos: [1]; default: 0; + * Set the bit to enable variable dummy cycle in spi DDR mode. + */ + uint32_t smem_var_dummy:1; + /** smem_ddr_rdat_swp : HRO; bitpos: [2]; default: 0; + * Set the bit to reorder rx data of the word in spi DDR mode. + */ + uint32_t smem_ddr_rdat_swp:1; + /** smem_ddr_wdat_swp : HRO; bitpos: [3]; default: 0; + * Set the bit to reorder tx data of the word in spi DDR mode. + */ + uint32_t smem_ddr_wdat_swp:1; + /** smem_ddr_cmd_dis : HRO; bitpos: [4]; default: 0; + * the bit is used to disable dual edge in command phase when DDR mode. + */ + uint32_t smem_ddr_cmd_dis:1; + /** smem_outminbytelen : HRO; bitpos: [11:5]; default: 1; + * It is the minimum output data length in the DDR psram. + */ + uint32_t smem_outminbytelen:7; + /** smem_tx_ddr_msk_en : HRO; bitpos: [12]; default: 1; + * Set this bit to mask the first or the last byte in SPI0 ECC DDR write mode, when + * accesses to external RAM. + */ + uint32_t smem_tx_ddr_msk_en:1; + /** smem_rx_ddr_msk_en : HRO; bitpos: [13]; default: 1; + * Set this bit to mask the first or the last byte in SPI0 ECC DDR read mode, when + * accesses to external RAM. + */ + uint32_t smem_rx_ddr_msk_en:1; + /** smem_usr_ddr_dqs_thd : HRO; bitpos: [20:14]; default: 0; + * The delay number of data strobe which from memory based on SPI clock. + */ + uint32_t smem_usr_ddr_dqs_thd:7; + /** smem_ddr_dqs_loop : HRO; bitpos: [21]; default: 0; + * 1: Do not need the input of SPI_DQS signal, SPI0 starts to receive data when + * spi0_slv_st is in spi_mem_c_DIN state. It is used when there is no SPI_DQS signal or + * SPI_DQS signal is not stable. 0: SPI0 starts to store data at the positive and + * negative edge of SPI_DQS. + */ + uint32_t smem_ddr_dqs_loop:1; + uint32_t reserved_22:2; + /** smem_clk_diff_en : HRO; bitpos: [24]; default: 0; + * Set this bit to enable the differential SPI_CLK#. + */ + uint32_t smem_clk_diff_en:1; + uint32_t reserved_25:1; + /** smem_dqs_ca_in : HRO; bitpos: [26]; default: 0; + * Set this bit to enable the input of SPI_DQS signal in SPI phases of CMD and ADDR. + */ + uint32_t smem_dqs_ca_in:1; + /** smem_hyperbus_dummy_2x : HRO; bitpos: [27]; default: 0; + * Set this bit to enable the vary dummy function in SPI HyperBus mode, when SPI0 + * accesses flash or SPI1 accesses flash or sram. + */ + uint32_t smem_hyperbus_dummy_2x:1; + /** smem_clk_diff_inv : HRO; bitpos: [28]; default: 0; + * Set this bit to invert SPI_DIFF when accesses to external RAM. . + */ + uint32_t smem_clk_diff_inv:1; + /** smem_octa_ram_addr : HRO; bitpos: [29]; default: 0; + * Set this bit to enable octa_ram address out when accesses to external RAM, which + * means ADDR_OUT[31:0] = {spi_usr_addr_value[25:4], 6'd0, spi_usr_addr_value[3:1], + * 1'b0}. + */ + uint32_t smem_octa_ram_addr:1; + /** smem_hyperbus_ca : HRO; bitpos: [30]; default: 0; + * Set this bit to enable HyperRAM address out when accesses to external RAM, which + * means ADDR_OUT[31:0] = {spi_usr_addr_value[19:4], 13'd0, spi_usr_addr_value[3:1]}. + */ + uint32_t smem_hyperbus_ca:1; + uint32_t reserved_31:1; + }; + uint32_t val; +} spi_smem_c_ddr_reg_t; + /** Type of smem_ddr register * SPI0 external RAM DDR mode control register */ @@ -2523,9 +2703,11 @@ typedef struct { volatile spi_mem_c_misc_reg_t misc; uint32_t reserved_038; volatile spi_mem_c_cache_fctrl_reg_t cache_fctrl; - uint32_t reserved_040; + volatile spi_mem_c_cache_sctrl_reg_t mem_cache_sctrl; volatile spi_mem_c_sram_cmd_reg_t sram_cmd; - uint32_t reserved_048[3]; + volatile spi_mem_c_sram_drd_cmd_reg_t mem_sram_drd_cmd; + volatile spi_mem_c_sram_dwr_cmd_reg_t mem_sram_dwr_cmd; + volatile spi_mem_c_sram_clk_reg_t mem_sram_clk; volatile spi_mem_c_fsm_reg_t fsm; uint32_t reserved_058[26]; volatile spi_mem_c_int_ena_reg_t int_ena; diff --git a/examples/system/xip_from_psram/README.md b/examples/system/xip_from_psram/README.md index a4612395dc..229381de18 100644 --- a/examples/system/xip_from_psram/README.md +++ b/examples/system/xip_from_psram/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | -------- | --------- | -------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | --------- | -------- | -------- | -------- | -------- | # XIP (Execute-In-Place) From PSRAM Example