Merge branch 'feat/psram_s31' into 'master'

psram: s31 support

Closes IDF-14718, IDF-14716, and IDF-14717

See merge request espressif/esp-idf!47044
This commit is contained in:
Armando (Dou Yiwen)
2026-04-01 00:30:01 +00:00
50 changed files with 2987 additions and 932 deletions
@@ -23,7 +23,6 @@
#include "soc/rtc_wdt_reg.h"
#include "hal/rwdt_ll.h"
#endif
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/pmu_reg.h"
#include "hal/regi2c_ctrl_ll.h"
#include "hal/modem_lpcon_ll.h"
@@ -32,13 +31,6 @@ ESP_LOG_ATTR_TAG(TAG, "boot.esp32s31");
static inline void bootloader_hardware_init(void)
{
// IDF-15507: Work around ESP32-S31 cache/MSPI issues by keeping the cache path clocks ungated.
REG_SET_BIT(HP_SYS_CLKRST_CACHE_CTRL0_REG,
HP_SYS_CLKRST_REG_CPU_ACACHE_CPU_CLK_FORCE_ON |
HP_SYS_CLKRST_REG_ROM_ACACHE_MEM_CLK_FORCE_ON |
HP_SYS_CLKRST_REG_CPU_CACHE_CPU_CLK_FORCE_ON |
HP_SYS_CLKRST_REG_MSPI_CACHE_SYS_CLK_FORCE_ON);
/* Disable RF pll by default */
REG_SET_FIELD(PMU_RF_PWC_REG, PMU_XPD_RF_CIRCUIT, 0xFFFF);
@@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <strings.h>
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"
#include "sdkconfig.h"
ESP_LOG_ATTR_TAG(TAG, "secure_boot");
esp_err_t esp_secure_boot_enable_secure_features(void)
{
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
ESP_LOGI(TAG, "Enabling Security download mode...");
esp_err_t err = esp_efuse_enable_rom_secure_download_mode();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not enable Security download mode...");
return err;
}
#elif CONFIG_SECURE_DISABLE_ROM_DL_MODE
ESP_LOGI(TAG, "Disable ROM Download mode...");
esp_err_t err = esp_efuse_disable_rom_download_mode();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Could not disable ROM Download mode...");
return err;
}
#else
ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable hardware & software JTAG...");
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count);
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
#endif
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool rd_dis_now = true;
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
/* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
when Flash Encryption is being enabled */
rd_dis_now = esp_efuse_is_flash_encryption_enabled();
#endif
if (rd_dis_now) {
ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS);
}
#else
ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
#endif
return ESP_OK;
}
@@ -433,7 +433,8 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
// are mutually exclusive because this will make the chip not functional.
// Only one type key must be configured in eFuses.
secure = false;
for (unsigned i = 0; i < sizeof(purposes) / sizeof(esp_efuse_purpose_t); i++) {
size_t purpose_count = sizeof(purposes) / sizeof(esp_efuse_purpose_t);
for (size_t i = 0; i < purpose_count; i++) {
esp_efuse_block_t block;
if (esp_efuse_find_purpose(purposes[i], &block)) {
secure = esp_efuse_get_key_dis_read(block);
@@ -139,7 +139,8 @@ static inline __attribute__((always_inline)) void clk_ll_lp_pll_disable(void)
*/
static inline __attribute__((always_inline)) void clk_ll_mpll_enable(void)
{
// TODO: [ESP32S31] IDF-14733
REG_SET_BIT(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD);
REG_SET_BIT(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_MPLL_500M_CLK_EN);
}
/**
@@ -147,7 +148,7 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_enable(void)
*/
static inline __attribute__((always_inline)) void clk_ll_mpll_disable(void)
{
// TODO: [ESP32S31] IDF-14733
REG_CLR_BIT(PMU_PSRAM_CFG_REG, PMU_PSRAM_XPD);
}
/**
@@ -289,6 +290,18 @@ static inline __attribute__((always_inline)) bool clk_ll_xtal32k_digi_is_enabled
// TODO: [ESP32S31] IDF-14733
}
/**
* @brief Get XTAL_CLK frequency
*
* @return Main XTAL clock frequency, in MHz.
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_get_freq_mhz(void)
{
return 40;
}
#define clk_ll_xtal_load_freq_mhz() clk_ll_xtal_get_freq_mhz()
/**
* @brief Enable the digital RC32K_CLK, which is used to support peripherals.
*/
@@ -386,9 +399,8 @@ static inline __attribute__((always_inline)) bool clk_ll_cpll_calibration_is_don
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_mpll_get_freq_mhz(uint32_t xtal_freq_mhz)
{
// uint8_t div = REGI2C_READ_MASK(I2C_MPLL, I2C_MPLL_DIV_ADDR);
// uint8_t ref_div = REGI2C_READ_MASK(I2C_MPLL, I2C_MPLL_REF_DIV_ADDR);
return 0;//xtal_freq_mhz * (div + 1) / (ref_div + 1);
uint8_t fb_div = REG_GET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV);
return xtal_freq_mhz * (fb_div + 1) / 2;
}
/**
@@ -399,7 +411,11 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_mpll_get_freq_mhz(u
*/
static inline __attribute__((always_inline)) void clk_ll_mpll_set_config(uint32_t mpll_freq_mhz, uint32_t xtal_freq_mhz)
{
// TODO: [ESP32S31] IDF-14733
HAL_ASSERT(xtal_freq_mhz == SOC_XTAL_FREQ_40M);
uint8_t ref_div = 1;
uint8_t fb_div = mpll_freq_mhz * (ref_div + 1) / xtal_freq_mhz - 1;
REG_SET_FIELD(LP_AONCLKRST_MSPI_DIV_REG, LP_AONCLKRST_MSPI_FB_DIV, fb_div);
}
/**
@@ -859,35 +875,6 @@ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uin
// }
/************************** LP STORAGE REGISTER STORE/LOAD **************************/
/**
* @brief Store XTAL_CLK frequency in RTC storage register
*
* Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit
* halves. These are the routines to work with that representation.
*
* @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even,
* otherwise there will be a conflict with the low bit, which is used to disable logs
* in the ROM code.
*/
static inline __attribute__((always_inline)) void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz)
{
// TODO: [ESP32S31] IDF-14733
}
/**
* @brief Load XTAL_CLK frequency from RTC storage register
*
* Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit
* halves. These are the routines to work with that representation.
*
* @return XTAL frequency, in MHz. Returns 0 if value in reg is invalid.
*/
static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz(void)
{
// TODO: [ESP32S31] IDF-14733
return 0;
}
/**
* @brief Store RTC_SLOW_CLK calibration value in RTC storage register
*
@@ -84,6 +84,7 @@ extern "C" {
#define MSPI_LL_AXI_DISABLE_SUPPORTED 1
#define MSPI_LL_INTR_EVENT_SUPPORTED 1
#define MSPI_LL_PSRAM_DQS1_SUPPORTED 1
/**
* MSPI DQS ID
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -29,12 +29,16 @@
#include "esp_bit_defs.h"
#include "hal/assert.h"
#include "soc/soc.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/spi_mem_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/iomux_mspi_pin_reg.h"
#include "soc/iomux_mspi_pin_struct.h"
#include "soc/spi_mem_struct.h"
#include "soc/spi_mem_s_struct.h"
#include "soc/spi_mem_c_reg.h"
#include "soc/spi1_mem_c_reg.h"
#include "soc/clk_tree_defs.h"
#ifdef __cplusplus
extern "C" {
@@ -50,8 +54,171 @@ extern "C" {
#define MSPI_LL_AXI_DISABLE_SUPPORTED 1
#define MSPI_LL_INTR_EVENT_SUPPORTED 1
// TODO: ["ESP32S31"] IDF-14653
/**
* MSPI DQS ID
*/
typedef enum {
MSPI_LL_DQS_ID_0,
} mspi_ll_dqs_id_t;
/**
* MSPI DQS Phase
*/
typedef enum {
MSPI_LL_DQS_PHASE_67_5,
MSPI_LL_DQS_PHASE_78_75,
MSPI_LL_DQS_PHASE_90,
MSPI_LL_DQS_PHASE_101_25,
MSPI_LL_DQS_PHASE_MAX,
} mspi_ll_dqs_phase_t;
/**
* MSPI Delayline
*
* @note The Sequence of these enums should not be changed
*/
typedef enum {
MSPI_LL_PIN_D = 0,
MSPI_LL_PIN_Q,
MSPI_LL_PIN_WP,
MSPI_LL_PIN_HD,
MSPI_LL_PIN_D4,
MSPI_LL_PIN_D5,
MSPI_LL_PIN_D6,
MSPI_LL_PIN_D7,
MSPI_LL_PIN_DQS0,
MSPI_LL_PIN_CLK,
MSPI_LL_PIN_CS,
MSPI_LL_PIN_MAX,
} mspi_ll_pin_t;
/*---------------------------------------------------------------
PSRAM tuning
---------------------------------------------------------------*/
/**
* Set all MSPI DQS phase
*
* @param dqs_id DQS ID
* @param phase Phase
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_dqs_phase(mspi_ll_dqs_id_t dqs_id, mspi_ll_dqs_phase_t phase)
{
HAL_ASSERT(dqs_id < 1);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_PHASE, phase);
}
/**
* Set all MSPI delayline
*
* @param pin Pin
* @param delayline Delayline
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_delayline(mspi_ll_pin_t pin, uint8_t delayline)
{
HAL_ASSERT(pin < MSPI_LL_PIN_MAX);
switch (pin) {
case MSPI_LL_PIN_DQS0:
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_delay_90 = delayline;
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_delay_270 = delayline;
break;
case MSPI_LL_PIN_D:
case MSPI_LL_PIN_Q:
case MSPI_LL_PIN_WP:
case MSPI_LL_PIN_HD:
case MSPI_LL_PIN_D4:
case MSPI_LL_PIN_D5:
case MSPI_LL_PIN_D6:
case MSPI_LL_PIN_D7:
MSPI_IOMUX.psram_pin_group.pin_group0[pin].reg_psram_pin_dlc = delayline;
break;
case MSPI_LL_PIN_CLK:
MSPI_IOMUX.psram_pin_group.pin_clk.reg_psram_pin_dlc = delayline;
break;
case MSPI_LL_PIN_CS:
MSPI_IOMUX.psram_pin_group.pin_cs.reg_psram_pin_dlc = delayline;
break;
default:
HAL_ASSERT(false);
break;
}
}
/**
* Enable DQS
*
* @param en Enable/disable
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_enable_dqs(bool en)
{
if (en) {
REG_SET_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_XPD);
} else {
REG_CLR_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_XPD);
}
}
/**
* Set all MSPI pin drive
*
* @param drv Pin drive
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_pin_drv_set(uint8_t drv)
{
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_D_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_Q_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_Q_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_WP_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_WP_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_HOLD_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_HOLD_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ4_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ4_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ5_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ5_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ6_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ6_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ7_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ7_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CK_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CK_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CS_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CS_DRV, drv);
}
/*---------------------------------------------------------------
Flash tuning
---------------------------------------------------------------*/
/*
* @brief Select FLASH clock source
*
* @param mspi_id mspi_id
* @param clk_src clock source, see valid sources in type `soc_periph_flash_clk_src_t`
*/
__attribute__((always_inline))
static inline void _mspi_timing_ll_set_flash_clk_src(uint32_t mspi_id, soc_periph_flash_clk_src_t clk_src)
{
HAL_ASSERT(mspi_id == MSPI_TIMING_LL_MSPI_ID_0);
uint32_t clk_val = 0;
switch (clk_src) {
case FLASH_CLK_SRC_XTAL:
clk_val = 0;
break;
case FLASH_CLK_SRC_SPLL:
clk_val = 1;
break;
case FLASH_CLK_SRC_CPLL:
clk_val = 2;
break;
default:
HAL_ASSERT(false);
break;
}
HP_SYS_CLKRST.flash_ctrl0.reg_flash_sys_clk_en = 1;
HP_SYS_CLKRST.flash_ctrl0.reg_flash_pll_clk_en = 1;
HP_SYS_CLKRST.flash_ctrl0.reg_flash_clk_src_sel = clk_val;
}
/*---------------------------------------------------------------
Misc
---------------------------------------------------------------*/
/**
* @brief Enable/Disable MSPI controller interrupt
*
@@ -0,0 +1,946 @@
/*
* SPDX-FileCopyrightText: 2026 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 "hal/config.h"
#include "soc/spi_mem_s_struct.h"
#include "soc/spi_mem_s_reg.h"
#include "soc/spi1_mem_s_reg.h"
#include "soc/spi1_mem_s_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/clk_tree_defs.h"
#include "soc/hp_system_struct.h"
#include "rom/opi_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PSRAM_CTRLR_LL_MSPI_ID_2 2
#define PSRAM_CTRLR_LL_MSPI_ID_3 3
#define PSRAM_CTRLR_LL_MSPI_ID_SYSTEM PSRAM_CTRLR_LL_MSPI_ID_2
#define PSRAM_CTRLR_LL_MSPI_ID_PERI PSRAM_CTRLR_LL_MSPI_ID_3
#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)
#define PSRAM_CTRLR_LL_FIFO_MAX_BYTES 64
#define PSRAM_CTRLR_LL_THRESH_INT_SUPPORTED 1
#define PSRAM_CTRLR_LL_PMS_INT_SUPPORTED 1
#define PSRAM_CTRLR_LL_ADDR_INT_SUPPORTED 1
#define PSRAM_CTRLR_LL_EVENT_SLV_ST_END (1<<3)
#define PSRAM_CTRLR_LL_EVENT_MST_ST_END (1<<4)
#define PSRAM_CTRLR_LL_EVENT_ECC_ERR (1<<5)
#define PSRAM_CTRLR_LL_EVENT_PMS_REJECT (1<<6)
#define PSRAM_CTRLR_LL_EVENT_AXI_RADDR_ERR (1<<7)
#define PSRAM_CTRLR_LL_EVENT_AXI_WR_FLASH_ERR (1<<8)
#define PSRAM_CTRLR_LL_EVENT_AXI_WADDR_ERR (1<<9)
#define PSRAM_CTRLR_LL_EVENT_RX_TRANS_OVF (1<<26)
#define PSRAM_CTRLR_LL_EVENT_TX_TRANS_UDF (1<<27)
#define PSRAM_CTRLR_LL_EVENT_MASK (PSRAM_CTRLR_LL_EVENT_ECC_ERR | PSRAM_CTRLR_LL_EVENT_PMS_REJECT | PSRAM_CTRLR_LL_EVENT_AXI_RADDR_ERR | \
PSRAM_CTRLR_LL_EVENT_AXI_WR_FLASH_ERR | PSRAM_CTRLR_LL_EVENT_AXI_WADDR_ERR | PSRAM_CTRLR_LL_EVENT_RX_TRANS_OVF | \
PSRAM_CTRLR_LL_EVENT_TX_TRANS_UDF)
#define PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED 1
/**
* @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);
SPIMEM2.mem_cache_sctrl.mem_cache_sram_usr_wcmd = 1;
SPIMEM2.mem_sram_dwr_cmd.mem_cache_sram_usr_wr_cmd_bitlen = cmd_bitlen - 1;
HAL_FORCE_MODIFY_U32_REG_FIELD(SPIMEM2.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);
SPIMEM2.mem_cache_sctrl.mem_cache_sram_usr_rcmd = 1;
SPIMEM2.mem_sram_drd_cmd.mem_cache_sram_usr_rd_cmd_bitlen = cmd_bitlen - 1;
HAL_FORCE_MODIFY_U32_REG_FIELD(SPIMEM2.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);
SPIMEM2.mem_cache_sctrl.mem_sram_addr_bitlen = addr_bitlen - 1;
}
/**
* @brief Enable PSRAM 4B addr
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_4byte_addr(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_cache_sctrl.mem_cache_usr_saddr_4byte = en;
}
/**
* @brief Set PSRAM write dummy
*
* @param mspi_id mspi_id
* @param dummy_n dummy number
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_wr_dummy(uint32_t mspi_id, uint32_t dummy_n)
{
(void)mspi_id;
HAL_ASSERT(dummy_n > 0);
SPIMEM2.mem_cache_sctrl.mem_usr_wr_sram_dummy = 1;
SPIMEM2.mem_cache_sctrl.mem_sram_wdummy_cyclelen = dummy_n - 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);
SPIMEM2.mem_cache_sctrl.mem_usr_rd_sram_dummy = 1;
SPIMEM2.mem_cache_sctrl.mem_sram_rdummy_cyclelen = dummy_n - 1;
}
/**
* @brief Enable PSRAM variable dummy
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_variable_dummy(uint32_t mspi_id, bool en)
{
if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_2) {
SPIMEM2.smem_ddr.smem_var_dummy = en;
} else if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_3) {
SPIMEM3.ddr.fmem_var_dummy = en;
}
}
/**
* @brief Enable PSRAM write dummy level control
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_wr_dummy_level_control(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_sram_cmd.mem_sdummy_wout = en;
}
/**
* @brief Enable PSRAM read dummy level control
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_rd_dummy_level_control(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_sram_cmd.mem_sdummy_rin = en;
}
/**
* @brief Enable PSRAM ddr mode
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_ddr_mode(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.smem_ddr.smem_ddr_en = en;
}
/**
* @brief Enable PSRAM ddr write data swap
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_ddr_wr_data_swap(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.smem_ddr.smem_ddr_wdat_swp = en;
}
/**
* @brief Enable PSRAM ddr read data swap
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_ddr_rd_data_swap(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.smem_ddr.smem_ddr_rdat_swp = en;
}
/**
* @brief Enable PSRAM octal mode
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_oct_line_mode(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_cache_sctrl.mem_sram_oct = en;
SPIMEM2.mem_sram_cmd.mem_scmd_oct = en;
SPIMEM2.mem_sram_cmd.mem_saddr_oct = en;
SPIMEM2.mem_sram_cmd.mem_sdout_oct = en;
SPIMEM2.mem_sram_cmd.mem_sdin_oct = en;
}
/**
* @brief Enable PSRAM hex data line mode
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_hex_data_line_mode(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_sram_cmd.mem_sdin_hex = en;
SPIMEM2.mem_sram_cmd.mem_sdout_hex = en;
}
/**
* @brief Get PSRAM hex data line mode enable status
*
* @param mspi_id mspi_id
*
* @return true if hex data line mode is enabled, false otherwise
*/
__attribute__((always_inline))
static inline bool psram_ctrlr_ll_is_hex_data_line_mode(uint32_t mspi_id)
{
(void)mspi_id;
return (SPIMEM2.mem_sram_cmd.mem_sdin_hex & SPIMEM2.mem_sram_cmd.mem_sdout_hex);
}
/**
* @brief Enable PSRAM AXI master access
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_axi_access(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_cache_fctrl.mem_axi_req_en = en;
SPIMEM2.mem_cache_fctrl.close_axi_inf_en = !en;
}
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
/**
* @brief Enable PSRAM AXI weight arbiter for TX / RX AXI requests
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_axi_req_weight_arbiter(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_cache_fctrl.mem_arb_wei_en = en;
}
/**
* @brief Set PSRAM AXI request weight
*
* @param mspi_id mspi_id
* @param rd_weight read weight
* @param wr_weight write weight
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_axi_req_weight(uint32_t mspi_id, uint32_t rd_weight, uint32_t wr_weight)
{
//1~15
HAL_ASSERT(rd_weight && rd_weight < 16);
HAL_ASSERT(wr_weight && wr_weight < 16);
SPIMEM2.mem_cache_fctrl.mem_arb_req0_wei = rd_weight;
SPIMEM2.mem_cache_fctrl.mem_arb_req1_wei = wr_weight;
}
/**
* @brief Set PSRAM AXI request priority
*
* @param mspi_id mspi_id
* @param rd_prio read priority
* @param wr_prio write priority
*/
static inline void psram_ctrlr_ll_set_axi_req_priority(uint32_t mspi_id, uint32_t rd_prio, uint32_t wr_prio)
{
SPIMEM2.mem_cache_fctrl.mem_arb_req0_pri = rd_prio;
SPIMEM2.mem_cache_fctrl.mem_arb_req1_pri = wr_prio;
}
#endif
/**
* @brief Enable PSRAM write splice transfer
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_wr_splice(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_ctrl1.mem_aw_splice_en = en;
}
/**
* @brief Enable PSRAM read splice transfer
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_rd_splice(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.mem_ctrl1.mem_ar_splice_en = en;
}
/**
* @brief Enable PSRAM module clock
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void _psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en)
{
(void)mspi_id;
HP_SYS_CLKRST.psram_ctrl0.reg_psram_sys_clk_en = en;
HP_SYS_CLKRST.psram_ctrl0.reg_psram_pll_clk_en = en;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_enable_module_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_psram_ctrlr_ll_enable_module_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset PSRAM module clock
*
* @param mspi_id mspi_id
*/
__attribute__((always_inline))
static inline void _psram_ctrlr_ll_reset_module_clock(uint32_t mspi_id)
{
HP_SYS_CLKRST.psram_ctrl0.reg_psram_axi_rst_en = 1;
HP_SYS_CLKRST.psram_ctrl0.reg_psram_apb_rst_en = 1;
HP_SYS_CLKRST.psram_ctrl0.reg_psram_apb_rst_en = 0;
HP_SYS_CLKRST.psram_ctrl0.reg_psram_axi_rst_en = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_reset_module_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_psram_ctrlr_ll_reset_module_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Select PSRAM clock source
*
* @param mspi_id mspi_id
* @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t`
*/
__attribute__((always_inline))
static inline void _psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph_psram_clk_src_t clk_src)
{
(void)mspi_id;
uint32_t clk_val = 0;
switch (clk_src) {
case PSRAM_CLK_SRC_XTAL:
clk_val = 0;
break;
case PSRAM_CLK_SRC_MPLL:
clk_val = 1;
break;
case PSRAM_CLK_SRC_CPLL:
clk_val = 2;
break;
default:
HAL_ASSERT(false);
break;
}
HP_SYS_CLKRST.psram_ctrl0.reg_psram_clk_src_sel = clk_val;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_select_clk_source(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_psram_ctrlr_ll_select_clk_source(__VA_ARGS__); \
} while(0)
/**
* @brief Set PSRAM core clock
*
* @param mspi_id mspi_id
* @param freqdiv Divider value
*/
__attribute__((always_inline))
static inline void _psram_ctrlr_ll_set_core_clock_div(uint8_t spi_num, uint32_t freqdiv)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.psram_ctrl0, reg_psram_core_clk_div_num, freqdiv - 1);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_set_core_clock_div(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_psram_ctrlr_ll_set_core_clock_div(__VA_ARGS__); \
} while(0)
/**
* @brief Enable or disable the PSRAM core clock
*
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void _psram_ctrlr_ll_enable_core_clock(uint8_t spi_num, bool en)
{
HP_SYS_CLKRST.psram_ctrl0.reg_psram_core_clk_en = en;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define psram_ctrlr_ll_enable_core_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
_psram_ctrlr_ll_enable_core_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Set PSRAM bus clock
*
* @param mspi_id mspi_id
* @param freqdiv Divider value
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_bus_clock(uint32_t mspi_id, uint32_t freqdiv)
{
if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_2) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, SPI_MEM_S_SCLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_S_SCLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_S_SCLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_S_SCLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, freqbits);
}
} else if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_3) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI1_MEM_S_CLOCK_REG, SPI1_MEM_S_CLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI1_MEM_S_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI1_MEM_S_CLKCNT_H_S)) | ((freqdiv - 1) << SPI1_MEM_S_CLKCNT_L_S);
WRITE_PERI_REG(SPI1_MEM_S_CLOCK_REG, freqbits);
}
}
}
/**
* @brief Enable PSRAM DLL
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_dll(uint32_t mspi_id, bool en)
{
if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_2) {
SPIMEM2.smem_timing_cali.smem_dll_timing_cali = en;
} else if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_3) {
SPIMEM2.mem_timing_cali.mem_dll_timing_cali = en;
} else {
HAL_ASSERT(false);
}
}
/**
* @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);
SPIMEM2.smem_ac.smem_cs_setup = 1;
SPIMEM2.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);
SPIMEM2.smem_ac.smem_cs_hold = 1;
SPIMEM2.smem_ac.smem_cs_hold_time = hold_n - 1;
}
/**
* @brief Set CS hold delay
*
* @param mspi_id mspi_id
* @param hold_n cs hold 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);
SPIMEM2.smem_ac.smem_cs_hold_delay = hold_delay_n - 1;
}
/**
* @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_cs_hold_ecc(uint32_t mspi_id, uint32_t hold_n)
{
(void)mspi_id;
HAL_ASSERT(hold_n > 0);
SPIMEM2.smem_ac.smem_ecc_cs_hold_time = hold_n - 1;
}
/**
* @brief Enable 16to18 ECC
*
* @param mspi_id mspi_id
* @param en enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_16to18_ecc(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.smem_ac.smem_ecc_16to18_byte_en = en;
}
/**
* @brief Enable ECC 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)
{
(void)mspi_id;
SPIMEM2.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;
SPIMEM2.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;
SPIMEM2.smem_ecc_ctrl.smem_ecc_addr_en = en;
}
/**
* @brief Set page size
*
* @param mspi_id mspi_id
* @param page_size page size
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_page_size(uint32_t mspi_id, uint32_t page_size)
{
(void)mspi_id;
switch (page_size) {
case 256:
SPIMEM2.smem_ecc_ctrl.smem_page_size = 0;
break;
case 512:
SPIMEM2.smem_ecc_ctrl.smem_page_size = 1;
break;
case 1024:
SPIMEM2.smem_ecc_ctrl.smem_page_size = 2;
break;
case 2048:
SPIMEM2.smem_ecc_ctrl.smem_page_size = 3;
break;
default:
HAL_ASSERT(false);
}
}
/**
* @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 = SPIMEM2.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 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);
SPIMEM2.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);
SPIMEM2.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 0;
SPIMEM2.smem_pmsn_attr[region_id].smem_pmsn_rd_attr = 0;
if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE) {
SPIMEM2.smem_pmsn_attr[region_id].smem_pmsn_wr_attr = 1;
}
if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_READABLE) {
SPIMEM2.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);
SPIMEM2.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);
SPIMEM2.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 SPIMEM2.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 SPIMEM2.smem_pmsn_size[region_id].smem_pmsn_size;
}
/**
* @brief PSRAM common transaction
*
* See `opi_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_set_op_mode(mspi_id, mode);
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);
}
/**
* @brief PSRAM common transaction
*
* See `opi_flash.h` for parameters
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_common_transaction(uint32_t mspi_id,
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,
bool is_write_erase_operation)
{
esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
uint32_t cs_mask = 1 << 1;
psram_ctrlr_ll_common_transaction_base(mspi_id, mode, cmd, cmd_bitlen, addr, addr_bitlen, dummy_bits,
mosi_data, mosi_bitlen, miso_data, miso_bitlen, cs_mask,
is_write_erase_operation);
}
/**
* @brief Wait MSPI PSRAM controller transaction done
*
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_wait_all_transaction_done(void)
{
#define ALL_TRANSACTION_DONE ( SPI_MEM_S_ALL_FIFO_EMPTY | \
SPI_RDATA_AFIFO_REMPTY | \
SPI_RADDR_AFIFO_REMPTY | \
SPI_WDATA_AFIFO_REMPTY | \
SPI_WBLEN_AFIFO_REMPTY | \
SPI_ALL_AXI_TRANS_AFIFO_EMPTY)
while (SPIMEM2.smem_axi_addr_ctrl.val != ALL_TRANSACTION_DONE) {
;
}
}
/**
* @brief Enable/Disable PSRAM controller interrupt
*
* @param mspi_id mspi_id
* @param intr_mask interrupt mask
* @param enable enable / disable
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_intr(uint32_t mspi_id, uint32_t intr_mask, bool enable)
{
if (enable) {
SPIMEM2.mem_int_ena.val |= intr_mask;
} else {
SPIMEM2.mem_int_ena.val &= ~intr_mask;
}
}
/**
* @brief Clear PSRAM controller interrupt
*
* @param mspi_id mspi_id
* @param intr_mask interrupt mask
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_clear_intr(uint32_t mspi_id, uint32_t intr_mask)
{
SPIMEM2.mem_int_clr.val = intr_mask;
}
/**
* @brief Get PSRAM controller interrupt raw
*
* @param mspi_id mspi_id
*/
__attribute__((always_inline))
static inline uint32_t psram_ctrlr_ll_get_intr_raw(uint32_t mspi_id)
{
return SPIMEM2.mem_int_raw.val;
}
/**
* @brief Backup PSRAM controller registers
*
* @param mspi_id mspi_id
* @param reg registers
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_backup_registers(uint32_t mspi_id, spi_mem_s_dev_t *reg)
{
memcpy(reg, &SPIMEM2, sizeof(spi_mem_s_dev_t));
}
/**
* @brief Restore PSRAM controller registers
*
* @param mspi_id mspi_id
* @param reg registers
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_restore_registers(uint32_t mspi_id, spi_mem_s_dev_t *reg)
{
memcpy(&SPIMEM2, reg, sizeof(spi_mem_s_dev_t));
}
/**
* @brief Disable core error response
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_disable_core_err_resp(void)
{
HP_SYSTEM.core_err_resp_dis.val = 0x7;
}
/**
* @brief Enable core error response
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_core_err_resp(void)
{
HP_SYSTEM.core_err_resp_dis.val = 0x0;
}
#ifdef __cplusplus
}
#endif
@@ -682,7 +682,7 @@ static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void)
switch (HP_SYS_CLKRST.flash_ctrl0.reg_flash_clk_src_sel) {
case 0:
source_clk_mhz = clk_ll_xtal_load_freq_mhz();
source_clk_mhz = clk_ll_xtal_get_freq_mhz();
break;
case 1:
source_clk_mhz = CLK_LL_PLL_480M_FREQ_MHZ; // SPLL
+2
View File
@@ -33,6 +33,8 @@ static int s_apll_ref_cnt = 0;
#if SOC_CLK_MPLL_SUPPORTED
static uint32_t s_cur_mpll_freq_hz = 0;
static int s_mpll_ref_cnt = 0;
#endif
#if CONFIG_ESP_LDO_RESERVE_PSRAM
static esp_ldo_channel_handle_t s_ldo_chan = NULL;
#endif
+12 -11
View File
@@ -37,20 +37,21 @@ entries:
rtc_sleep:rtc_sleep_pd (noflash)
if IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y:
rtc_sleep:rtc_sleep_pu (noflash)
if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y:
pmu_sleep (noflash)
if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP != y:
pmu_sleep_clock_icg:pmu_sleep_clock_icg_config (noflash)
sleep_mspi (noflash)
if SOC_PMU_SUPPORTED = y:
if SPIRAM_FLASH_LOAD_TO_PSRAM = y:
pmu_init (noflash)
pmu_param (noflash)
elif PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32P4 != y:
pmu_param:get_act_lp_dbias (noflash)
if IDF_TARGET_ESP32H4 || IDF_TARGET_ESP32H21 = y:
pmu_param:get_act_hp_drvb (noflash)
else:
pmu_param:get_act_hp_dbias (noflash)
if SOC_LIGHT_SLEEP_SUPPORTED = y:
pmu_sleep (noflash)
if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP != y:
pmu_sleep_clock_icg:pmu_sleep_clock_icg_config (noflash)
sleep_mspi (noflash)
if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32P4 != y:
pmu_param:get_act_lp_dbias (noflash)
if IDF_TARGET_ESP32H4 || IDF_TARGET_ESP32H21 = y:
pmu_param:get_act_hp_drvb (noflash)
else:
pmu_param:get_act_hp_dbias (noflash)
if SOC_PMU_PVT_SUPPORTED = y && ESP_ENABLE_PVT = y:
pmu_pvt (noflash)
if PM_SLP_IRAM_OPT = y && SOC_USB_SERIAL_JTAG_SUPPORTED = y:
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -481,6 +481,18 @@ void mspi_timing_psram_tuning(void)
/*------------------------------------------------------------------------------
* APIs to make SPI0 (and SPI1) FLASH work for high/low freq
*----------------------------------------------------------------------------*/
void __attribute__((weak)) mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi)
{
(void)control_both_mspi;
//for compatibility, will be replaced by the actual implementation once flash timing tuning is ready
}
void __attribute__((weak)) mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi)
{
(void)control_both_mspi;
//for compatibility, will be replaced by the actual implementation once flash timing tuning is ready
}
uint32_t mspi_timing_get_psram_low_speed_freq_mhz(void)
{
return 20;
@@ -0,0 +1,11 @@
target_include_directories(${COMPONENT_LIB} PUBLIC .)
set(srcs)
if(NOT BOOTLOADER_BUILD)
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi_timing_config.c")
endif()
endif()
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
@@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "soc/soc_caps.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/mspi_timing_config.h"
#include "mspi_timing_tuning_configs.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/mspi_ll.h"
#include "soc/hp_sys_clkrst_struct.h"
ESP_LOG_ATTR_TAG(TAG, "MSPI Timing");
//-------------------------------------MSPI Clock Setting-------------------------------------//
void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi)
{
uint32_t freqdiv = MSPI_TIMING_MPLL_FREQ_MHZ / MSPI_TIMING_CORE_CLOCK_DIV / psram_freq_mhz;
assert(freqdiv > 0);
ESP_DRAM_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv);
PERIPH_RCC_ATOMIC() {
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, freqdiv);
}
}
void mspi_timing_config_set_flash_clock(uint32_t flash_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi)
{
#if MSPI_TIMING_FLASH_NEEDS_TUNING
assert(HP_SYS_CLKRST.peri_clk_ctrl00.reg_flash_clk_src_sel == 1);
uint32_t core_clock_mhz = MSPI_TIMING_SPLL_FREQ_MHZ / MSPI_TIMING_LL_HP_FLASH_CORE_CLK_DIV;
assert(core_clock_mhz == 120);
uint32_t freqdiv = core_clock_mhz / flash_freq_mhz;
PERIPH_RCC_ATOMIC() {
//core clock shared among SPI0 / SPI1
mspi_timing_ll_set_flash_core_clock(MSPI_TIMING_LL_MSPI_ID_0, core_clock_mhz);
}
mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_0, freqdiv);
if (control_both_mspi) {
mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_1, freqdiv);
}
mspi_timing_ll_mask_invalid_dqs(MSPI_TIMING_LL_MSPI_ID_0, true);
mspi_timing_ll_mask_invalid_dqs(MSPI_TIMING_LL_MSPI_ID_1, true);
#endif
}
@@ -0,0 +1,60 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#define MSPI_TIMING_MSPI1_IS_INVOLVED CONFIG_ESPTOOLPY_FLASHFREQ_120M //This means esp flash driver needs to be notified
#define MSPI_TIMING_CONFIG_NUM_MAX 32 //This should be larger than the max available timing config num
#define MSPI_TIMING_TEST_DATA_LEN 128
#define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0x80
#define MSPI_TIMING_DELAYLINE_TEST_NUMS 100
#define MSPI_TIMING_FLASH_TEST_DATA_ADDR CONFIG_BOOTLOADER_OFFSET_IN_FLASH
#define MSPI_TIMING_CORE_CLOCK_DIV 1
#if CONFIG_SPIRAM_SPEED_250M
#define MSPI_TIMING_PSRAM_NEEDS_TUNING 1
#define MSPI_TIMING_MPLL_FREQ_MHZ 500
#elif CONFIG_SPIRAM_SPEED_200M
#define MSPI_TIMING_PSRAM_NEEDS_TUNING 1
#define MSPI_TIMING_MPLL_FREQ_MHZ 400
#elif CONFIG_SPIRAM_SPEED_80M
#define MSPI_TIMING_PSRAM_NEEDS_TUNING 1
#define MSPI_TIMING_MPLL_FREQ_MHZ 320
#else
#define MSPI_TIMING_MPLL_FREQ_MHZ 400
#endif
#define MSPI_TIMING_SPLL_FREQ_MHZ 480
#define MSPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_OCT
#define MSPI_TIMING_FLASH_STR_MODE 1
#if CONFIG_ESPTOOLPY_FLASHFREQ_20M
#define MSPI_TIMING_FLASH_MODULE_CLOCK 20
#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
#define MSPI_TIMING_FLASH_MODULE_CLOCK 40
#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
#define MSPI_TIMING_FLASH_MODULE_CLOCK 80
#else //CONFIG_ESPTOOLPY_FLASHFREQ_120M
#define MSPI_TIMING_FLASH_MODULE_CLOCK 120
#endif
#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 80)
#if MSPI_TIMING_FLASH_NEEDS_TUNING
#define MSPI_TIMING_FLASH_CORE_CLOCK_MHZ 120
#else
#define MSPI_TIMING_FLASH_CORE_CLOCK_MHZ 80
#endif
//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------//
#define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \
(mspi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \
.available_config_num = MSPI_TIMING_##type##_CONFIG_NUM_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \
.flash_default_config_id = MSPI_TIMING_##type##_DEFAULT_CONFIG_ID_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode }
#define _GET_TUNING_CONFIG(type, core_clock, module_clock, mode) __GET_TUNING_CONFIG(type, core_clock, module_clock, mode)
#define MSPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -157,24 +157,6 @@ void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi);
*/
void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi);
/**
* @brief Set Flash timing tuning settings
*
* This is used when the system is going to high speed mode / MSPI needs to be run in high speed
*
* @param[in] control_both_mspi Control MSPI1 as well
*/
void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi);
/**
* @brief Clear Flash timing tuning settings
*
* This is used when the system is going into low speed mode / MSPI doesn't need to be run in high speed
*
* @param[in] control_both_mspi Control MSPI1 as well
*/
void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#ifdef __cplusplus
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -49,12 +49,14 @@ ESP_LOG_ATTR_TAG(TAG, "MSPI DQS");
const static uint32_t s_test_data[MSPI_TIMING_TEST_DATA_LEN] = {0x7f786655, 0xa5ff005a, 0x3f3c33aa, 0xa5ff5a00, 0x1f1e9955, 0xa5005aff, 0x0f0fccaa, 0xa55a00ff,
0x07876655, 0xffa55a00, 0x03c333aa, 0xff00a55a, 0x01e19955, 0xff005aa5, 0x00f0ccaa, 0xff5a00a5,
0x80786655, 0x00a5ff5a, 0xc03c33aa, 0x00a55aff, 0xe01e9355, 0x00ff5aa5, 0xf00fccaa, 0x005affa5,
0xf8876655, 0x5aa5ff00, 0xfcc333aa, 0x5affa500, 0xfee19955, 0x5a00a5ff, 0x11f0ccaa, 0x5a00ffa5};
0xf8876655, 0x5aa5ff00, 0xfcc333aa, 0x5affa500, 0xfee19955, 0x5a00a5ff, 0x11f0ccaa, 0x5a00ffa5
};
const static mspi_timing_config_t s_test_delayline_config = {
.delayline_table = {{0, 15}, {0, 14}, {0, 13}, {0, 12}, {0, 11}, {0, 10}, {0, 9}, {0, 8}, {0, 7}, {0, 6}, {0, 5}, {0, 4}, {0, 3}, {0, 2}, {0, 1},
{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0}},
.available_config_num = 31,
};
.delayline_table = {{0, 15}, {0, 14}, {0, 13}, {0, 12}, {0, 11}, {0, 10}, {0, 9}, {0, 8}, {0, 7}, {0, 6}, {0, 5}, {0, 4}, {0, 3}, {0, 2}, {0, 1},
{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0}
},
.available_config_num = 31,
};
static mspi_ll_dqs_phase_t s_psram_best_phase = MSPI_LL_DQS_PHASE_MAX;
static delayline_config_t s_psram_best_delayline = {WRONG_DELAYLINE, WRONG_DELAYLINE};
@@ -121,7 +123,9 @@ void mspi_timing_config_psram_set_tuning_phase(const void *configs, uint8_t id)
{
mspi_ll_dqs_phase_t phase = ((mspi_timing_config_t *)configs)->phase[id];
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, phase);
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, phase);
#endif
ESP_DRAM_LOGD(TAG, "set to phase: %d", phase);
}
@@ -139,7 +143,7 @@ uint32_t mspi_timing_psram_select_best_tuning_phase(const void *configs, uint32_
}
if (success) {
ESP_DRAM_LOGD(TAG, "tuning success, best phase id is %"PRIu32, best_phase_id);
ESP_DRAM_LOGI(TAG, "tuning success, best phase id is %"PRIu32, best_phase_id);
} else {
ESP_DRAM_LOGW(TAG, "tuning fail, best phase id is fallen back to index %"PRIu32"", best_phase_id);
}
@@ -162,14 +166,22 @@ void mspi_timing_config_psram_set_tuning_delayline(const void *configs, uint8_t
{
assert(s_psram_best_phase != MSPI_LL_DQS_PHASE_MAX);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, s_psram_best_phase);
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, s_psram_best_phase);
#endif
ESP_DRAM_LOGD(TAG, "set to best phase: %d", s_psram_best_phase);
const delayline_config_t *delayline_config = &((mspi_timing_config_t *)configs)->delayline_table[id];
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
if (i == MSPI_LL_PIN_DQS0 || i == MSPI_LL_PIN_DQS1) {
if (i == MSPI_LL_PIN_DQS0) {
mspi_timing_ll_set_delayline(i, delayline_config->dqs_delayline);
} else {
}
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
else if (i == MSPI_LL_PIN_DQS1) {
mspi_timing_ll_set_delayline(i, delayline_config->dqs_delayline);
}
#endif
else {
mspi_timing_ll_set_delayline(i, delayline_config->data_delayline);
}
}
@@ -185,7 +197,7 @@ uint32_t mspi_timing_psram_select_best_tuning_delayline(const void *configs, uin
ESP_DRAM_LOGW(TAG, "tuning fail, best delayline id is fallen back to index %"PRIu32"", bset_delayline_id);
} else {
bset_delayline_id = end - consecutive_length / 2;
ESP_DRAM_LOGD(TAG, "tuning success, best delayline id is %"PRIu32, bset_delayline_id);
ESP_DRAM_LOGI(TAG, "tuning success, best delayline id is %"PRIu32, bset_delayline_id);
}
return bset_delayline_id;
@@ -199,8 +211,9 @@ void mspi_timing_psram_set_best_tuning_delayline(const void *configs, uint8_t be
void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi)
{
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, 0);
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, 0);
#endif
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
mspi_timing_ll_set_delayline(i, 0);
}
@@ -209,12 +222,20 @@ void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi)
void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi)
{
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, s_psram_best_phase);
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, s_psram_best_phase);
#endif
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
if (i == MSPI_LL_PIN_DQS0 || i == MSPI_LL_PIN_DQS1) {
if (i == MSPI_LL_PIN_DQS0) {
mspi_timing_ll_set_delayline(i, s_psram_best_delayline.dqs_delayline);
} else {
}
#if MSPI_LL_PSRAM_DQS1_SUPPORTED
else if (i == MSPI_LL_PIN_DQS1) {
mspi_timing_ll_set_delayline(i, s_psram_best_delayline.dqs_delayline);
}
#endif
else {
mspi_timing_ll_set_delayline(i, s_psram_best_delayline.data_delayline);
}
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -40,4 +40,11 @@
void esp_cpu_configure_region_protection(void)
{
/* TODO: [ESP32S31] IDF-15238 */
__attribute__((unused)) const unsigned PMA_RW = PMA_L | PMA_EN | PMA_R | PMA_W;
__attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X;
__attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X;
//without setting this, psram cannot be reached
PMA_RESET_AND_ENTRY_SET_NAPOT(7, SOC_EXTRAM_LOW, (SOC_EXTRAM_HIGH - SOC_EXTRAM_LOW), PMA_NAPOT | PMA_RWX);
}
@@ -32,7 +32,7 @@ static const char *TAG = "rtc_clk";
static int s_cur_cpll_freq = 0;
// MPLL frequency option, 400MHz. Zero if MPLL is not enabled.
static SPM_DRAM_ATTR uint32_t s_cur_mpll_freq = 0;
static uint32_t s_cur_mpll_freq = 0;
void rtc_clk_32k_enable(bool enable)
{
@@ -204,7 +204,7 @@ void rtc_clk_cpu_freq_set_xtal_for_sleep(void)
soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
{
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
uint32_t xtal_freq_mhz = clk_ll_xtal_get_freq_mhz();
if (xtal_freq_mhz == 0) {
ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz");
return SOC_XTAL_FREQ_40M;
@@ -214,7 +214,7 @@ soc_xtal_freq_t rtc_clk_xtal_freq_get(void)
void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq)
{
clk_ll_xtal_store_freq_mhz(xtal_freq);
// clk_ll_xtal_store_freq_mhz(xtal_freq);
}
uint32_t rtc_clk_apb_freq_get(void)
@@ -331,7 +331,26 @@ IRAM_ATTR void rtc_clk_mpll_enable(void)
void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq, bool thread_safe)
{
// TODO: ["ESP32S31"] IDF-14678
/* Analog part */
if (thread_safe) {
_regi2c_ctrl_ll_master_enable_clock(true);
} else {
ANALOG_CLOCK_ENABLE();
}
/* MPLL calibration start */
clk_ll_mpll_calibration_start();
clk_ll_mpll_set_config(mpll_freq, xtal_freq);
/* wait calibration done */
while(!clk_ll_mpll_calibration_is_done());
/* MPLL calibration stop */
clk_ll_mpll_calibration_stop();
if (thread_safe) {
_regi2c_ctrl_ll_master_enable_clock(false);
} else {
ANALOG_CLOCK_DISABLE();
}
s_cur_mpll_freq = mpll_freq;
}
IRAM_ATTR uint32_t rtc_clk_mpll_get_freq(void)
@@ -213,7 +213,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
uint64_t rtc_time_get(void)
{
return 0;// TODO: ["ESP32S31"] IDF-14678
return rtc_timer_hal_get_cycle_count(0);
}
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
+3 -1
View File
@@ -31,7 +31,9 @@ if(CONFIG_SPIRAM)
endif()
elseif(CONFIG_SPIRAM_MODE_OCT)
list(APPEND srcs "${target}/esp_psram_impl_octal.c")
if(${target} STREQUAL "esp32s3")
list(APPEND srcs "${target}/esp_psram_impl_octal.c")
endif()
endif()
endif()
@@ -6,6 +6,12 @@ if(CONFIG_SPIRAM_MODE_QUAD)
endif()
endif()
if(CONFIG_SPIRAM_MODE_OCT)
if(NOT ${target} STREQUAL "esp32s3")
list(APPEND srcs "esp_psram_impl_ap_oct.c")
endif()
endif()
if(CONFIG_SPIRAM_MODE_HEX)
list(APPEND srcs "esp_psram_impl_ap_hex.c")
endif()
@@ -0,0 +1,585 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/mspi_timing_tuning.h"
#include "esp_private/esp_psram_impl.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/mspi_ll.h"
#include "clk_ctrl_os.h"
#include "soc/rtc.h"
#define AP_OCT_PSRAM_SYNC_READ 0x0000
#define AP_OCT_PSRAM_SYNC_WRITE 0x8080
#define AP_OCT_PSRAM_BURST_READ 0x2020
#define AP_OCT_PSRAM_BURST_WRITE 0xA0A0
#define AP_OCT_PSRAM_REG_READ 0x4040
#define AP_OCT_PSRAM_REG_WRITE 0xC0C0
#define AP_OCT_PSRAM_RD_CMD_BITLEN 16
#define AP_OCT_PSRAM_WR_CMD_BITLEN 16
#define AP_OCT_PSRAM_ADDR_BITLEN 32
#if CONFIG_SPIRAM_SPEED_250M
#define AP_OCT_PSRAM_RD_DUMMY_BITLEN (2*(18-1))
#define AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN (2*(9-1))
#define AP_OCT_PSRAM_WR_DUMMY_BITLEN (2*(9-1))
#define AP_OCT_PSRAM_RD_LATENCY 6
#define AP_OCT_PSRAM_WR_LATENCY 3
#elif CONFIG_SPIRAM_SPEED_200M
#define AP_OCT_PSRAM_RD_DUMMY_BITLEN (2*(14-1))
#define AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN (2*(7-1))
#define AP_OCT_PSRAM_WR_DUMMY_BITLEN (2*(7-1))
#define AP_OCT_PSRAM_RD_LATENCY 4
#define AP_OCT_PSRAM_WR_LATENCY 1
#else
#define AP_OCT_PSRAM_RD_DUMMY_BITLEN (2*(10-1))
#define AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN (2*(5-1))
#define AP_OCT_PSRAM_WR_DUMMY_BITLEN (2*(5-1))
#define AP_OCT_PSRAM_RD_LATENCY 2
#define AP_OCT_PSRAM_WR_LATENCY 2
#endif
#define AP_OCT_PSRAM_VENDOR_ID_AP 0xD
#define AP_OCT_PSRAM_VENDOR_ID_UNILC 0x1A //UnilC shares driver pattern with AP
#define AP_OCT_PSRAM_CS_SETUP_TIME 4
#define AP_OCT_PSRAM_CS_HOLD_TIME 4
#define AP_OCT_PSRAM_CS_ECC_HOLD_TIME 4
#define AP_OCT_PSRAM_CS_HOLD_DELAY 3
#if CONFIG_SPIRAM_SPEED_80M
#define AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ 320
#elif CONFIG_SPIRAM_SPEED_250M
#define AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ 500
#else
#define AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ 400
#endif
#define AP_OCT_PSRAM_REF_DATA 0x5a6b7c8d
#define AP_OCT_PSRAM_ULP_MODE_HALFSLEEP 0xF0
typedef struct {
union {
struct {
uint8_t drive_str: 2;
uint8_t read_latency: 3;
uint8_t lt: 1;
uint8_t rsvd6: 1;
uint8_t tso: 1;
};
uint8_t val;
} mr0;
union {
struct {
uint8_t vendor_id: 5;
uint8_t rsvd5_7: 3;
uint8_t ulp: 1;
};
uint8_t val;
} mr1;
union {
struct {
uint8_t density: 3;
uint8_t dev_id: 2;
uint8_t kgd: 3;
};
uint8_t val;
} mr2;
union {
struct {
uint8_t rsvd0_3: 4;
uint8_t srf: 2;
uint8_t rsvd6: 1;
uint8_t rbx_en: 1;
};
uint8_t val;
} mr3;
union {
struct {
uint8_t pasr: 3;
uint8_t rf: 2;
uint8_t wr_latency: 3;
};
uint8_t val;
} mr4;
union {
struct {
uint8_t rsvd0_3: 4;
uint8_t halfsleep: 4;
};
uint8_t val;
} mr6;
union {
struct {
uint8_t bl: 2;
uint8_t bt: 1;
uint8_t rbx: 1;
uint8_t rsvd5: 2;
uint8_t x16: 1;
uint8_t rsvd7: 1;
};
uint8_t val;
} mr8;
} oct_psram_mode_reg_t;
static const char* TAG = "oct_psram";
static uint32_t s_psram_size; //this stands for physical psram size in bytes
/**
* Common psram transaction
*/
static void s_psram_common_transaction(uint32_t mspi_id,
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,
bool is_write_erase_operation)
{
psram_ctrlr_ll_common_transaction(mspi_id, cmd, cmd_bitlen, addr, addr_bitlen, dummy_bits,
mosi_data, mosi_bitlen, miso_data, miso_bitlen,
is_write_erase_operation);
}
/**
* Initialise mode registers of the PSRAM
*/
static void s_init_psram_mode_reg(int spi_num, oct_psram_mode_reg_t *mode_reg_config)
{
int cmd_len = 16;
uint32_t addr = 0x0;
int addr_bit_len = 32;
int dummy = AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN;
oct_psram_mode_reg_t mode_reg = {0};
int data_bit_len = 16;
//read MR0 and MR1
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
dummy,
NULL, 0,
&mode_reg.mr0.val, data_bit_len,
false);
addr = 0x4;
//read MR4 and MR8
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
dummy,
NULL, 0,
&mode_reg.mr4.val, data_bit_len,
false);
//modify
mode_reg.mr0.lt = mode_reg_config->mr0.lt;
mode_reg.mr0.read_latency = mode_reg_config->mr0.read_latency;
mode_reg.mr0.drive_str = mode_reg_config->mr0.drive_str;
mode_reg.mr4.wr_latency = mode_reg_config->mr4.wr_latency;
//write
addr = 0x0;
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
0,
&mode_reg.mr0.val, 16,
NULL, 0,
false);
addr = 0x4;
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
0,
&mode_reg.mr4.val, 16,
NULL, 0,
false);
//read
addr = 0x8;
data_bit_len = 8;
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
dummy,
NULL, 0,
&mode_reg.mr8.val, data_bit_len,
false);
//modify
mode_reg.mr8.bt = mode_reg_config->mr8.bt;
mode_reg.mr8.bl = mode_reg_config->mr8.bl;
mode_reg.mr8.rbx = mode_reg_config->mr8.rbx;
mode_reg.mr8.x16 = mode_reg_config->mr8.x16;
//write
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
0,
&mode_reg.mr8.val, 16,
NULL, 0,
false);
}
static void s_get_psram_mode_reg(int spi_num, oct_psram_mode_reg_t *out_reg)
{
int cmd_len = 16;
int addr_bit_len = 32;
int dummy = AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN;
int data_bit_len = 16;
//Read MR0~1 register
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
0x0, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr0.val, data_bit_len,
false);
//Read MR2~3 register
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
0x2, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr2.val, data_bit_len,
false);
data_bit_len = 8;
//Read MR4 register
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
0x4, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr4.val, data_bit_len,
false);
//Read MR8 register
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_REG_READ, cmd_len,
0x8, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr8.val, data_bit_len,
false);
}
/**
* Check if PSRAM is connected by write and read
*/
static esp_err_t s_check_psram_connected(int spi_num)
{
uint32_t addr = 0x80;
uint32_t ref_data = AP_OCT_PSRAM_REF_DATA;
uint32_t exp_data = 0;
int data_bit_len = 32;
//write
addr = 0x0;
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_SYNC_WRITE, AP_OCT_PSRAM_WR_CMD_BITLEN,
addr, AP_OCT_PSRAM_ADDR_BITLEN,
AP_OCT_PSRAM_WR_DUMMY_BITLEN,
(uint8_t *)&ref_data, data_bit_len,
NULL, 0,
false);
//read MR4 and MR8
s_psram_common_transaction(spi_num,
AP_OCT_PSRAM_SYNC_READ, AP_OCT_PSRAM_RD_CMD_BITLEN,
addr, AP_OCT_PSRAM_ADDR_BITLEN,
AP_OCT_PSRAM_RD_DUMMY_BITLEN,
NULL, 0,
(uint8_t *)&exp_data, data_bit_len,
false);
ESP_EARLY_LOGD(TAG, "exp_data: 0x%08x", exp_data);
ESP_EARLY_LOGD(TAG, "ref_data: 0x%08x", ref_data);
return (exp_data == ref_data ? ESP_OK : ESP_FAIL);
}
static void s_print_psram_info(oct_psram_mode_reg_t *reg_val)
{
ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : "UNKNOWN");
ESP_EARLY_LOGI(TAG, "Latency : 0x%02x (%s)", reg_val->mr0.lt, reg_val->mr0.lt == 1 ? "Fixed" : "Variable");
ESP_EARLY_LOGI(TAG, "DriveStr. : 0x%02x (%d Ohm)", reg_val->mr0.drive_str, reg_val->mr0.drive_str < 2 ? 25 * (reg_val->mr0.drive_str + 1) : 100 * (reg_val->mr0.drive_str - 1));
ESP_EARLY_LOGI(TAG, "dev id : 0x%02x (generation %d)", reg_val->mr2.dev_id, reg_val->mr2.dev_id + 1);
ESP_EARLY_LOGI(TAG, "density : 0x%02x (%d Mbit)", reg_val->mr2.density, reg_val->mr2.density == 0x1 ? 32 :
reg_val->mr2.density == 0X3 ? 64 :
reg_val->mr2.density == 0x5 ? 128 :
reg_val->mr2.density == 0x7 ? 256 : 0);
ESP_EARLY_LOGI(TAG, "good-die : 0x%02x (%s)", reg_val->mr2.kgd, reg_val->mr2.kgd == 6 ? "Pass" : "Fail");
ESP_EARLY_LOGI(TAG, "SRF : 0x%02x (%s Refresh)", reg_val->mr3.srf, reg_val->mr3.srf == 0x1 ? "Fast" : "Slow");
ESP_EARLY_LOGI(TAG, "BurstType : 0x%02x (%s Wrap)", reg_val->mr8.bt, reg_val->mr8.bt == 1 && reg_val->mr8.bl != 3 ? "Hybrid" : "");
ESP_EARLY_LOGI(TAG, "BurstLen : 0x%02x (%d Byte)", reg_val->mr8.bl, reg_val->mr8.bl == 0x00 ? 16 :
reg_val->mr8.bl == 0x01 ? 32 :
reg_val->mr8.bl == 0x10 ? 64 : 2048);
ESP_EARLY_LOGI(TAG, "BitMode : 0x%02x (%s Mode)", reg_val->mr8.x16, reg_val->mr8.x16 == 1 ? "X16" : "X8");
ESP_EARLY_LOGI(TAG, "Readlatency : 0x%02x (%d cycles@%s)", reg_val->mr0.read_latency, reg_val->mr0.read_latency * 2 + 6,
reg_val->mr0.lt == 1 ? "Fixed" : "Variable");
ESP_EARLY_LOGI(TAG, "DriveStrength: 0x%02x (1/%d)", reg_val->mr0.drive_str, reg_val->mr0.drive_str == 0x00 ? 1 :
reg_val->mr0.drive_str == 0x01 ? 2 :
reg_val->mr0.drive_str == 0x02 ? 4 : 8);
}
static void s_config_mspi_for_psram(void)
{
//Config Write CMD phase for SPI0 to access PSRAM
psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_WR_CMD_BITLEN, AP_OCT_PSRAM_SYNC_WRITE);
//Config Read CMD phase for SPI0 to access PSRAM
psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_RD_CMD_BITLEN, AP_OCT_PSRAM_SYNC_READ);
//Config ADDR phase
psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_ADDR_BITLEN);
psram_ctrlr_ll_enable_4byte_addr(PSRAM_CTRLR_LL_MSPI_ID_2, true);
//Config RD/WR Dummy phase
psram_ctrlr_ll_set_wr_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_WR_DUMMY_BITLEN);
psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_RD_DUMMY_BITLEN);
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_wr_dummy_level_control(PSRAM_CTRLR_LL_MSPI_ID_2, true);
//DDR
psram_ctrlr_ll_enable_ddr_wr_data_swap(PSRAM_CTRLR_LL_MSPI_ID_2, false);
psram_ctrlr_ll_enable_ddr_rd_data_swap(PSRAM_CTRLR_LL_MSPI_ID_2, false);
psram_ctrlr_ll_enable_ddr_mode(PSRAM_CTRLR_LL_MSPI_ID_2, true);
//8-line mode
psram_ctrlr_ll_enable_oct_line_mode(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_hex_data_line_mode(PSRAM_CTRLR_LL_MSPI_ID_2, false);
//AXI
psram_ctrlr_ll_enable_axi_access(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_wr_splice(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_rd_splice(PSRAM_CTRLR_LL_MSPI_ID_2, true);
}
static void s_set_psram_cs_timing(void)
{
psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_CS_SETUP_TIME);
psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_CS_HOLD_TIME);
psram_ctrlr_ll_set_cs_hold_delay(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_CS_HOLD_DELAY);
#if CONFIG_SPIRAM_ECC_ENABLE
psram_ctrlr_ll_set_cs_hold_ecc(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_CS_ECC_HOLD_TIME);
#endif
}
#if CONFIG_SPIRAM_ECC_ENABLE
static void s_mspi_ecc_show_info(void)
{
for (int i = 0; i < PSRAM_CTRLR_LL_PMS_REGION_NUMS; i++) {
ESP_EARLY_LOGV(TAG, "region[%d] addr: 0x%08x", i, psram_ctrlr_ll_get_pms_region_start_addr(PSRAM_CTRLR_LL_MSPI_ID_2, i));
ESP_EARLY_LOGV(TAG, "region[%d] size: 0x%08x", i, psram_ctrlr_ll_get_pms_region_size(PSRAM_CTRLR_LL_MSPI_ID_2, i));
}
uint32_t page_size = psram_ctrlr_ll_get_page_size(PSRAM_CTRLR_LL_MSPI_ID_2);
ESP_EARLY_LOGV(TAG, "ECC page size: %d", page_size);
}
/**
* Enable error correcting code feature
*
* Can add an input parameter for selecting ECC mode if needed
*/
static void s_configure_psram_ecc(void)
{
psram_ctrlr_ll_enable_16to18_ecc(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_skip_page_corner(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_ecc_addr_conversion(PSRAM_CTRLR_LL_MSPI_ID_2, 2048);
/**
* Enable ECC region 0 (ACE0)
* Default: ACE0 range: 0 ~ 256MB
* Current PSRAM is 8MB, ACE0 is enough
*/
psram_ctrlr_ll_enable_pms_region_ecc(PSRAM_CTRLR_LL_MSPI_ID_2, 0, true);
ESP_EARLY_LOGI(TAG, "ECC is enabled");
s_mspi_ecc_show_info();
}
#endif //#if CONFIG_SPIRAM_ECC_ENABLE
esp_err_t esp_psram_impl_enable(void)
{
#if SOC_CLK_MPLL_SUPPORTED
periph_rtc_mpll_acquire();
uint32_t real_mpll_freq = 0;
periph_rtc_mpll_freq_set(AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, &real_mpll_freq);
ESP_EARLY_LOGD(TAG, "real_mpll_freq: %d", real_mpll_freq);
#endif
PERIPH_RCC_ATOMIC() {
psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_reset_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL);
}
mspi_timing_ll_pin_drv_set(2);
mspi_timing_ll_enable_dqs(true);
s_set_psram_cs_timing();
psram_ctrlr_ll_enable_split_trans(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_page_size(PSRAM_CTRLR_LL_MSPI_ID_2, 2048);
#if CONFIG_SPIRAM_ECC_ENABLE
s_configure_psram_ecc();
#endif
//enter MSPI slow mode to init PSRAM device registers
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ / CONFIG_SPIRAM_SPEED);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ / CONFIG_SPIRAM_SPEED);
psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_3, true);
static oct_psram_mode_reg_t mode_reg = {};
mode_reg.mr0.lt = 1;
mode_reg.mr0.read_latency = AP_OCT_PSRAM_RD_LATENCY;
mode_reg.mr0.drive_str = 0;
mode_reg.mr4.wr_latency = AP_OCT_PSRAM_WR_LATENCY;
mode_reg.mr8.bl = 3;
mode_reg.mr8.bt = 0;
mode_reg.mr8.rbx = 1;
mode_reg.mr8.x16 = 0;
s_init_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
if (s_check_psram_connected(PSRAM_CTRLR_LL_MSPI_ID_3) != ESP_OK) {
ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected");
return ESP_ERR_NOT_SUPPORTED;
}
s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
if (mode_reg.mr1.vendor_id != AP_OCT_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != AP_OCT_PSRAM_VENDOR_ID_UNILC) {
ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", mode_reg.mr1.vendor_id);
}
s_print_psram_info(&mode_reg);
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
mode_reg.mr2.density == 0x5 ? PSRAM_SIZE_16MB :
mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_32MB :
mode_reg.mr2.density == 0x6 ? PSRAM_SIZE_64MB : 0;
s_config_mspi_for_psram();
mspi_timing_psram_tuning();
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_3, true);
return ESP_OK;
}
uint8_t esp_psram_impl_get_cs_io(void)
{
ESP_EARLY_LOGI(TAG, "psram CS IO is dedicated");
return -1;
}
esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
{
if (!out_size_bytes) {
return ESP_ERR_INVALID_ARG;
}
*out_size_bytes = s_psram_size;
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
}
/**
* This function is to get the available physical psram size in bytes.
* If ECC is enabled, available PSRAM size will be 7/8 times its physical size.
*/
esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
{
if (!out_size_bytes) {
return ESP_ERR_INVALID_ARG;
}
#if CONFIG_SPIRAM_ECC_ENABLE
*out_size_bytes = s_psram_size * 7 / 8;
#else
*out_size_bytes = s_psram_size;
#endif
return (s_psram_size ? ESP_OK : ESP_ERR_INVALID_STATE);
}
/******************************* Halfsleep Mode *******************************/
static struct {
uint8_t mr4;
uint64_t halfsleep_wakeup_tick;
} s_halfsleep_ctx = {0};
void esp_psram_impl_enter_halfsleep_mode(void)
{
// Backup MR4
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_OCT_PSRAM_REG_READ, AP_OCT_PSRAM_RD_CMD_BITLEN,
0x4, AP_OCT_PSRAM_ADDR_BITLEN,
AP_OCT_PSRAM_RD_REG_DUMMY_BITLEN,
NULL, 0,
&s_halfsleep_ctx.mr4, 16,
false);
// Set refresh rate to 0.5x
oct_psram_mode_reg_t mode_reg;
mode_reg.mr4.val = s_halfsleep_ctx.mr4;
mode_reg.mr4.rf = 3; // (0:4x 1:1x 3:0.5x)
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_OCT_PSRAM_REG_WRITE, AP_OCT_PSRAM_RD_CMD_BITLEN,
0x4, AP_OCT_PSRAM_ADDR_BITLEN,
0,
&mode_reg.mr4.val, 16,
NULL, 0,
false);
// Set halfsleep mode
uint8_t halfsleep_cmd = AP_OCT_PSRAM_ULP_MODE_HALFSLEEP;
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_OCT_PSRAM_REG_WRITE, AP_OCT_PSRAM_RD_CMD_BITLEN,
0x6, AP_OCT_PSRAM_ADDR_BITLEN,
0,
&halfsleep_cmd, 16,
NULL, 0,
false);
}
void esp_psram_impl_exit_halfsleep_mode(void)
{
// Record the tick exiting halfsleep mode
s_halfsleep_ctx.halfsleep_wakeup_tick = rtc_time_get();
// Do a SPI dummy write transmission to invalid address to wake up from halfsleep mode
uint8_t null = 0;
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_OCT_PSRAM_REG_WRITE, AP_OCT_PSRAM_WR_CMD_BITLEN,
0xFF, AP_OCT_PSRAM_ADDR_BITLEN,
0,
&null, 0,
NULL, 0,
false);
}
void esp_psram_impl_resume_from_halfsleep_mode(uint32_t slowclk_period)
{
uint64_t halfsleep_exit_tick = s_halfsleep_ctx.halfsleep_wakeup_tick + rtc_time_us_to_slowclk(CONFIG_PM_SLP_SPIRAM_HALFSLEEP_EXIT_WAIT_DELAY, slowclk_period);
while (rtc_time_get() < halfsleep_exit_tick) {
// Busy wait for PSRAM to exit halfsleep mode
}
// Restore MR4 configuration (restore refresh rate)
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_OCT_PSRAM_REG_WRITE, AP_OCT_PSRAM_WR_CMD_BITLEN,
0x4, AP_OCT_PSRAM_ADDR_BITLEN,
0,
&s_halfsleep_ctx.mr4, 16,
NULL, 0,
false);
}
@@ -0,0 +1,96 @@
config SPIRAM
bool "Support for external PSRAM"
default "n"
help
This enables support for an external PSRAM chip, connected in parallel with the
main SPI flash chip.
menu "PSRAM config"
depends on SPIRAM
choice SPIRAM_MODE
prompt "Line Mode of PSRAM chip in use"
default SPIRAM_MODE_OCT
config SPIRAM_MODE_OCT
bool "8-Line-Mode PSRAM"
endchoice
choice SPIRAM_SPEED
prompt "Set PSRAM clock speed"
default SPIRAM_SPEED_200M
help
Select the speed for the PSRAM chip.
config SPIRAM_SPEED_250M
bool "250MHz clock speed"
config SPIRAM_SPEED_200M
bool "200MHz clock speed"
config SPIRAM_SPEED_80M
bool "80MHz clock speed"
config SPIRAM_SPEED_40M
bool "40MHz clock speed"
endchoice
config SPIRAM_SPEED
int
default 40 if SPIRAM_SPEED_40M
default 80 if SPIRAM_SPEED_80M
default 100 if SPIRAM_SPEED_100M
default 200 if SPIRAM_SPEED_200M
default 250 if SPIRAM_SPEED_250M
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
depends on SPIRAM_BOOT_INIT
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.
Because P4 flash and PSRAM are using two separate SPI buses, moving flash content to PSRAM will
actually increase the load of the PSRAM MSPI bus, so the exact impact on performance will be dependent
on your app usage of PSRAM. For example, as the PSRAM bus speed could be much faster than flash bus speed,
if the instructions and data that are used to be in flash are not accessed very frequently, you might
get better performance with this option enabled. We suggest doing performance profiling to determine
if enabling this option.
config SPIRAM_FLASH_LOAD_TO_PSRAM
bool
help
This is a helper indicating this condition:
`CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32S31`
config SPIRAM_ECC_ENABLE
bool "Enable PSRAM ECC"
default n
help
Enable 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
+3 -1
View File
@@ -17,8 +17,10 @@ entries:
if SPIRAM_MODE_HEX = y:
esp_psram_impl_ap_hex (noflash)
if SPIRAM_MODE_OCT = y:
esp_psram_impl_ap_oct (noflash)
if SPIRAM_FLASH_LOAD_TO_PSRAM = y:
esp_psram_impl_ap_hex (noflash)
mmu_psram_flash_v2 (noflash)
esp_psram: esp_psram_chip_init (noflash)
esp_psram: esp_psram_init (noflash)
@@ -1,4 +1,4 @@
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
This test app is used to test PSRAM
@@ -65,9 +65,9 @@ TEST_CASE("test psram halfsleep mode (if applicable)", "[psram]")
{
uint32_t rtc_slow_clk_period = rtc_clk_cal(CLK_CAL_RTC_SLOW, CONFIG_RTC_CLK_CAL_CYCLES);
s_test_psram_heap_allocable();
for (int i = 0; i < 5; i++) {
for (int i = 0; i < 3; i++) {
esp_psram_impl_enter_halfsleep_mode();
vTaskDelay(pdMS_TO_TICKS(1000));
esp_rom_delay_us(1000);
esp_psram_impl_exit_halfsleep_mode();
esp_psram_impl_resume_from_halfsleep_mode(rtc_slow_clk_period);
s_test_psram_heap_allocable();
@@ -0,0 +1,325 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ROM_OPI_FLASH_H_
#define _ROM_OPI_FLASH_H_
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "spi_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint8_t mode;
uint8_t cmd_bit_len;
uint16_t cmd;
uint32_t addr;
uint8_t addr_bit_len;
uint8_t dummy_bit_len;
uint8_t data_bit_len;
uint8_t cs_sel: 4;
uint8_t is_pe: 4;
} esp_rom_opiflash_cmd_t;
typedef struct {
uint8_t addr_bit_len;
uint8_t dummy_bit_len;
uint16_t cmd;
uint8_t cmd_bit_len;
uint8_t var_dummy_en;
} esp_rom_opiflash_spi0rd_t;
typedef struct {
esp_rom_opiflash_cmd_t rdid;
esp_rom_opiflash_cmd_t rdsr;
esp_rom_opiflash_cmd_t wren;
esp_rom_opiflash_cmd_t se;
esp_rom_opiflash_cmd_t be64k;
esp_rom_opiflash_cmd_t read;
esp_rom_opiflash_cmd_t pp;
esp_rom_opiflash_spi0rd_t cache_rd_cmd;
bool usr_ecc_en;
} esp_rom_opiflash_def_t;
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;
#define ESP_ROM_OPIFLASH_MUX_TAKE()
#define ESP_ROM_OPIFLASH_MUX_GIVE()
#define ESP_ROM_OPIFLASH_SEL_CS0 (BIT(0))
#define ESP_ROM_OPIFLASH_SEL_CS1 (BIT(1))
// 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
extern const esp_rom_opiflash_def_t *rom_opiflash_cmd_def;
/**
* @brief init legacy driver for Octal Flash
*/
void esp_rom_opiflash_legacy_driver_init(const esp_rom_opiflash_def_t *flash_cmd_def);
// 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);
/**
* @brief Config opi flash pads according to efuse settings.
*/
void esp_rom_opiflash_pin_config(void);
// 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);
/**
* @brief Set data swap mode in DTR(DDR) mode
* @param spi_num spi port
* @param wr_swap to decide whether to swap fifo data in dtr write operation
* @param rd_swap to decide whether to swap fifo data in dtr read operation
*/
void esp_rom_spi_set_dtr_swap_mode(int spi, bool wr_swap, bool rd_swap);
/**
* @brief to send reset command in spi/opi-str/opi-dtr mode(for MX25UM25645G)
* @param spi_num spi port
*/
void esp_rom_opiflash_mode_reset(int spi_num);
/**
* @brief To execute a flash operation command
* @param spi_num spi port
* @param mode Flash Read Mode
* @param cmd data to send in command field
* @param cmd_bit_len bit length of command field
* @param addr data to send in address field
* @param addr_bit_len bit length of address field
* @param dummy_bits bit length of dummy field
* @param mosi_data data buffer to be sent in mosi field
* @param mosi_bit_len bit length of data buffer to be sent in mosi field
* @param miso_data data buffer to accept data in miso field
* @param miso_bit_len bit length of data buffer to accept data in miso field
* @param cs_mark decide which cs pin to use. 0: cs0, 1: cs1
* @param is_write_erase_operation to indicate whether this a write or erase flash operation
*/
void esp_rom_opiflash_exec_cmd(int spi_num, esp_rom_spiflash_read_mode_t mode,
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits,
uint8_t* mosi_data, int mosi_bit_len,
uint8_t* miso_data, int miso_bit_len,
uint32_t cs_mask,
bool is_write_erase_operation);
/**
* @brief send reset command to opi flash
* @param spi_num spi port
* @param mode Flash Operation Mode
*/
void esp_rom_opiflash_soft_reset(int spi_num, esp_rom_spiflash_read_mode_t mode);
/**
* @brief to read opi flash ID
* @note command format would be defined in initialization
* @param[out] out_id buffer to accept id
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_read_id(uint8_t *out_id);
/**
* @brief to read opi flash status register
* @note command format would be defined in initialization
* @return opi flash status value
*/
uint8_t esp_rom_opiflash_rdsr(void);
/**
* @brief wait opi flash status register to be idle
* @note command format would be defined in initialization
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_wait_idle(void);
/**
* @brief to erase flash sector
* @note command format would be defined in initialization
* @param sector_num the sector to be erased
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_erase_sector(uint32_t sector_num);
/**
* @brief to erase flash block
* @note command format would be defined in initialization
* @param block_num the block to be erased
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_erase_block_64k(uint32_t block_num);
/**
* @brief to erase a flash area define by start address and length
* @note command format would be defined in initialization
* @param start_addr the start address to be erased
* @param area_len the erea length to be erased
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_erase_area(uint32_t start_addr, uint32_t area_len);
/**
* @brief to read data from opi flash
* @note command format would be defined in initialization
* @param flash_addr flash address to read data from
* @param data_addr data buffer to accept the data
* @param len data length to be read
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_read(uint32_t flash_addr, void *data_addr, int len);
/**
* @brief to write data to opi flash
* @note command format would be defined in initialization
* @param flash_addr flash address to write data to
* @param data_addr data buffer to write to flash
* @param len data length to write
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_write(uint32_t flash_addr, const uint32_t *data_addr, int len);
/**
* @brief send WREN command
* @note command format would be defined in initialization
* @param arg not used, set to NULL
* @return flash operation result
*/
esp_rom_spiflash_result_t esp_rom_opiflash_wren(void* arg);
/**
* @brief to configure SPI0 read flash command format for cache
* @note command format would be defined in initialization
*
*/
void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const esp_rom_opiflash_spi0rd_t *cache);
esp_rom_spiflash_result_t esp_rom_opiflash_read_raw(uint32_t flash_addr, uint8_t* buf, int len);
#ifdef __cplusplus
}
#endif
#endif
+1 -1
View File
@@ -52,7 +52,7 @@ void bootloader_clock_configure(void)
#endif
}
void esp_rtc_init(void)
void IRAM_ATTR esp_rtc_init(void)
{
#if SOC_PMU_SUPPORTED
pmu_init();
+2
View File
@@ -81,6 +81,8 @@ void cache_hal_init(const cache_hal_config_t *config)
{
s_cache_hal_init_ctx();
cache_ll_clk_init();
if (CACHE_LL_LEVEL_EXT_MEM == 1) {
cache_ll_enable_cache(1, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, ctx.l1.i_autoload_en, ctx.l1.d_autoload_en);
} else if (CACHE_LL_LEVEL_EXT_MEM == 2) {
@@ -53,6 +53,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -52,6 +52,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -43,6 +43,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -1,3 +1,4 @@
/*
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
@@ -42,6 +43,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -42,6 +42,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -42,6 +42,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -43,6 +43,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if Cache auto preload is enabled or not.
*
@@ -43,6 +43,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if L1 ICache autoload is enabled or not
*
@@ -63,6 +63,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/*------------------------------------------------------------------------------
* Autoload
*----------------------------------------------------------------------------*/
@@ -40,6 +40,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if ICache auto preload is enabled or not
*
@@ -55,6 +55,15 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
//for compatibility
}
/**
* @brief Check if ICache auto preload is enabled or not
*
@@ -15,6 +15,7 @@
#include "hal/cache_types.h"
#include "hal/assert.h"
#include "esp32s31/rom/cache.h"
#include "soc/hp_sys_clkrst_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -51,6 +52,18 @@ typedef enum {
CACHE_LL_PRELOAD_ARBITRARY = 2,
} cache_ll_preload_strategy_t;
/**
* @brief Initialize the cache clock
*/
__attribute__((always_inline))
static inline void cache_ll_clk_init(void)
{
HP_SYS_CLKRST.cache_ctrl0.reg_cpu_acache_cpu_clk_force_on = 1;
HP_SYS_CLKRST.cache_ctrl0.reg_rom_acache_mem_clk_force_on = 1;
HP_SYS_CLKRST.cache_ctrl0.reg_cpu_cache_cpu_clk_force_on = 1;
HP_SYS_CLKRST.cache_ctrl0.reg_mspi_cache_sys_clk_force_on = 1;
}
/*------------------------------------------------------------------------------
* Autoload
*----------------------------------------------------------------------------*/
@@ -67,6 +67,10 @@ config SOC_RTC_TIMER_SUPPORTED
bool
default y
config SOC_SPIRAM_SUPPORTED
bool
default y
config SOC_PSRAM_DMA_CAPABLE
bool
default y
@@ -299,6 +303,18 @@ config SOC_SPI_MAXIMUM_BUFFER_SIZE
int
default 64
config SOC_SPIRAM_XIP_SUPPORTED
bool
default y
config SOC_SPI_MEM_SUPPORT_TIMING_TUNING
bool
default y
config SOC_MEMSPI_TIMING_TUNING_BY_DQS
bool
default y
config SOC_MSPI_HAS_INDEPENT_IOMUX
bool
default y
@@ -311,10 +327,6 @@ config SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT
bool
default y
config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT
bool
default y
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
int
default 16
@@ -415,6 +427,10 @@ config SOC_CLK_APLL_SUPPORTED
bool
default y
config SOC_CLK_MPLL_SUPPORTED
bool
default y
config SOC_CLK_RC32K_SUPPORTED
bool
default y
@@ -274,6 +274,23 @@ typedef enum {
SPI_CLK_SRC_DEFAULT = SOC_MOD_CLK_SPLL, /*!< Select XTAL as default source clock */
} soc_periph_spi_clk_src_t;
/////////////////////////////////////////////////PSRAM////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of PSRAM
*/
#define SOC_PSRAM_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_CPLL, SOC_MOD_CLK_MPLL}
/**
* @brief Type of PSRAM clock source.
*/
typedef enum {
PSRAM_CLK_SRC_DEFAULT = SOC_MOD_CLK_MPLL, /*!< Select SOC_MOD_CLK_MPLL as PSRAM source clock */
PSRAM_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select SOC_MOD_CLK_XTAL as PSRAM source clock */
PSRAM_CLK_SRC_CPLL = SOC_MOD_CLK_CPLL, /*!< Select SOC_MOD_CLK_CPLL as PSRAM source clock */
PSRAM_CLK_SRC_MPLL = SOC_MOD_CLK_MPLL, /*!< Select SOC_MOD_CLK_MPLL as PSRAM source clock */
} soc_periph_psram_clk_src_t;
/////////////////////////////////////////////////FLASH////////////////////////////////////////////////////////////////////
/**
@@ -80,7 +80,7 @@
// #define SOC_LP_PERIPHERALS_SUPPORTED 1 // TODO: [ESP32S31] IDF-14785
// #define SOC_LP_I2C_SUPPORTED 1 // TODO: [ESP32S31] IDF-14635
// #define SOC_LP_SPI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14639
// #define SOC_SPIRAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14718
#define SOC_SPIRAM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14718
#define SOC_PSRAM_DMA_CAPABLE 1
// #define SOC_SDMMC_HOST_SUPPORTED 1 // TODO: [ESP32S31] IDF-14705
// #define SOC_CLK_TREE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14733
@@ -217,13 +217,17 @@
#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64
#define SOC_SPI_MAX_BITWIDTH(host_id) ((host_id == 2) ? 4 : 8) // Supported line mode: SPI3: 1, 2, 4, SPI1/2: 1, 2, 4, 8
/*-------------------------- SPIRAM CAPS ----------------------------------------*/
#define SOC_SPIRAM_XIP_SUPPORTED 1
/*-------------------------- SPI MEM CAPS ---------------------------------------*/
#define SOC_SPI_MEM_SUPPORT_TIMING_TUNING (1)
#define SOC_MEMSPI_TIMING_TUNING_BY_DQS (1)
#define SOC_MSPI_HAS_INDEPENT_IOMUX 1
#define SOC_MEMSPI_IS_INDEPENDENT 1
#define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1
#define SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT 1
#define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */
/*-------------------------- SYSTIMER CAPS ----------------------------------*/
@@ -281,6 +285,7 @@
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
#define SOC_CLK_APLL_SUPPORTED (1) /*!< Support Audio PLL */
#define SOC_CLK_MPLL_SUPPORTED (1) /*!< Support MSPI PLL */
#define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */
#define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */
@@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -26,405 +26,89 @@ typedef union {
uint32_t val;
} iomux_mspi_pin_clk_en0_reg_t;
/** Group: psram_d_pin */
/** Type of psram_d_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
/** psram_pin */
typedef union {
struct {
/** reg_psram_d_dli : R/W; bitpos: [3:0]; default: 0;
* psram d dli
/** reg_psram_pin_dli : R/W; bitpos: [3:0]; default: 0;
* psram pin dli
*/
uint32_t reg_psram_d_dli:4;
/** reg_psram_d_dlc : R/W; bitpos: [7:4]; default: 0;
* psram d dlc
uint32_t reg_psram_pin_dli:4;
/** reg_psram_pin_dlc : R/W; bitpos: [7:4]; default: 0;
* psram pin dlc
*/
uint32_t reg_psram_d_dlc:4;
/** reg_psram_d_hys : R/W; bitpos: [8]; default: 0;
* psram d sl
uint32_t reg_psram_pin_dlc:4;
/** reg_psram_pin_hys : R/W; bitpos: [8]; default: 0;
* psram pin hys
*/
uint32_t reg_psram_d_hys:1;
/** reg_psram_d_ie : R/W; bitpos: [9]; default: 0;
uint32_t reg_psram_pin_hys:1;
/** reg_psram_pin_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_d_ie:1;
/** reg_psram_d_wpu : R/W; bitpos: [10]; default: 0;
* psram d wpu
uint32_t reg_psram_pin_ie:1;
/** reg_psram_pin_wpu : R/W; bitpos: [10]; default: 0;
* psram pin wpu
*/
uint32_t reg_psram_d_wpu:1;
/** reg_psram_d_wpd : R/W; bitpos: [11]; default: 0;
* psram d wpd
uint32_t reg_psram_pin_wpu:1;
/** reg_psram_pin_wpd : R/W; bitpos: [11]; default: 0;
* psram pin wpd
*/
uint32_t reg_psram_d_wpd:1;
/** reg_psram_d_drv : R/W; bitpos: [14:12]; default: 4;
* psram d drv
uint32_t reg_psram_pin_wpd:1;
/** reg_psram_pin_drv : R/W; bitpos: [14:12]; default: 4;
* psram pin drv
*/
uint32_t reg_psram_d_drv:3;
/** reg_psram_d_hold : R/W; bitpos: [15]; default: 0;
* psram d hold
uint32_t reg_psram_pin_drv:3;
/** reg_psram_pin_hold : R/W; bitpos: [15]; default: 0;
* psram pin hold
*/
uint32_t reg_psram_d_hold:1;
uint32_t reg_psram_pin_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_d_pin0_reg_t;
} iomux_mspi_pin_psram_pin_reg_t;
/** Group: psram_q_pin */
/** Type of psram_q_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
/** psram_dqs_pin */
typedef union {
struct {
/** reg_psram_q_dli : R/W; bitpos: [3:0]; default: 0;
* psram q dli
/** reg_psram_dqs_xpd : R/W; bitpos: [0]; default: 0;
* psram xpd dqs
*/
uint32_t reg_psram_q_dli:4;
/** reg_psram_q_dlc : R/W; bitpos: [7:4]; default: 0;
* psram q dlc
uint32_t reg_psram_dqs_xpd:1;
/** reg_psram_dqs_phase : R/W; bitpos: [2:1]; default: 0;
* psram dqs phase
*/
uint32_t reg_psram_q_dlc:4;
/** reg_psram_q_hys : R/W; bitpos: [8]; default: 0;
* psram q sl
uint32_t reg_psram_dqs_phase:2;
/** reg_psram_dqs_dli : R/W; bitpos: [6:3]; default: 0;
* psram dqs dli
*/
uint32_t reg_psram_q_hys:1;
/** reg_psram_q_ie : R/W; bitpos: [9]; default: 0;
uint32_t reg_psram_dqs_dli:4;
/** reg_psram_dqs_delay_90 : R/W; bitpos: [10:7]; default: 0;
* psram dqs delay 90
*/
uint32_t reg_psram_dqs_delay_90:4;
/** reg_psram_dqs_hys : R/W; bitpos: [11]; default: 0;
* psram dqs hys
*/
uint32_t reg_psram_dqs_hys:1;
/** reg_psram_dqs_ie : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t reg_psram_q_ie:1;
/** reg_psram_q_wpu : R/W; bitpos: [10]; default: 0;
* psram q wpu
uint32_t reg_psram_dqs_ie:1;
/** reg_psram_dqs_wpu : R/W; bitpos: [13]; default: 0;
* psram dqs wpu
*/
uint32_t reg_psram_q_wpu:1;
/** reg_psram_q_wpd : R/W; bitpos: [11]; default: 0;
* psram q wpd
uint32_t reg_psram_dqs_wpu:1;
/** reg_psram_dqs_wpd : R/W; bitpos: [14]; default: 0;
* psram dqs wpd
*/
uint32_t reg_psram_q_wpd:1;
/** reg_psram_q_drv : R/W; bitpos: [14:12]; default: 4;
* psram q drv
uint32_t reg_psram_dqs_wpd:1;
/** reg_psram_dqs_drv : R/W; bitpos: [17:15]; default: 4;
* psram dqs drv
*/
uint32_t reg_psram_q_drv:3;
/** reg_psram_q_hold : R/W; bitpos: [15]; default: 0;
* psram q hold
uint32_t reg_psram_dqs_drv:3;
/** reg_psram_dqs_delay_270 : R/W; bitpos: [21:18]; default: 0;
* psram dqs delay 270
*/
uint32_t reg_psram_q_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_q_pin0_reg_t;
/** Group: psram_wp_pin */
/** Type of psram_wp_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_wp_dli : R/W; bitpos: [3:0]; default: 0;
* psram wp dli
*/
uint32_t reg_psram_wp_dli:4;
/** reg_psram_wp_dlc : R/W; bitpos: [7:4]; default: 0;
* psram wp dlc
*/
uint32_t reg_psram_wp_dlc:4;
/** reg_psram_wp_hys : R/W; bitpos: [8]; default: 0;
* psram wp sl
*/
uint32_t reg_psram_wp_hys:1;
/** reg_psram_wp_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_wp_ie:1;
/** reg_psram_wp_wpu : R/W; bitpos: [10]; default: 0;
* psram wp wpu
*/
uint32_t reg_psram_wp_wpu:1;
/** reg_psram_wp_wpd : R/W; bitpos: [11]; default: 0;
* psram wp wpd
*/
uint32_t reg_psram_wp_wpd:1;
/** reg_psram_wp_drv : R/W; bitpos: [14:12]; default: 4;
* psram wp drv
*/
uint32_t reg_psram_wp_drv:3;
/** reg_psram_wp_hold : R/W; bitpos: [15]; default: 0;
* psram wp hold
*/
uint32_t reg_psram_wp_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_wp_pin0_reg_t;
/** Group: psram_hold_pin */
/** Type of psram_hold_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_hold_dli : R/W; bitpos: [3:0]; default: 0;
* psram hold dli
*/
uint32_t reg_psram_hold_dli:4;
/** reg_psram_hold_dlc : R/W; bitpos: [7:4]; default: 0;
* psram hold dlc
*/
uint32_t reg_psram_hold_dlc:4;
/** reg_psram_hold_hys : R/W; bitpos: [8]; default: 0;
* psram hold sl
*/
uint32_t reg_psram_hold_hys:1;
/** reg_psram_hold_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_hold_ie:1;
/** reg_psram_hold_wpu : R/W; bitpos: [10]; default: 0;
* psram hold wpu
*/
uint32_t reg_psram_hold_wpu:1;
/** reg_psram_hold_wpd : R/W; bitpos: [11]; default: 0;
* psram hold wpd
*/
uint32_t reg_psram_hold_wpd:1;
/** reg_psram_hold_drv : R/W; bitpos: [14:12]; default: 4;
* psram hold drv
*/
uint32_t reg_psram_hold_drv:3;
/** reg_psram_hold_hold : R/W; bitpos: [15]; default: 0;
* psram hold hold
*/
uint32_t reg_psram_hold_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_hold_pin0_reg_t;
/** Group: psram_dq4_pin */
/** Type of psram_dq4_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq4_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq4 dli
*/
uint32_t reg_psram_dq4_dli:4;
/** reg_psram_dq4_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq4 dlc
*/
uint32_t reg_psram_dq4_dlc:4;
/** reg_psram_dq4_hys : R/W; bitpos: [8]; default: 0;
* psram dq4 sl
*/
uint32_t reg_psram_dq4_hys:1;
/** reg_psram_dq4_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq4_ie:1;
/** reg_psram_dq4_wpu : R/W; bitpos: [10]; default: 0;
* psram dq4 wpu
*/
uint32_t reg_psram_dq4_wpu:1;
/** reg_psram_dq4_wpd : R/W; bitpos: [11]; default: 0;
* psram dq4 wpd
*/
uint32_t reg_psram_dq4_wpd:1;
/** reg_psram_dq4_drv : R/W; bitpos: [14:12]; default: 4;
* psram dq4 drv
*/
uint32_t reg_psram_dq4_drv:3;
/** reg_psram_dq4_hold : R/W; bitpos: [15]; default: 0;
* psram dq4 hold
*/
uint32_t reg_psram_dq4_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_dq4_pin0_reg_t;
/** Group: psram_dq5_pin */
/** Type of psram_dq5_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq5_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq5 dli
*/
uint32_t reg_psram_dq5_dli:4;
/** reg_psram_dq5_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq5 dlc
*/
uint32_t reg_psram_dq5_dlc:4;
/** reg_psram_dq5_hys : R/W; bitpos: [8]; default: 0;
* psram dq5 sl
*/
uint32_t reg_psram_dq5_hys:1;
/** reg_psram_dq5_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq5_ie:1;
/** reg_psram_dq5_wpu : R/W; bitpos: [10]; default: 0;
* psram dq5 wpu
*/
uint32_t reg_psram_dq5_wpu:1;
/** reg_psram_dq5_wpd : R/W; bitpos: [11]; default: 0;
* psram dq5 wpd
*/
uint32_t reg_psram_dq5_wpd:1;
/** reg_psram_dq5_drv : R/W; bitpos: [14:12]; default: 4;
* psram dq5 drv
*/
uint32_t reg_psram_dq5_drv:3;
/** reg_psram_dq5_hold : R/W; bitpos: [15]; default: 0;
* psram dq5 hold
*/
uint32_t reg_psram_dq5_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_dq5_pin0_reg_t;
/** Group: psram_dq6_pin */
/** Type of psram_dq6_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq6_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq6 dli
*/
uint32_t reg_psram_dq6_dli:4;
/** reg_psram_dq6_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq6 dlc
*/
uint32_t reg_psram_dq6_dlc:4;
/** reg_psram_dq6_hys : R/W; bitpos: [8]; default: 0;
* psram dq6 sl
*/
uint32_t reg_psram_dq6_hys:1;
/** reg_psram_dq6_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq6_ie:1;
/** reg_psram_dq6_wpu : R/W; bitpos: [10]; default: 0;
* psram dq6 wpu
*/
uint32_t reg_psram_dq6_wpu:1;
/** reg_psram_dq6_wpd : R/W; bitpos: [11]; default: 0;
* psram dq6 wpd
*/
uint32_t reg_psram_dq6_wpd:1;
/** reg_psram_dq6_drv : R/W; bitpos: [14:12]; default: 4;
* psram dq6 drv
*/
uint32_t reg_psram_dq6_drv:3;
/** reg_psram_dq6_hold : R/W; bitpos: [15]; default: 0;
* psram dq6 hold
*/
uint32_t reg_psram_dq6_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_dq6_pin0_reg_t;
/** Group: psram_dq7_pin */
/** Type of psram_dq7_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq7_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq7 dli
*/
uint32_t reg_psram_dq7_dli:4;
/** reg_psram_dq7_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq7 dlc
*/
uint32_t reg_psram_dq7_dlc:4;
/** reg_psram_dq7_hys : R/W; bitpos: [8]; default: 0;
* psram dq7 sl
*/
uint32_t reg_psram_dq7_hys:1;
/** reg_psram_dq7_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq7_ie:1;
/** reg_psram_dq7_wpu : R/W; bitpos: [10]; default: 0;
* psram dq7 wpu
*/
uint32_t reg_psram_dq7_wpu:1;
/** reg_psram_dq7_wpd : R/W; bitpos: [11]; default: 0;
* psram dq7 wpd
*/
uint32_t reg_psram_dq7_wpd:1;
/** reg_psram_dq7_drv : R/W; bitpos: [14:12]; default: 4;
* psram dq7 drv
*/
uint32_t reg_psram_dq7_drv:3;
/** reg_psram_dq7_hold : R/W; bitpos: [15]; default: 0;
* psram dq7 hold
*/
uint32_t reg_psram_dq7_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_dq7_pin0_reg_t;
/** Group: psram_dqs_0_pin */
/** Type of psram_dqs_0_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dqs_0_xpd : R/W; bitpos: [0]; default: 0;
* psram xpd dqs0
*/
uint32_t reg_psram_dqs_0_xpd:1;
/** reg_psram_dqs_0_phase : R/W; bitpos: [2:1]; default: 0;
* psram dqs0 phase
*/
uint32_t reg_psram_dqs_0_phase:2;
/** reg_psram_dqs_0_dli : R/W; bitpos: [6:3]; default: 0;
* psram dqs0 dli
*/
uint32_t reg_psram_dqs_0_dli:4;
/** reg_psram_dqs_0_delay_90 : R/W; bitpos: [10:7]; default: 0;
* psram dqs0 delay 90
*/
uint32_t reg_psram_dqs_0_delay_90:4;
/** reg_psram_dqs_0_hys : R/W; bitpos: [11]; default: 0;
* psram dqs0 sl
*/
uint32_t reg_psram_dqs_0_hys:1;
/** reg_psram_dqs_0_ie : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t reg_psram_dqs_0_ie:1;
/** reg_psram_dqs_0_wpu : R/W; bitpos: [13]; default: 0;
* psram dqs0 wpu
*/
uint32_t reg_psram_dqs_0_wpu:1;
/** reg_psram_dqs_0_wpd : R/W; bitpos: [14]; default: 0;
* psram dqs0 wpd
*/
uint32_t reg_psram_dqs_0_wpd:1;
/** reg_psram_dqs_0_drv : R/W; bitpos: [17:15]; default: 4;
* psram dqs0 drv
*/
uint32_t reg_psram_dqs_0_drv:3;
/** reg_psram_dqs_0_delay_270 : R/W; bitpos: [21:18]; default: 0;
* psram dqs0 delay 270
*/
uint32_t reg_psram_dqs_0_delay_270:4;
uint32_t reg_psram_dqs_delay_270:4;
/** reg_psram_dqs_hold : R/W; bitpos: [22]; default: 0;
* psram dqs hold
*/
@@ -432,111 +116,20 @@ typedef union {
uint32_t reserved_23:9;
};
uint32_t val;
} iomux_mspi_pin_psram_dqs_0_pin0_reg_t;
/** Group: psram_ck_pin */
/** Type of psram_ck_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_ck_dli : R/W; bitpos: [3:0]; default: 0;
* psram ck dli
*/
uint32_t reg_psram_ck_dli:4;
/** reg_psram_ck_dlc : R/W; bitpos: [7:4]; default: 0;
* psram ck dlc
*/
uint32_t reg_psram_ck_dlc:4;
/** reg_psram_ck_hys : R/W; bitpos: [8]; default: 0;
* psram ck sl
*/
uint32_t reg_psram_ck_hys:1;
/** reg_psram_ck_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_ck_ie:1;
/** reg_psram_ck_wpu : R/W; bitpos: [10]; default: 0;
* psram ck wpu
*/
uint32_t reg_psram_ck_wpu:1;
/** reg_psram_ck_wpd : R/W; bitpos: [11]; default: 0;
* psram ck wpd
*/
uint32_t reg_psram_ck_wpd:1;
/** reg_psram_ck_drv : R/W; bitpos: [14:12]; default: 4;
* psram ck drv
*/
uint32_t reg_psram_ck_drv:3;
/** reg_psram_ck_hold : R/W; bitpos: [15]; default: 0;
* psram ck hold
*/
uint32_t reg_psram_ck_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_ck_pin0_reg_t;
/** Group: psram_cs_pin */
/** Type of psram_cs_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_cs_dli : R/W; bitpos: [3:0]; default: 0;
* psram cs dli
*/
uint32_t reg_psram_cs_dli:4;
/** reg_psram_cs_dlc : R/W; bitpos: [7:4]; default: 0;
* psram cs dlc
*/
uint32_t reg_psram_cs_dlc:4;
/** reg_psram_cs_hys : R/W; bitpos: [8]; default: 0;
* psram cs sl
*/
uint32_t reg_psram_cs_hys:1;
/** reg_psram_cs_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_cs_ie:1;
/** reg_psram_cs_wpu : R/W; bitpos: [10]; default: 0;
* psram cs wpu
*/
uint32_t reg_psram_cs_wpu:1;
/** reg_psram_cs_wpd : R/W; bitpos: [11]; default: 0;
* psram cs wpd
*/
uint32_t reg_psram_cs_wpd:1;
/** reg_psram_cs_drv : R/W; bitpos: [14:12]; default: 4;
* psram cs drv
*/
uint32_t reg_psram_cs_drv:3;
/** reg_psram_cs_hold : R/W; bitpos: [15]; default: 0;
* psram cs hold
*/
uint32_t reg_psram_cs_hold:1;
uint32_t reserved_16:16;
};
uint32_t val;
} iomux_mspi_pin_psram_cs_pin0_reg_t;
} iomux_mspi_pin_psram_dqs_pin_reg_t;
/** psram_pin group */
typedef struct {
volatile iomux_mspi_pin_psram_pin_reg_t pin_group0[8]; // for d, q, wp, hold, dq4, dq5, dq6, dq7
volatile iomux_mspi_pin_psram_dqs_pin_reg_t dqs0;
volatile iomux_mspi_pin_psram_pin_reg_t pin_clk;
volatile iomux_mspi_pin_psram_pin_reg_t pin_cs;
} iomux_mspi_pin_psram_pin_grp_reg_t;
typedef struct {
volatile iomux_mspi_pin_clk_en0_reg_t clk_en0;
uint32_t reserved_004[6];
volatile iomux_mspi_pin_psram_d_pin0_reg_t psram_d_pin0;
volatile iomux_mspi_pin_psram_q_pin0_reg_t psram_q_pin0;
volatile iomux_mspi_pin_psram_wp_pin0_reg_t psram_wp_pin0;
volatile iomux_mspi_pin_psram_hold_pin0_reg_t psram_hold_pin0;
volatile iomux_mspi_pin_psram_dq4_pin0_reg_t psram_dq4_pin0;
volatile iomux_mspi_pin_psram_dq5_pin0_reg_t psram_dq5_pin0;
volatile iomux_mspi_pin_psram_dq6_pin0_reg_t psram_dq6_pin0;
volatile iomux_mspi_pin_psram_dq7_pin0_reg_t psram_dq7_pin0;
volatile iomux_mspi_pin_psram_dqs_0_pin0_reg_t psram_dqs_0_pin0;
volatile iomux_mspi_pin_psram_ck_pin0_reg_t psram_ck_pin0;
volatile iomux_mspi_pin_psram_cs_pin0_reg_t psram_cs_pin0;
volatile iomux_mspi_pin_psram_pin_grp_reg_t psram_pin_group;
} iomux_mspi_pin_dev_t;
extern iomux_mspi_pin_dev_t MSPI_IOMUX;
@@ -81,7 +81,7 @@
#define DR_REG_HP_ALIVE_SYS_BASE 0x20589000
#define DR_REG_HP_PERI1_PMS_BASE 0x2058A000
#define DR_REG_LP_SYS_BASE 0x20700000
#define DR_REG_LP_CLKRST_BASE 0x20701000
#define DR_REG_LP_AONCLKRST_BASE 0x20701000
#define DR_REG_LP_ANA_BASE 0x20702000
#define DR_REG_HUK_BASE 0x20703000
#define DR_REG_PMU_BASE 0x20704000
@@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -121,7 +121,7 @@ typedef union {
uint32_t flash_read:1;
};
uint32_t val;
} spi_mem_cmd_reg_t;
} spi1_mem_c_cmd_reg_t;
/** Type of addr register
* SPI1 address register
@@ -135,7 +135,7 @@ typedef union {
uint32_t usr_addr_value:32;
};
uint32_t val;
} spi_mem_addr_reg_t;
} spi1_mem_c_addr_reg_t;
/** Type of user register
* SPI1 user register.
@@ -203,7 +203,7 @@ typedef union {
uint32_t usr_command:1;
};
uint32_t val;
} spi_mem_user_reg_t;
} spi1_mem_c_user_reg_t;
/** Type of user1 register
* SPI1 user1 register.
@@ -222,7 +222,7 @@ typedef union {
uint32_t usr_addr_bitlen:6;
};
uint32_t val;
} spi_mem_user1_reg_t;
} spi1_mem_c_user1_reg_t;
/** Type of user2 register
* SPI1 user2 register.
@@ -240,7 +240,7 @@ typedef union {
uint32_t usr_command_bitlen:4;
};
uint32_t val;
} spi_mem_user2_reg_t;
} spi1_mem_c_user2_reg_t;
/** Group: Control and configuration registers */
@@ -303,7 +303,7 @@ typedef union {
*/
uint32_t fread_dual:1;
/** resandres : R/W; bitpos: [15]; default: 1;
* The Device ID is read out to SPI_MEM_RD_STATUS register, this bit combine with
* The Device ID is read out to SPI1_MEM_C_RD_STATUS register, this bit combine with
* spi_mem_flash_res bit. 1: enable 0: disable.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
@@ -344,7 +344,7 @@ typedef union {
uint32_t reserved_25:7;
};
uint32_t val;
} spi_mem_ctrl_reg_t;
} spi1_mem_c_ctrl_reg_t;
/** Type of ctrl1 register
* SPI1 control1 register.
@@ -358,19 +358,26 @@ typedef union {
*/
uint32_t clk_mode:2;
/** cs_hold_dly_res : R/W; bitpos: [11:2]; default: 1023;
* After RES/DP/HPM/PES command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] *
* 128) SPI_CLK cycles.
* After RES/DP/HPM command is sent, SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] *
* 512) SPI_CLK cycles.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t cs_hold_dly_res:10;
/** cs_hold_dly_per : R/W; bitpos: [21:12]; default: 1023;
* After PER command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DLY_PER[9:0] * 128) SPI_CLK
* cycles.
/** cs_hold_dly_per : R/W; bitpos: [20:12]; default: 511;
* After PER command is sent, SPI1 waits (SPI1_MEM_C_CS_HOLD_DLY_PER[8:0] * 128)
* SPI_CLK cycles.
*/
uint32_t cs_hold_dly_per:10;
uint32_t reserved_22:10;
uint32_t cs_hold_dly_per:9;
uint32_t reserved_21:2;
/** cs_hold_dly_per_en : R/W; bitpos: [23]; default: 0;
* 1: use SPI1_MEM_C_CS_HOLD_DLY_PER for per, use SPI1_MEM_C_CS_HOLD_DELAY_RES for
* pes/dp/hpm . 0: use SPI1_MEM_C_CS_HOLD_DELAY_RES for pes/dp/hpm/per .
*/
uint32_t cs_hold_dly_per_en:1;
uint32_t reserved_24:8;
};
uint32_t val;
} spi_mem_ctrl1_reg_t;
} spi1_mem_c_ctrl1_reg_t;
/** Type of ctrl2 register
* SPI1 control2 register.
@@ -384,7 +391,7 @@ typedef union {
uint32_t sync_reset:1;
};
uint32_t val;
} spi_mem_ctrl2_reg_t;
} spi1_mem_c_ctrl2_reg_t;
/** Type of clock register
* SPI1 clock division control register.
@@ -392,16 +399,16 @@ typedef union {
typedef union {
struct {
/** clkcnt_l : R/W; bitpos: [7:0]; default: 3;
* In the master mode it must be equal to SPI_MEM_CLKCNT_N.
* In the master mode it must be equal to SPI1_MEM_C_CLKCNT_N.
*/
uint32_t clkcnt_l:8;
/** clkcnt_h : R/W; bitpos: [15:8]; default: 1;
* In the master mode it must be floor((SPI_MEM_CLKCNT_N+1)/2-1).
* In the master mode it must be floor((SPI1_MEM_C_CLKCNT_N+1)/2-1).
*/
uint32_t clkcnt_h:8;
/** clkcnt_n : R/W; bitpos: [23:16]; default: 3;
* In the master mode it is the divider of spi_mem_clk. So spi_mem_clk frequency is
* system/(SPI_MEM_CLKCNT_N+1)
* system/(SPI1_MEM_C_CLKCNT_N+1)
*/
uint32_t clkcnt_n:8;
uint32_t reserved_24:7;
@@ -411,7 +418,7 @@ typedef union {
uint32_t clk_equ_sysclk:1;
};
uint32_t val;
} spi_mem_clock_reg_t;
} spi1_mem_c_clock_reg_t;
/** Type of mosi_dlen register
* SPI1 send data bit length control register.
@@ -425,7 +432,7 @@ typedef union {
uint32_t reserved_10:22;
};
uint32_t val;
} spi_mem_mosi_dlen_reg_t;
} spi1_mem_c_mosi_dlen_reg_t;
/** Type of miso_dlen register
* SPI1 receive data bit length control register.
@@ -439,7 +446,7 @@ typedef union {
uint32_t reserved_10:22;
};
uint32_t val;
} spi_mem_miso_dlen_reg_t;
} spi1_mem_c_miso_dlen_reg_t;
/** Type of rd_status register
* SPI1 status register.
@@ -455,20 +462,10 @@ typedef union {
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode:8;
/** wb_mode_bitlen : R/W; bitpos: [26:24]; default: 0;
* Mode bits length for flash fast read mode.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode_bitlen:3;
/** wb_mode_en : R/W; bitpos: [27]; default: 0;
* Mode bits is valid while this bit is enable. 1: enable 0: disable.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode_en:1;
uint32_t reserved_28:4;
uint32_t reserved_24:8;
};
uint32_t val;
} spi_mem_rd_status_reg_t;
} spi1_mem_c_rd_status_reg_t;
/** Type of misc register
* SPI1 misc register
@@ -497,7 +494,7 @@ typedef union {
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_misc_reg_t;
} spi1_mem_c_misc_reg_t;
/** Type of cache_fctrl register
* SPI1 bit mode control register.
@@ -550,7 +547,7 @@ typedef union {
uint32_t reserved_9:23;
};
uint32_t val;
} spi_mem_cache_fctrl_reg_t;
} spi1_mem_c_cache_fctrl_reg_t;
/** Type of flash_waiti_ctrl register
* SPI1 wait idle control register
@@ -573,9 +570,9 @@ typedef union {
*/
uint32_t waiti_addr_en:1;
/** waiti_addr_cyclelen : R/W; bitpos: [4:3]; default: 0;
* When SPI_MEM_WAITI_ADDR_EN is set, the cycle length of sent out address is
* (SPI_MEM_WAITI_ADDR_CYCLELEN[1:0] + 1) SPI bus clock cycles. It is not active when
* SPI_MEM_WAITI_ADDR_EN is cleared.
* When SPI1_MEM_C_WAITI_ADDR_EN is set, the cycle length of sent out address is
* (SPI1_MEM_C_WAITI_ADDR_CYCLELEN[1:0] + 1) SPI bus clock cycles. It is not active
* when SPI1_MEM_C_WAITI_ADDR_EN is cleared.
*/
uint32_t waiti_addr_cyclelen:2;
uint32_t reserved_5:4;
@@ -593,7 +590,7 @@ typedef union {
uint32_t waiti_cmd:16;
};
uint32_t val;
} spi_mem_flash_waiti_ctrl_reg_t;
} spi1_mem_c_flash_waiti_ctrl_reg_t;
/** Type of flash_sus_ctrl register
* SPI1 flash suspend control register
@@ -613,13 +610,13 @@ typedef union {
*/
uint32_t flash_pes:1;
/** flash_per_wait_en : R/W; bitpos: [2]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* 1: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* program erase resume command is sent. 0: SPI1 does not wait after program erase
* resume command is sent.
*/
uint32_t flash_per_wait_en:1;
/** flash_pes_wait_en : R/W; bitpos: [3]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* 1: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* program erase suspend command is sent. 0: SPI1 does not wait after program erase
* suspend command is sent.
*/
@@ -637,7 +634,7 @@ typedef union {
* The mask value when check SUS/SUS1/SUS2 status bit. If the read status value is
* status_in[15:0](only status_in[7:0] is valid when only one byte of data is read
* out, status_in[15:0] is valid when two bytes of data are read out), SUS/SUS1/SUS2 =
* status_in[15:0]^ SPI_MEM_PESR_END_MSK[15:0].
* status_in[15:0]^ SPI1_MEM_C_PESR_END_MSK[15:0].
*/
uint32_t pesr_end_msk:16;
/** fmem_rd_sus_2b : R/W; bitpos: [22]; default: 0;
@@ -656,13 +653,13 @@ typedef union {
*/
uint32_t pes_end_en:1;
/** sus_timeout_cnt : R/W; bitpos: [31:25]; default: 4;
* When SPI1 checks SUS/SUS1/SUS2 bits fail for SPI_MEM_SUS_TIMEOUT_CNT[6:0] times, it
* will be treated as check pass.
* When SPI1 checks SUS/SUS1/SUS2 bits fail for SPI1_MEM_C_SUS_TIMEOUT_CNT[6:0] times,
* it will be treated as check pass.
*/
uint32_t sus_timeout_cnt:7;
};
uint32_t val;
} spi_mem_flash_sus_ctrl_reg_t;
} spi1_mem_c_flash_sus_ctrl_reg_t;
/** Type of flash_sus_cmd register
* SPI1 flash suspend command register
@@ -680,7 +677,7 @@ typedef union {
uint32_t wait_pesr_command:16;
};
uint32_t val;
} spi_mem_flash_sus_cmd_reg_t;
} spi1_mem_c_flash_sus_cmd_reg_t;
/** Type of sus_status register
* SPI1 flash suspend status register
@@ -692,40 +689,40 @@ typedef union {
*/
uint32_t flash_sus:1;
/** wait_pesr_cmd_2b : R/W; bitpos: [1]; default: 0;
* 1: SPI1 sends out SPI_MEM_WAIT_PESR_COMMAND[15:0] to check SUS/SUS1/SUS2 bit. 0:
* SPI1 sends out SPI_MEM_WAIT_PESR_COMMAND[7:0] to check SUS/SUS1/SUS2 bit.
* 1: SPI1 sends out SPI1_MEM_C_WAIT_PESR_COMMAND[15:0] to check SUS/SUS1/SUS2 bit. 0:
* SPI1 sends out SPI1_MEM_C_WAIT_PESR_COMMAND[7:0] to check SUS/SUS1/SUS2 bit.
*/
uint32_t wait_pesr_cmd_2b:1;
/** flash_hpm_dly_128 : R/W; bitpos: [2]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after HPM
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after HPM command is sent.
* 1: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after HPM
* command is sent. 0: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after HPM command is sent.
*/
uint32_t flash_hpm_dly_128:1;
/** flash_res_dly_128 : R/W; bitpos: [3]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after RES
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after RES command is sent.
* 1: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after RES
* command is sent. 0: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after RES command is sent.
*/
uint32_t flash_res_dly_128:1;
/** flash_dp_dly_128 : R/W; bitpos: [4]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after DP
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after DP command is sent.
* 1: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after DP
* command is sent. 0: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after DP command is sent.
*/
uint32_t flash_dp_dly_128:1;
/** flash_per_dly_128 : R/W; bitpos: [5]; default: 0;
* Valid when SPI_MEM_FLASH_PER_WAIT_EN is 1. 1: SPI1 waits
* (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PER command is sent. 0:
* SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PER command is
* sent.
* Valid when SPI1_MEM_C_FLASH_PER_WAIT_EN is 1. 1: SPI1 waits
* (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PER command is sent.
* 0: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PER
* command is sent.
*/
uint32_t flash_per_dly_128:1;
/** flash_pes_dly_128 : R/W; bitpos: [6]; default: 0;
* Valid when SPI_MEM_FLASH_PES_WAIT_EN is 1. 1: SPI1 waits
* (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PES command is sent. 0:
* SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PES command is
* sent.
* Valid when SPI1_MEM_C_FLASH_PES_WAIT_EN is 1. 1: SPI1 waits
* (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PES command is sent.
* 0: SPI1 waits (SPI1_MEM_C_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PES
* command is sent.
*/
uint32_t flash_pes_dly_128:1;
/** spi0_lock_en : R/W; bitpos: [7]; default: 0;
@@ -744,25 +741,7 @@ typedef union {
uint32_t flash_per_command:16;
};
uint32_t val;
} spi_mem_sus_status_reg_t;
/** Type of flash_waiti_ctrl1 register
* SPI1 wait idle control register
*/
typedef union {
struct {
/** waiti_idle_delay_time : R/W; bitpos: [9:0]; default: 0;
* SPI1 wait idle gap time configuration. SPI1 slv fsm will count during SPI1 IDLE.
*/
uint32_t waiti_idle_delay_time:10;
/** waiti_idle_delay_time_en : R/W; bitpos: [10]; default: 0;
* Enable SPI1 wait idle gap time count function. 1: Enable. 0: Disable.
*/
uint32_t waiti_idle_delay_time_en:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_flash_waiti_ctrl1_reg_t;
} spi1_mem_c_sus_status_reg_t;
/** Type of ddr register
* SPI1 DDR control register
@@ -800,8 +779,8 @@ typedef union {
uint32_t fmem_usr_ddr_dqs_thd:7;
/** fmem_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_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
* spi0_slv_st is in SPI1_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 fmem_ddr_dqs_loop:1;
@@ -837,7 +816,7 @@ typedef union {
uint32_t reserved_31:1;
};
uint32_t val;
} spi_mem_ddr_reg_t;
} spi1_mem_c_ddr_reg_t;
/** Type of clock_gate register
* SPI1 clk_gate register
@@ -851,7 +830,7 @@ typedef union {
uint32_t reserved_1:31;
};
uint32_t val;
} spi_mem_clock_gate_reg_t;
} spi1_mem_c_clock_gate_reg_t;
/** Group: Status register */
@@ -867,7 +846,8 @@ typedef union {
uint32_t tx_crc_data:32;
};
uint32_t val;
} spi_mem_tx_crc_reg_t;
} spi1_mem_c_tx_crc_reg_t;
/** Group: Interrupt registers */
/** Type of int_ena register
@@ -876,34 +856,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_ena : R/W; bitpos: [0]; default: 0;
* The enable bit for SPI_MEM_PER_END_INT interrupt.
* The enable bit for SPI1_MEM_C_PER_END_INT interrupt.
*/
uint32_t per_end_int_ena:1;
/** pes_end_int_ena : R/W; bitpos: [1]; default: 0;
* The enable bit for SPI_MEM_PES_END_INT interrupt.
* The enable bit for SPI1_MEM_C_PES_END_INT interrupt.
*/
uint32_t pes_end_int_ena:1;
/** wpe_end_int_ena : R/W; bitpos: [2]; default: 0;
* The enable bit for SPI_MEM_WPE_END_INT interrupt.
* The enable bit for SPI1_MEM_C_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_ena:1;
/** slv_st_end_int_ena : R/W; bitpos: [3]; default: 0;
* The enable bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The enable bit for SPI1_MEM_C_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_ena:1;
/** mst_st_end_int_ena : R/W; bitpos: [4]; default: 0;
* The enable bit for SPI_MEM_MST_ST_END_INT interrupt.
* The enable bit for SPI1_MEM_C_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_ena:1;
uint32_t reserved_5:5;
/** brown_out_int_ena : R/W; bitpos: [10]; default: 0;
* The enable bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The enable bit for SPI1_MEM_C_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_ena:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_ena_reg_t;
} spi1_mem_c_int_ena_reg_t;
/** Type of int_clr register
* SPI1 interrupt clear register
@@ -911,34 +891,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_clr : WT; bitpos: [0]; default: 0;
* The clear bit for SPI_MEM_PER_END_INT interrupt.
* The clear bit for SPI1_MEM_C_PER_END_INT interrupt.
*/
uint32_t per_end_int_clr:1;
/** pes_end_int_clr : WT; bitpos: [1]; default: 0;
* The clear bit for SPI_MEM_PES_END_INT interrupt.
* The clear bit for SPI1_MEM_C_PES_END_INT interrupt.
*/
uint32_t pes_end_int_clr:1;
/** wpe_end_int_clr : WT; bitpos: [2]; default: 0;
* The clear bit for SPI_MEM_WPE_END_INT interrupt.
* The clear bit for SPI1_MEM_C_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_clr:1;
/** slv_st_end_int_clr : WT; bitpos: [3]; default: 0;
* The clear bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The clear bit for SPI1_MEM_C_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_clr:1;
/** mst_st_end_int_clr : WT; bitpos: [4]; default: 0;
* The clear bit for SPI_MEM_MST_ST_END_INT interrupt.
* The clear bit for SPI1_MEM_C_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_clr:1;
uint32_t reserved_5:5;
/** brown_out_int_clr : WT; bitpos: [10]; default: 0;
* The status bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The status bit for SPI1_MEM_C_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_clr:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_clr_reg_t;
} spi1_mem_c_int_clr_reg_t;
/** Type of int_raw register
* SPI1 interrupt raw register
@@ -946,34 +926,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_raw : R/WTC/SS; bitpos: [0]; default: 0;
* The raw bit for SPI_MEM_PER_END_INT interrupt. 1: Triggered when Auto Resume
* The raw bit for SPI1_MEM_C_PER_END_INT interrupt. 1: Triggered when Auto Resume
* command (0x7A) is sent and flash is resumed successfully. 0: Others.
*/
uint32_t per_end_int_raw:1;
/** pes_end_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
* The raw bit for SPI_MEM_PES_END_INT interrupt.1: Triggered when Auto Suspend
* The raw bit for SPI1_MEM_C_PES_END_INT interrupt.1: Triggered when Auto Suspend
* command (0x75) is sent and flash is suspended successfully. 0: Others.
*/
uint32_t pes_end_int_raw:1;
/** wpe_end_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
* The raw bit for SPI_MEM_WPE_END_INT interrupt. 1: Triggered when WRSR/PP/SE/BE/CE
* is sent and flash is already idle. 0: Others.
* The raw bit for SPI1_MEM_C_WPE_END_INT interrupt. 1: Triggered when
* WRSR/PP/SE/BE/CE is sent and flash is already idle. 0: Others.
*/
uint32_t wpe_end_int_raw:1;
/** slv_st_end_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
* The raw bit for SPI_MEM_SLV_ST_END_INT interrupt. 1: Triggered when spi1_slv_st is
* changed from non idle state to idle state. It means that SPI_CS raises high. 0:
* The raw bit for SPI1_MEM_C_SLV_ST_END_INT interrupt. 1: Triggered when spi1_slv_st
* is changed from non idle state to idle state. It means that SPI_CS raises high. 0:
* Others
*/
uint32_t slv_st_end_int_raw:1;
/** mst_st_end_int_raw : R/WTC/SS; bitpos: [4]; default: 0;
* The raw bit for SPI_MEM_MST_ST_END_INT interrupt. 1: Triggered when spi1_mst_st is
* changed from non idle state to idle state. 0: Others.
* The raw bit for SPI1_MEM_C_MST_ST_END_INT interrupt. 1: Triggered when spi1_mst_st
* is changed from non idle state to idle state. 0: Others.
*/
uint32_t mst_st_end_int_raw:1;
uint32_t reserved_5:5;
/** brown_out_int_raw : R/WTC/SS; bitpos: [10]; default: 0;
* The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that
* The raw bit for SPI1_MEM_C_BROWN_OUT_INT interrupt. 1: Triggered condition is that
* chip is losing power and RTC module sends out brown out close flash request to
* SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered
* and MSPI returns to idle state. 0: Others.
@@ -982,7 +962,7 @@ typedef union {
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_raw_reg_t;
} spi1_mem_c_int_raw_reg_t;
/** Type of int_st register
* SPI1 interrupt status register
@@ -990,34 +970,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_st : RO; bitpos: [0]; default: 0;
* The status bit for SPI_MEM_PER_END_INT interrupt.
* The status bit for SPI1_MEM_C_PER_END_INT interrupt.
*/
uint32_t per_end_int_st:1;
/** pes_end_int_st : RO; bitpos: [1]; default: 0;
* The status bit for SPI_MEM_PES_END_INT interrupt.
* The status bit for SPI1_MEM_C_PES_END_INT interrupt.
*/
uint32_t pes_end_int_st:1;
/** wpe_end_int_st : RO; bitpos: [2]; default: 0;
* The status bit for SPI_MEM_WPE_END_INT interrupt.
* The status bit for SPI1_MEM_C_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_st:1;
/** slv_st_end_int_st : RO; bitpos: [3]; default: 0;
* The status bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The status bit for SPI1_MEM_C_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_st:1;
/** mst_st_end_int_st : RO; bitpos: [4]; default: 0;
* The status bit for SPI_MEM_MST_ST_END_INT interrupt.
* The status bit for SPI1_MEM_C_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_st:1;
uint32_t reserved_5:5;
/** brown_out_int_st : RO; bitpos: [10]; default: 0;
* The status bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The status bit for SPI1_MEM_C_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_st:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_st_reg_t;
} spi1_mem_c_int_st_reg_t;
/** Group: Timing registers */
@@ -1038,7 +1018,7 @@ typedef union {
uint32_t reserved_5:27;
};
uint32_t val;
} spi_mem_timing_cali_reg_t;
} spi1_mem_c_timing_cali_reg_t;
/** Group: Version register */
@@ -1047,57 +1027,54 @@ typedef union {
*/
typedef union {
struct {
/** date : R/W; bitpos: [27:0]; default: 37786176;
/** date : R/W; bitpos: [27:0]; default: 38801712;
* Version control register
*/
uint32_t date:28;
uint32_t reserved_28:4;
};
uint32_t val;
} spi_mem_date_reg_t;
} spi1_mem_c_date_reg_t;
typedef struct spi1_mem_c_dev_s {
volatile spi_mem_cmd_reg_t cmd;
volatile spi1_mem_c_cmd_reg_t cmd;
volatile uint32_t addr;
volatile spi_mem_ctrl_reg_t ctrl;
volatile spi_mem_ctrl1_reg_t ctrl1;
volatile spi_mem_ctrl2_reg_t ctrl2;
volatile spi_mem_clock_reg_t clock;
volatile spi_mem_user_reg_t user;
volatile spi_mem_user1_reg_t user1;
volatile spi_mem_user2_reg_t user2;
volatile spi_mem_mosi_dlen_reg_t mosi_dlen;
volatile spi_mem_miso_dlen_reg_t miso_dlen;
volatile spi_mem_rd_status_reg_t rd_status;
volatile spi1_mem_c_ctrl_reg_t ctrl;
volatile spi1_mem_c_ctrl1_reg_t ctrl1;
volatile spi1_mem_c_ctrl2_reg_t ctrl2;
volatile spi1_mem_c_clock_reg_t clock;
volatile spi1_mem_c_user_reg_t user;
volatile spi1_mem_c_user1_reg_t user1;
volatile spi1_mem_c_user2_reg_t user2;
volatile spi1_mem_c_mosi_dlen_reg_t mosi_dlen;
volatile spi1_mem_c_miso_dlen_reg_t miso_dlen;
volatile spi1_mem_c_rd_status_reg_t rd_status;
uint32_t reserved_030;
volatile spi_mem_misc_reg_t misc;
volatile spi_mem_tx_crc_reg_t tx_crc;
volatile spi_mem_cache_fctrl_reg_t cache_fctrl;
volatile spi1_mem_c_misc_reg_t misc;
volatile spi1_mem_c_tx_crc_reg_t tx_crc;
volatile spi1_mem_c_cache_fctrl_reg_t cache_fctrl;
uint32_t reserved_040[6];
volatile uint32_t data_buf[16];
volatile spi_mem_flash_waiti_ctrl_reg_t flash_waiti_ctrl;
volatile spi_mem_flash_sus_ctrl_reg_t flash_sus_ctrl;
volatile spi_mem_flash_sus_cmd_reg_t flash_sus_cmd;
volatile spi_mem_sus_status_reg_t sus_status;
uint32_t reserved_0a8;
volatile spi_mem_flash_waiti_ctrl1_reg_t flash_waiti_ctrl1;
uint32_t reserved_0b0[4];
volatile spi_mem_int_ena_reg_t int_ena;
volatile spi_mem_int_clr_reg_t int_clr;
volatile spi_mem_int_raw_reg_t int_raw;
volatile spi_mem_int_st_reg_t int_st;
volatile spi1_mem_c_flash_waiti_ctrl_reg_t flash_waiti_ctrl;
volatile spi1_mem_c_flash_sus_ctrl_reg_t flash_sus_ctrl;
volatile spi1_mem_c_flash_sus_cmd_reg_t flash_sus_cmd;
volatile spi1_mem_c_sus_status_reg_t sus_status;
uint32_t reserved_0a8[6];
volatile spi1_mem_c_int_ena_reg_t int_ena;
volatile spi1_mem_c_int_clr_reg_t int_clr;
volatile spi1_mem_c_int_raw_reg_t int_raw;
volatile spi1_mem_c_int_st_reg_t int_st;
uint32_t reserved_0d0;
volatile spi_mem_ddr_reg_t ddr;
volatile spi1_mem_c_ddr_reg_t ddr;
uint32_t reserved_0d8[42];
volatile spi_mem_timing_cali_reg_t timing_cali;
volatile spi1_mem_c_timing_cali_reg_t timing_cali;
uint32_t reserved_184[31];
volatile spi_mem_clock_gate_reg_t clock_gate;
volatile spi1_mem_c_clock_gate_reg_t clock_gate;
uint32_t reserved_204[126];
volatile spi_mem_date_reg_t date;
volatile spi1_mem_c_date_reg_t date;
} spi1_mem_c_dev_t;
#ifndef __cplusplus
_Static_assert(sizeof(spi1_mem_c_dev_t) == 0x400, "Invalid size of spi1_mem_c_dev_t structure");
#endif
@@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -121,7 +121,7 @@ typedef union {
uint32_t flash_read:1;
};
uint32_t val;
} spi_mem_cmd_reg_t;
} spi1_mem_s_cmd_reg_t;
/** Type of addr register
* SPI1 address register
@@ -135,7 +135,7 @@ typedef union {
uint32_t usr_addr_value:32;
};
uint32_t val;
} spi_mem_addr_reg_t;
} spi1_mem_s_addr_reg_t;
/** Type of user register
* SPI1 user register.
@@ -201,7 +201,7 @@ typedef union {
uint32_t usr_command:1;
};
uint32_t val;
} spi_mem_user_reg_t;
} spi1_mem_s_user_reg_t;
/** Type of user1 register
* SPI1 user1 register.
@@ -220,7 +220,7 @@ typedef union {
uint32_t usr_addr_bitlen:6;
};
uint32_t val;
} spi_mem_user1_reg_t;
} spi1_mem_s_user1_reg_t;
/** Type of user2 register
* SPI1 user2 register.
@@ -238,7 +238,7 @@ typedef union {
uint32_t usr_command_bitlen:4;
};
uint32_t val;
} spi_mem_user2_reg_t;
} spi1_mem_s_user2_reg_t;
/** Group: Control and configuration registers */
@@ -301,7 +301,7 @@ typedef union {
*/
uint32_t fread_dual:1;
/** resandres : R/W; bitpos: [15]; default: 1;
* The Device ID is read out to SPI_MEM_RD_STATUS register, this bit combine with
* The Device ID is read out to SPI1_MEM_S_RD_STATUS register, this bit combine with
* spi_mem_flash_res bit. 1: enable 0: disable.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
@@ -342,7 +342,7 @@ typedef union {
uint32_t reserved_25:7;
};
uint32_t val;
} spi_mem_ctrl_reg_t;
} spi1_mem_s_ctrl_reg_t;
/** Type of ctrl1 register
* SPI1 control1 register.
@@ -356,19 +356,26 @@ typedef union {
*/
uint32_t clk_mode:2;
/** cs_hold_dly_res : R/W; bitpos: [11:2]; default: 1023;
* After RES/DP/HPM/PES command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] *
* 128) SPI_CLK cycles.
* After RES/DP/HPM command is sent, SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] *
* 512) SPI_CLK cycles.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t cs_hold_dly_res:10;
/** cs_hold_dly_per : R/W; bitpos: [21:12]; default: 1023;
* After PER command is sent, SPI1 waits (SPI_MEM_CS_HOLD_DLY_PER[9:0] * 128) SPI_CLK
* cycles.
/** cs_hold_dly_per : R/W; bitpos: [20:12]; default: 511;
* After PER command is sent, SPI1 waits (SPI1_MEM_S_CS_HOLD_DLY_PER[8:0] * 128)
* SPI_CLK cycles.
*/
uint32_t cs_hold_dly_per:10;
uint32_t reserved_22:10;
uint32_t cs_hold_dly_per:9;
uint32_t reserved_21:2;
/** cs_hold_dly_per_en : R/W; bitpos: [23]; default: 0;
* 1: use SPI1_MEM_S_CS_HOLD_DLY_PER for per, use SPI1_MEM_S_CS_HOLD_DELAY_RES for
* pes/dp/hpm . 0: use SPI1_MEM_S_CS_HOLD_DELAY_RES for pes/dp/hpm/per .
*/
uint32_t cs_hold_dly_per_en:1;
uint32_t reserved_24:8;
};
uint32_t val;
} spi_mem_ctrl1_reg_t;
} spi1_mem_s_ctrl1_reg_t;
/** Type of ctrl2 register
* SPI1 control2 register.
@@ -382,7 +389,7 @@ typedef union {
uint32_t sync_reset:1;
};
uint32_t val;
} spi_mem_ctrl2_reg_t;
} spi1_mem_s_ctrl2_reg_t;
/** Type of clock register
* SPI1 clock division control register.
@@ -390,16 +397,16 @@ typedef union {
typedef union {
struct {
/** clkcnt_l : R/W; bitpos: [7:0]; default: 3;
* In the master mode it must be equal to SPI_MEM_CLKCNT_N.
* In the master mode it must be equal to SPI1_MEM_S_CLKCNT_N.
*/
uint32_t clkcnt_l:8;
/** clkcnt_h : R/W; bitpos: [15:8]; default: 1;
* In the master mode it must be floor((SPI_MEM_CLKCNT_N+1)/2-1).
* In the master mode it must be floor((SPI1_MEM_S_CLKCNT_N+1)/2-1).
*/
uint32_t clkcnt_h:8;
/** clkcnt_n : R/W; bitpos: [23:16]; default: 3;
* In the master mode it is the divider of spi_mem_clk. So spi_mem_clk frequency is
* system/(SPI_MEM_CLKCNT_N+1)
* system/(SPI1_MEM_S_CLKCNT_N+1)
*/
uint32_t clkcnt_n:8;
uint32_t reserved_24:7;
@@ -409,7 +416,7 @@ typedef union {
uint32_t clk_equ_sysclk:1;
};
uint32_t val;
} spi_mem_clock_reg_t;
} spi1_mem_s_clock_reg_t;
/** Type of mosi_dlen register
* SPI1 send data bit length control register.
@@ -423,7 +430,7 @@ typedef union {
uint32_t reserved_10:22;
};
uint32_t val;
} spi_mem_mosi_dlen_reg_t;
} spi1_mem_s_mosi_dlen_reg_t;
/** Type of miso_dlen register
* SPI1 receive data bit length control register.
@@ -437,7 +444,7 @@ typedef union {
uint32_t reserved_10:22;
};
uint32_t val;
} spi_mem_miso_dlen_reg_t;
} spi1_mem_s_miso_dlen_reg_t;
/** Type of rd_status register
* SPI1 status register.
@@ -453,20 +460,10 @@ typedef union {
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode:8;
/** wb_mode_bitlen : R/W; bitpos: [26:24]; default: 0;
* Mode bits length for flash fast read mode.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode_bitlen:3;
/** wb_mode_en : R/W; bitpos: [27]; default: 0;
* Mode bits is valid while this bit is enable. 1: enable 0: disable.
* This field is only for internal debugging purposes. Do not use it in applications.
*/
uint32_t wb_mode_en:1;
uint32_t reserved_28:4;
uint32_t reserved_24:8;
};
uint32_t val;
} spi_mem_rd_status_reg_t;
} spi1_mem_s_rd_status_reg_t;
/** Type of misc register
* SPI1 misc register
@@ -495,7 +492,7 @@ typedef union {
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_misc_reg_t;
} spi1_mem_s_misc_reg_t;
/** Type of cache_fctrl register
* SPI1 bit mode control register.
@@ -548,7 +545,7 @@ typedef union {
uint32_t reserved_9:23;
};
uint32_t val;
} spi_mem_cache_fctrl_reg_t;
} spi1_mem_s_cache_fctrl_reg_t;
/** Type of flash_waiti_ctrl register
* SPI1 wait idle control register
@@ -571,9 +568,9 @@ typedef union {
*/
uint32_t waiti_addr_en:1;
/** waiti_addr_cyclelen : R/W; bitpos: [4:3]; default: 0;
* When SPI_MEM_WAITI_ADDR_EN is set, the cycle length of sent out address is
* (SPI_MEM_WAITI_ADDR_CYCLELEN[1:0] + 1) SPI bus clock cycles. It is not active when
* SPI_MEM_WAITI_ADDR_EN is cleared.
* When SPI1_MEM_S_WAITI_ADDR_EN is set, the cycle length of sent out address is
* (SPI1_MEM_S_WAITI_ADDR_CYCLELEN[1:0] + 1) SPI bus clock cycles. It is not active
* when SPI1_MEM_S_WAITI_ADDR_EN is cleared.
*/
uint32_t waiti_addr_cyclelen:2;
uint32_t reserved_5:4;
@@ -591,7 +588,7 @@ typedef union {
uint32_t waiti_cmd:16;
};
uint32_t val;
} spi_mem_flash_waiti_ctrl_reg_t;
} spi1_mem_s_flash_waiti_ctrl_reg_t;
/** Type of flash_sus_ctrl register
* SPI1 flash suspend control register
@@ -611,13 +608,13 @@ typedef union {
*/
uint32_t flash_pes:1;
/** flash_per_wait_en : R/W; bitpos: [2]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* 1: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* program erase resume command is sent. 0: SPI1 does not wait after program erase
* resume command is sent.
*/
uint32_t flash_per_wait_en:1;
/** flash_pes_wait_en : R/W; bitpos: [3]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* 1: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4 or *128) SPI_CLK cycles after
* program erase suspend command is sent. 0: SPI1 does not wait after program erase
* suspend command is sent.
*/
@@ -635,7 +632,7 @@ typedef union {
* The mask value when check SUS/SUS1/SUS2 status bit. If the read status value is
* status_in[15:0](only status_in[7:0] is valid when only one byte of data is read
* out, status_in[15:0] is valid when two bytes of data are read out), SUS/SUS1/SUS2 =
* status_in[15:0]^ SPI_MEM_PESR_END_MSK[15:0].
* status_in[15:0]^ SPI1_MEM_S_PESR_END_MSK[15:0].
*/
uint32_t pesr_end_msk:16;
/** fmem_rd_sus_2b : R/W; bitpos: [22]; default: 0;
@@ -654,13 +651,13 @@ typedef union {
*/
uint32_t pes_end_en:1;
/** sus_timeout_cnt : R/W; bitpos: [31:25]; default: 4;
* When SPI1 checks SUS/SUS1/SUS2 bits fail for SPI_MEM_SUS_TIMEOUT_CNT[6:0] times, it
* will be treated as check pass.
* When SPI1 checks SUS/SUS1/SUS2 bits fail for SPI1_MEM_S_SUS_TIMEOUT_CNT[6:0] times,
* it will be treated as check pass.
*/
uint32_t sus_timeout_cnt:7;
};
uint32_t val;
} spi_mem_flash_sus_ctrl_reg_t;
} spi1_mem_s_flash_sus_ctrl_reg_t;
/** Type of flash_sus_cmd register
* SPI1 flash suspend command register
@@ -678,7 +675,7 @@ typedef union {
uint32_t wait_pesr_command:16;
};
uint32_t val;
} spi_mem_flash_sus_cmd_reg_t;
} spi1_mem_s_flash_sus_cmd_reg_t;
/** Type of sus_status register
* SPI1 flash suspend status register
@@ -690,40 +687,40 @@ typedef union {
*/
uint32_t flash_sus:1;
/** wait_pesr_cmd_2b : R/W; bitpos: [1]; default: 0;
* 1: SPI1 sends out SPI_MEM_WAIT_PESR_COMMAND[15:0] to check SUS/SUS1/SUS2 bit. 0:
* SPI1 sends out SPI_MEM_WAIT_PESR_COMMAND[7:0] to check SUS/SUS1/SUS2 bit.
* 1: SPI1 sends out SPI1_MEM_S_WAIT_PESR_COMMAND[15:0] to check SUS/SUS1/SUS2 bit. 0:
* SPI1 sends out SPI1_MEM_S_WAIT_PESR_COMMAND[7:0] to check SUS/SUS1/SUS2 bit.
*/
uint32_t wait_pesr_cmd_2b:1;
/** flash_hpm_dly_128 : R/W; bitpos: [2]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after HPM
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after HPM command is sent.
* 1: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after HPM
* command is sent. 0: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after HPM command is sent.
*/
uint32_t flash_hpm_dly_128:1;
/** flash_res_dly_128 : R/W; bitpos: [3]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after RES
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after RES command is sent.
* 1: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after RES
* command is sent. 0: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after RES command is sent.
*/
uint32_t flash_res_dly_128:1;
/** flash_dp_dly_128 : R/W; bitpos: [4]; default: 0;
* 1: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after DP
* command is sent. 0: SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles
* after DP command is sent.
* 1: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after DP
* command is sent. 0: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK
* cycles after DP command is sent.
*/
uint32_t flash_dp_dly_128:1;
/** flash_per_dly_128 : R/W; bitpos: [5]; default: 0;
* Valid when SPI_MEM_FLASH_PER_WAIT_EN is 1. 1: SPI1 waits
* (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PER command is sent. 0:
* SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PER command is
* sent.
* Valid when SPI1_MEM_S_FLASH_PER_WAIT_EN is 1. 1: SPI1 waits
* (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PER command is sent.
* 0: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PER
* command is sent.
*/
uint32_t flash_per_dly_128:1;
/** flash_pes_dly_128 : R/W; bitpos: [6]; default: 0;
* Valid when SPI_MEM_FLASH_PES_WAIT_EN is 1. 1: SPI1 waits
* (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PES command is sent. 0:
* SPI1 waits (SPI_MEM_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PES command is
* sent.
* Valid when SPI1_MEM_S_FLASH_PES_WAIT_EN is 1. 1: SPI1 waits
* (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 128) SPI_CLK cycles after PES command is sent.
* 0: SPI1 waits (SPI1_MEM_S_CS_HOLD_DELAY_RES[9:0] * 4) SPI_CLK cycles after PES
* command is sent.
*/
uint32_t flash_pes_dly_128:1;
/** spi0_lock_en : R/W; bitpos: [7]; default: 0;
@@ -742,25 +739,7 @@ typedef union {
uint32_t flash_per_command:16;
};
uint32_t val;
} spi_mem_sus_status_reg_t;
/** Type of flash_waiti_ctrl1 register
* SPI1 wait idle control register
*/
typedef union {
struct {
/** waiti_idle_delay_time : R/W; bitpos: [9:0]; default: 0;
* SPI1 wait idle gap time configuration. SPI1 slv fsm will count during SPI1 IDLE.
*/
uint32_t waiti_idle_delay_time:10;
/** waiti_idle_delay_time_en : R/W; bitpos: [10]; default: 0;
* Enable SPI1 wait idle gap time count function. 1: Enable. 0: Disable.
*/
uint32_t waiti_idle_delay_time_en:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_flash_waiti_ctrl1_reg_t;
} spi1_mem_s_sus_status_reg_t;
/** Type of ddr register
* SPI1 DDR control register
@@ -798,8 +777,8 @@ typedef union {
uint32_t fmem_usr_ddr_dqs_thd:7;
/** fmem_ddr_dqs_loop : R/W; 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_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
* spi0_slv_st is in SPI1_MEM_S_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 fmem_ddr_dqs_loop:1;
@@ -835,7 +814,7 @@ typedef union {
uint32_t reserved_31:1;
};
uint32_t val;
} spi_mem_ddr_reg_t;
} spi1_mem_s_ddr_reg_t;
/** Type of clock_gate register
* SPI1 clk_gate register
@@ -849,7 +828,7 @@ typedef union {
uint32_t reserved_1:31;
};
uint32_t val;
} spi_mem_clock_gate_reg_t;
} spi1_mem_s_clock_gate_reg_t;
/** Group: Status register */
@@ -864,7 +843,7 @@ typedef union {
uint32_t tx_crc_data:32;
};
uint32_t val;
} spi_mem_tx_crc_reg_t;
} spi1_mem_s_tx_crc_reg_t;
/** Group: Memory data buffer register */
@@ -879,7 +858,7 @@ typedef union {
uint32_t buf0:32;
};
uint32_t val;
} spi_mem_w0_reg_t;
} spi1_mem_s_w0_reg_t;
/** Type of w1 register
* SPI1 memory data buffer1
@@ -892,7 +871,7 @@ typedef union {
uint32_t buf1:32;
};
uint32_t val;
} spi_mem_w1_reg_t;
} spi1_mem_s_w1_reg_t;
/** Type of w2 register
* SPI1 memory data buffer2
@@ -905,7 +884,7 @@ typedef union {
uint32_t buf2:32;
};
uint32_t val;
} spi_mem_w2_reg_t;
} spi1_mem_s_w2_reg_t;
/** Type of w3 register
* SPI1 memory data buffer3
@@ -918,7 +897,7 @@ typedef union {
uint32_t buf3:32;
};
uint32_t val;
} spi_mem_w3_reg_t;
} spi1_mem_s_w3_reg_t;
/** Type of w4 register
* SPI1 memory data buffer4
@@ -931,7 +910,7 @@ typedef union {
uint32_t buf4:32;
};
uint32_t val;
} spi_mem_w4_reg_t;
} spi1_mem_s_w4_reg_t;
/** Type of w5 register
* SPI1 memory data buffer5
@@ -944,7 +923,7 @@ typedef union {
uint32_t buf5:32;
};
uint32_t val;
} spi_mem_w5_reg_t;
} spi1_mem_s_w5_reg_t;
/** Type of w6 register
* SPI1 memory data buffer6
@@ -957,7 +936,7 @@ typedef union {
uint32_t buf6:32;
};
uint32_t val;
} spi_mem_w6_reg_t;
} spi1_mem_s_w6_reg_t;
/** Type of w7 register
* SPI1 memory data buffer7
@@ -970,7 +949,7 @@ typedef union {
uint32_t buf7:32;
};
uint32_t val;
} spi_mem_w7_reg_t;
} spi1_mem_s_w7_reg_t;
/** Type of w8 register
* SPI1 memory data buffer8
@@ -983,7 +962,7 @@ typedef union {
uint32_t buf8:32;
};
uint32_t val;
} spi_mem_w8_reg_t;
} spi1_mem_s_w8_reg_t;
/** Type of w9 register
* SPI1 memory data buffer9
@@ -996,7 +975,7 @@ typedef union {
uint32_t buf9:32;
};
uint32_t val;
} spi_mem_w9_reg_t;
} spi1_mem_s_w9_reg_t;
/** Type of w10 register
* SPI1 memory data buffer10
@@ -1009,7 +988,7 @@ typedef union {
uint32_t buf10:32;
};
uint32_t val;
} spi_mem_w10_reg_t;
} spi1_mem_s_w10_reg_t;
/** Type of w11 register
* SPI1 memory data buffer11
@@ -1022,7 +1001,7 @@ typedef union {
uint32_t buf11:32;
};
uint32_t val;
} spi_mem_w11_reg_t;
} spi1_mem_s_w11_reg_t;
/** Type of w12 register
* SPI1 memory data buffer12
@@ -1035,7 +1014,7 @@ typedef union {
uint32_t buf12:32;
};
uint32_t val;
} spi_mem_w12_reg_t;
} spi1_mem_s_w12_reg_t;
/** Type of w13 register
* SPI1 memory data buffer13
@@ -1048,7 +1027,7 @@ typedef union {
uint32_t buf13:32;
};
uint32_t val;
} spi_mem_w13_reg_t;
} spi1_mem_s_w13_reg_t;
/** Type of w14 register
* SPI1 memory data buffer14
@@ -1061,7 +1040,7 @@ typedef union {
uint32_t buf14:32;
};
uint32_t val;
} spi_mem_w14_reg_t;
} spi1_mem_s_w14_reg_t;
/** Type of w15 register
* SPI1 memory data buffer15
@@ -1074,7 +1053,7 @@ typedef union {
uint32_t buf15:32;
};
uint32_t val;
} spi_mem_w15_reg_t;
} spi1_mem_s_w15_reg_t;
/** Group: Interrupt registers */
@@ -1084,34 +1063,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_ena : R/W; bitpos: [0]; default: 0;
* The enable bit for SPI_MEM_PER_END_INT interrupt.
* The enable bit for SPI1_MEM_S_PER_END_INT interrupt.
*/
uint32_t per_end_int_ena:1;
/** pes_end_int_ena : R/W; bitpos: [1]; default: 0;
* The enable bit for SPI_MEM_PES_END_INT interrupt.
* The enable bit for SPI1_MEM_S_PES_END_INT interrupt.
*/
uint32_t pes_end_int_ena:1;
/** wpe_end_int_ena : R/W; bitpos: [2]; default: 0;
* The enable bit for SPI_MEM_WPE_END_INT interrupt.
* The enable bit for SPI1_MEM_S_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_ena:1;
/** slv_st_end_int_ena : R/W; bitpos: [3]; default: 0;
* The enable bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The enable bit for SPI1_MEM_S_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_ena:1;
/** mst_st_end_int_ena : R/W; bitpos: [4]; default: 0;
* The enable bit for SPI_MEM_MST_ST_END_INT interrupt.
* The enable bit for SPI1_MEM_S_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_ena:1;
uint32_t reserved_5:5;
/** brown_out_int_ena : R/W; bitpos: [10]; default: 0;
* The enable bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The enable bit for SPI1_MEM_S_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_ena:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_ena_reg_t;
} spi1_mem_s_int_ena_reg_t;
/** Type of int_clr register
* SPI1 interrupt clear register
@@ -1119,34 +1098,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_clr : WT; bitpos: [0]; default: 0;
* The clear bit for SPI_MEM_PER_END_INT interrupt.
* The clear bit for SPI1_MEM_S_PER_END_INT interrupt.
*/
uint32_t per_end_int_clr:1;
/** pes_end_int_clr : WT; bitpos: [1]; default: 0;
* The clear bit for SPI_MEM_PES_END_INT interrupt.
* The clear bit for SPI1_MEM_S_PES_END_INT interrupt.
*/
uint32_t pes_end_int_clr:1;
/** wpe_end_int_clr : WT; bitpos: [2]; default: 0;
* The clear bit for SPI_MEM_WPE_END_INT interrupt.
* The clear bit for SPI1_MEM_S_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_clr:1;
/** slv_st_end_int_clr : WT; bitpos: [3]; default: 0;
* The clear bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The clear bit for SPI1_MEM_S_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_clr:1;
/** mst_st_end_int_clr : WT; bitpos: [4]; default: 0;
* The clear bit for SPI_MEM_MST_ST_END_INT interrupt.
* The clear bit for SPI1_MEM_S_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_clr:1;
uint32_t reserved_5:5;
/** brown_out_int_clr : WT; bitpos: [10]; default: 0;
* The status bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The status bit for SPI1_MEM_S_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_clr:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_clr_reg_t;
} spi1_mem_s_int_clr_reg_t;
/** Type of int_raw register
* SPI1 interrupt raw register
@@ -1154,34 +1133,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_raw : R/WTC/SS; bitpos: [0]; default: 0;
* The raw bit for SPI_MEM_PER_END_INT interrupt. 1: Triggered when Auto Resume
* The raw bit for SPI1_MEM_S_PER_END_INT interrupt. 1: Triggered when Auto Resume
* command (0x7A) is sent and flash is resumed successfully. 0: Others.
*/
uint32_t per_end_int_raw:1;
/** pes_end_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
* The raw bit for SPI_MEM_PES_END_INT interrupt.1: Triggered when Auto Suspend
* The raw bit for SPI1_MEM_S_PES_END_INT interrupt.1: Triggered when Auto Suspend
* command (0x75) is sent and flash is suspended successfully. 0: Others.
*/
uint32_t pes_end_int_raw:1;
/** wpe_end_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
* The raw bit for SPI_MEM_WPE_END_INT interrupt. 1: Triggered when WRSR/PP/SE/BE/CE
* is sent and flash is already idle. 0: Others.
* The raw bit for SPI1_MEM_S_WPE_END_INT interrupt. 1: Triggered when
* WRSR/PP/SE/BE/CE is sent and flash is already idle. 0: Others.
*/
uint32_t wpe_end_int_raw:1;
/** slv_st_end_int_raw : R/WTC/SS; bitpos: [3]; default: 0;
* The raw bit for SPI_MEM_SLV_ST_END_INT interrupt. 1: Triggered when spi1_slv_st is
* changed from non idle state to idle state. It means that SPI_CS raises high. 0:
* The raw bit for SPI1_MEM_S_SLV_ST_END_INT interrupt. 1: Triggered when spi1_slv_st
* is changed from non idle state to idle state. It means that SPI_CS raises high. 0:
* Others
*/
uint32_t slv_st_end_int_raw:1;
/** mst_st_end_int_raw : R/WTC/SS; bitpos: [4]; default: 0;
* The raw bit for SPI_MEM_MST_ST_END_INT interrupt. 1: Triggered when spi1_mst_st is
* changed from non idle state to idle state. 0: Others.
* The raw bit for SPI1_MEM_S_MST_ST_END_INT interrupt. 1: Triggered when spi1_mst_st
* is changed from non idle state to idle state. 0: Others.
*/
uint32_t mst_st_end_int_raw:1;
uint32_t reserved_5:5;
/** brown_out_int_raw : R/WTC/SS; bitpos: [10]; default: 0;
* The raw bit for SPI_MEM_BROWN_OUT_INT interrupt. 1: Triggered condition is that
* The raw bit for SPI1_MEM_S_BROWN_OUT_INT interrupt. 1: Triggered condition is that
* chip is losing power and RTC module sends out brown out close flash request to
* SPI1. After SPI1 sends out suspend command to flash, this interrupt is triggered
* and MSPI returns to idle state. 0: Others.
@@ -1190,7 +1169,7 @@ typedef union {
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_raw_reg_t;
} spi1_mem_s_int_raw_reg_t;
/** Type of int_st register
* SPI1 interrupt status register
@@ -1198,34 +1177,34 @@ typedef union {
typedef union {
struct {
/** per_end_int_st : RO; bitpos: [0]; default: 0;
* The status bit for SPI_MEM_PER_END_INT interrupt.
* The status bit for SPI1_MEM_S_PER_END_INT interrupt.
*/
uint32_t per_end_int_st:1;
/** pes_end_int_st : RO; bitpos: [1]; default: 0;
* The status bit for SPI_MEM_PES_END_INT interrupt.
* The status bit for SPI1_MEM_S_PES_END_INT interrupt.
*/
uint32_t pes_end_int_st:1;
/** wpe_end_int_st : RO; bitpos: [2]; default: 0;
* The status bit for SPI_MEM_WPE_END_INT interrupt.
* The status bit for SPI1_MEM_S_WPE_END_INT interrupt.
*/
uint32_t wpe_end_int_st:1;
/** slv_st_end_int_st : RO; bitpos: [3]; default: 0;
* The status bit for SPI_MEM_SLV_ST_END_INT interrupt.
* The status bit for SPI1_MEM_S_SLV_ST_END_INT interrupt.
*/
uint32_t slv_st_end_int_st:1;
/** mst_st_end_int_st : RO; bitpos: [4]; default: 0;
* The status bit for SPI_MEM_MST_ST_END_INT interrupt.
* The status bit for SPI1_MEM_S_MST_ST_END_INT interrupt.
*/
uint32_t mst_st_end_int_st:1;
uint32_t reserved_5:5;
/** brown_out_int_st : RO; bitpos: [10]; default: 0;
* The status bit for SPI_MEM_BROWN_OUT_INT interrupt.
* The status bit for SPI1_MEM_S_BROWN_OUT_INT interrupt.
*/
uint32_t brown_out_int_st:1;
uint32_t reserved_11:21;
};
uint32_t val;
} spi_mem_int_st_reg_t;
} spi1_mem_s_int_st_reg_t;
/** Group: Timing registers */
@@ -1246,7 +1225,7 @@ typedef union {
uint32_t reserved_5:27;
};
uint32_t val;
} spi_mem_timing_cali_reg_t;
} spi1_mem_s_timing_cali_reg_t;
/** Group: Version register */
@@ -1255,71 +1234,70 @@ typedef union {
*/
typedef union {
struct {
/** date : R/W; bitpos: [27:0]; default: 37786176;
/** date : R/W; bitpos: [27:0]; default: 38801712;
* Version control register
*/
uint32_t date:28;
uint32_t reserved_28:4;
};
uint32_t val;
} spi_mem_date_reg_t;
} spi1_mem_s_date_reg_t;
typedef struct {
volatile spi_mem_cmd_reg_t cmd;
volatile spi_mem_addr_reg_t addr;
volatile spi_mem_ctrl_reg_t ctrl;
volatile spi_mem_ctrl1_reg_t ctrl1;
volatile spi_mem_ctrl2_reg_t ctrl2;
volatile spi_mem_clock_reg_t clock;
volatile spi_mem_user_reg_t user;
volatile spi_mem_user1_reg_t user1;
volatile spi_mem_user2_reg_t user2;
volatile spi_mem_mosi_dlen_reg_t mosi_dlen;
volatile spi_mem_miso_dlen_reg_t miso_dlen;
volatile spi_mem_rd_status_reg_t rd_status;
typedef struct spi1_mem_s_dev_s {
volatile spi1_mem_s_cmd_reg_t cmd;
volatile spi1_mem_s_addr_reg_t addr;
volatile spi1_mem_s_ctrl_reg_t ctrl;
volatile spi1_mem_s_ctrl1_reg_t ctrl1;
volatile spi1_mem_s_ctrl2_reg_t ctrl2;
volatile spi1_mem_s_clock_reg_t clock;
volatile spi1_mem_s_user_reg_t user;
volatile spi1_mem_s_user1_reg_t user1;
volatile spi1_mem_s_user2_reg_t user2;
volatile spi1_mem_s_mosi_dlen_reg_t mosi_dlen;
volatile spi1_mem_s_miso_dlen_reg_t miso_dlen;
volatile spi1_mem_s_rd_status_reg_t rd_status;
uint32_t reserved_030;
volatile spi_mem_misc_reg_t misc;
volatile spi_mem_tx_crc_reg_t tx_crc;
volatile spi_mem_cache_fctrl_reg_t cache_fctrl;
volatile spi1_mem_s_misc_reg_t misc;
volatile spi1_mem_s_tx_crc_reg_t tx_crc;
volatile spi1_mem_s_cache_fctrl_reg_t cache_fctrl;
uint32_t reserved_040[6];
volatile spi_mem_w0_reg_t w0;
volatile spi_mem_w1_reg_t w1;
volatile spi_mem_w2_reg_t w2;
volatile spi_mem_w3_reg_t w3;
volatile spi_mem_w4_reg_t w4;
volatile spi_mem_w5_reg_t w5;
volatile spi_mem_w6_reg_t w6;
volatile spi_mem_w7_reg_t w7;
volatile spi_mem_w8_reg_t w8;
volatile spi_mem_w9_reg_t w9;
volatile spi_mem_w10_reg_t w10;
volatile spi_mem_w11_reg_t w11;
volatile spi_mem_w12_reg_t w12;
volatile spi_mem_w13_reg_t w13;
volatile spi_mem_w14_reg_t w14;
volatile spi_mem_w15_reg_t w15;
volatile spi_mem_flash_waiti_ctrl_reg_t flash_waiti_ctrl;
volatile spi_mem_flash_sus_ctrl_reg_t flash_sus_ctrl;
volatile spi_mem_flash_sus_cmd_reg_t flash_sus_cmd;
volatile spi_mem_sus_status_reg_t sus_status;
uint32_t reserved_0a8;
volatile spi_mem_flash_waiti_ctrl1_reg_t flash_waiti_ctrl1;
uint32_t reserved_0b0[4];
volatile spi_mem_int_ena_reg_t int_ena;
volatile spi_mem_int_clr_reg_t int_clr;
volatile spi_mem_int_raw_reg_t int_raw;
volatile spi_mem_int_st_reg_t int_st;
volatile spi1_mem_s_w0_reg_t w0;
volatile spi1_mem_s_w1_reg_t w1;
volatile spi1_mem_s_w2_reg_t w2;
volatile spi1_mem_s_w3_reg_t w3;
volatile spi1_mem_s_w4_reg_t w4;
volatile spi1_mem_s_w5_reg_t w5;
volatile spi1_mem_s_w6_reg_t w6;
volatile spi1_mem_s_w7_reg_t w7;
volatile spi1_mem_s_w8_reg_t w8;
volatile spi1_mem_s_w9_reg_t w9;
volatile spi1_mem_s_w10_reg_t w10;
volatile spi1_mem_s_w11_reg_t w11;
volatile spi1_mem_s_w12_reg_t w12;
volatile spi1_mem_s_w13_reg_t w13;
volatile spi1_mem_s_w14_reg_t w14;
volatile spi1_mem_s_w15_reg_t w15;
volatile spi1_mem_s_flash_waiti_ctrl_reg_t flash_waiti_ctrl;
volatile spi1_mem_s_flash_sus_ctrl_reg_t flash_sus_ctrl;
volatile spi1_mem_s_flash_sus_cmd_reg_t flash_sus_cmd;
volatile spi1_mem_s_sus_status_reg_t sus_status;
uint32_t reserved_0a8[6];
volatile spi1_mem_s_int_ena_reg_t int_ena;
volatile spi1_mem_s_int_clr_reg_t int_clr;
volatile spi1_mem_s_int_raw_reg_t int_raw;
volatile spi1_mem_s_int_st_reg_t int_st;
uint32_t reserved_0d0;
volatile spi_mem_ddr_reg_t ddr;
volatile spi1_mem_s_ddr_reg_t ddr;
uint32_t reserved_0d8[42];
volatile spi_mem_timing_cali_reg_t timing_cali;
volatile spi1_mem_s_timing_cali_reg_t timing_cali;
uint32_t reserved_184[31];
volatile spi_mem_clock_gate_reg_t clock_gate;
volatile spi1_mem_s_clock_gate_reg_t clock_gate;
uint32_t reserved_204[126];
volatile spi_mem_date_reg_t date;
volatile spi1_mem_s_date_reg_t date;
} spi1_mem_s_dev_t;
extern spi1_mem_s_dev_t SPIMEM3;
#ifndef __cplusplus
_Static_assert(sizeof(spi1_mem_s_dev_t) == 0x400, "Invalid size of spi1_mem_s_dev_t structure");
+1 -1
View File
@@ -205,7 +205,7 @@ void IRAM_ATTR spi_flash_set_rom_required_regs(void)
#endif
}
#if CONFIG_SPIRAM_MODE_OCT
#if CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM_MODE_OCT
// This function will only be called when Octal PSRAM enabled.
void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
{
+2 -2
View File
@@ -1,5 +1,5 @@
| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | --------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
| ----------------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
# XIP (Execute-In-Place) From PSRAM Example