Merge branch 'feat/h4_psram' into 'master'

psram: h4 support

Closes IDF-12351 and IDF-12350

See merge request espressif/esp-idf!40484
This commit is contained in:
Armando (Dou Yiwen)
2025-07-28 09:39:41 +00:00
21 changed files with 1075 additions and 62 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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"
}

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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 <stdint.h>
#include <stdbool.h>
#include <sys/param.h>
#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

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -87,6 +87,10 @@ config SOC_SPI_FLASH_SUPPORTED
bool
default y
config SOC_SPIRAM_SUPPORTED
bool
default y
config SOC_XTAL_SUPPORT_32M
bool
default y
@@ -699,6 +703,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

View File

@@ -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
@@ -501,6 +501,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)

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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