feat(psram): esp32p4 psram device driver support

This commit is contained in:
Armando 2023-08-28 10:20:56 +08:00
parent bc4bdd6169
commit 712c0c0075
26 changed files with 2190 additions and 258 deletions

View File

@ -3,3 +3,6 @@
components/esp_common/test_apps/esp_common:
disable:
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
- if: CONFIG_NAME == "psram" and IDF_TARGET in ["esp32p4"]
temporary: true
reason: esp32p4 is not supported yet # TODO: IDF-7557

View File

@ -25,6 +25,10 @@ if(CONFIG_SPIRAM)
elseif(CONFIG_SPIRAM_MODE_OCT)
list(APPEND srcs "${target}/esp_psram_impl_octal.c")
endif()
if(CONFIG_SPIRAM_MODE_HEX)
list(APPEND srcs "device/esp_psram_impl_ap_hex.c")
endif()
endif()
idf_component_register(SRCS ${srcs}

View File

@ -107,12 +107,3 @@ config SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
Note the values placed into this section will not be initialized at startup and should keep its value
after software restart.
config SPIRAM_ECC_ENABLE
bool "Enable SPI RAM ECC"
default n
depends on SPIRAM_MODE_OCT && IDF_TARGET_ESP32S3
help
Enable MSPI Error-Correcting Code function when accessing SPIRAM.
If enabled, 1/16 of the SPI RAM total size will be reserved for error-correcting code.

View File

@ -0,0 +1,398 @@
/*
* SPDX-FileCopyrightText: 2019-2023 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_psram_impl.h"
#include "rom/opi_flash.h"
#include "hal/psram_ctrlr_ll.h"
#define AP_HEX_PSRAM_SYNC_READ 0x0000
#define AP_HEX_PSRAM_SYNC_WRITE 0x8080
#define AP_HEX_PSRAM_BURST_READ 0x2020
#define AP_HEX_PSRAM_BURST_WRITE 0xA0A0
#define AP_HEX_PSRAM_REG_READ 0x4040
#define AP_HEX_PSRAM_REG_WRITE 0xC0C0
#define AP_HEX_PSRAM_RD_CMD_BITLEN 16
#define AP_HEX_PSRAM_WR_CMD_BITLEN 16
#define AP_HEX_PSRAM_ADDR_BITLEN 32
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(10-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(5-1))
#define AP_HEX_PSRAM_VENDOR_ID 0xD
#define AP_HEX_PSRAM_CS_SETUP_TIME 4
#define AP_HEX_PSRAM_CS_HOLD_TIME 4
#define AP_HEX_PSRAM_CS_ECC_HOLD_TIME 4
#define AP_HEX_PSRAM_CS_HOLD_DELAY 3
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 rsvd0_2: 2;
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 rsvd3_7: 4;
uint8_t srf: 2;
uint8_t rsvd0: 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 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;
} hex_psram_mode_reg_t;
static const char* TAG = "hex_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, hex_psram_mode_reg_t *mode_reg_config)
{
int cmd_len = 16;
uint32_t addr = 0x0;
int addr_bit_len = 32;
int dummy = AP_HEX_PSRAM_RD_DUMMY_BITLEN;
hex_psram_mode_reg_t mode_reg = {0};
int data_bit_len = 16;
//read
s_psram_common_transaction(spi_num,
AP_HEX_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
dummy,
NULL, 0,
&mode_reg.mr0.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;
//write
s_psram_common_transaction(spi_num,
AP_HEX_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
0,
&mode_reg.mr0.val, 16,
NULL, 0,
false);
addr = 0x8;
data_bit_len = 8;
//read
s_psram_common_transaction(spi_num,
AP_HEX_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_HEX_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, hex_psram_mode_reg_t *out_reg)
{
int cmd_len = 16;
int addr_bit_len = 32;
int dummy = AP_HEX_PSRAM_RD_DUMMY_BITLEN;
int data_bit_len = 16;
//Read MR0~1 register
s_psram_common_transaction(spi_num,
AP_HEX_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_HEX_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_HEX_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_HEX_PSRAM_REG_READ, cmd_len,
0x8, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr8.val, data_bit_len,
false);
}
static void s_print_psram_info(hex_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_HEX_PSRAM_WR_CMD_BITLEN, AP_HEX_PSRAM_BURST_WRITE);
//Config Read CMD phase for SPI0 to access PSRAM
psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_PSRAM_RD_CMD_BITLEN, AP_HEX_PSRAM_BURST_READ);
//Config ADDR phase
psram_ctrlr_ll_set_addr_bitlen(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_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_HEX_PSRAM_WR_DUMMY_BITLEN);
psram_ctrlr_ll_set_rd_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_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);
//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, true);
#if CONFIG_SPIRAM_USE_8LINE_MODE
psram_ctrlr_ll_enable_hex_data_line_mode(PSRAM_CTRLR_LL_MSPI_ID_2, false);
#endif
//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_HEX_PSRAM_CS_SETUP_TIME);
psram_ctrlr_ll_set_cs_hold(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_PSRAM_CS_HOLD_TIME);
psram_ctrlr_ll_set_cs_hold_delay(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_PSRAM_CS_HOLD_DELAY);
#if CONFIG_SPIRAM_ECC_ENABLE
psram_ctrlr_ll_set_cs_hold_ecc(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_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_split_trans(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_page_size(PSRAM_CTRLR_LL_MSPI_ID_2, 2048);
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 Hex 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)
{
s_set_psram_cs_timing();
#if CONFIG_SPIRAM_ECC_ENABLE
s_configure_psram_ecc();
#endif
//enter MSPI slow mode to init PSRAM device registers
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, 2);
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 hex_psram_mode_reg_t mode_reg = {};
mode_reg.mr0.lt = 1;
mode_reg.mr0.read_latency = 2;
mode_reg.mr0.drive_str = 0;
mode_reg.mr8.bl = 3;
mode_reg.mr8.bt = 0;
mode_reg.mr8.rbx = 1;
mode_reg.mr8.x16 = 1;
#if CONFIG_SPIRAM_USE_8LINE_MODE
mode_reg.mr8.x16 = 0;
#endif
s_init_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
//Print PSRAM info
s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg);
if (mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID) {
ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", mode_reg.mr1.vendor_id);
return ESP_ERR_NOT_SUPPORTED;
}
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();
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);
}

View File

@ -189,6 +189,25 @@ typedef struct {
#define PSRAM_SPICLKEN DPORT_SPI01_CLK_EN
#endif
/*
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
issues but cannot be used when the app CPU cache is disabled.
*/
typedef enum {
PSRAM_VADDR_MODE_NORMAL = 0, ///< App and pro CPU use their own flash cache for external RAM access
PSRAM_VADDR_MODE_LOWHIGH, ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
PSRAM_VADDR_MODE_EVENODD, ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
} psram_vaddr_mode_t;
#if CONFIG_FREERTOS_UNICORE
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
#else
#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
#endif
static const char *TAG = "quad_psram";
typedef enum {
PSRAM_SPI_1 = 0x1,
@ -832,8 +851,9 @@ bool psram_is_32mbit_ver0(void)
* Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
* Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
*/
esp_err_t IRAM_ATTR esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) //psram init
esp_err_t IRAM_ATTR esp_psram_impl_enable(void) //psram init
{
psram_vaddr_mode_t vaddrmode = PSRAM_MODE;
psram_cache_speed_t mode = PSRAM_SPEED;
psram_io_t psram_io = {0};
uint32_t pkg_ver = efuse_ll_get_chip_ver_pkg();

View File

@ -0,0 +1,62 @@
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_HEX
config SPIRAM_MODE_HEX
bool "16-Line-Mode PSRAM"
endchoice
config SPIRAM_USE_8LINE_MODE
bool
depends on SPIRAM_MODE_HEX
default n
help
Enable 8-Line-Mode of the AP HEX PSRAM
choice SPIRAM_SPEED
prompt "Set PSRAM clock speed"
default SPIRAM_SPEED_20M
help
Select the speed for the PSRAM chip.
config SPIRAM_SPEED_20M
bool "20MHz clock speed"
endchoice
config SPIRAM_SPEED
int
default 20 if SPIRAM_SPEED_20M
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.
config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
bool "Allow external memory as an argument to xTaskCreateStatic"
default y
help
Accessing memory in PSRAM has certain restrictions, so task stacks allocated by xTaskCreate
are by default allocated from internal RAM.
This option allows for passing memory allocated from PSRAM to be passed to xTaskCreateStatic.
This should only be used for tasks where the stack is never accessed while the L2Cache is
disabled, e.g. during SPI Flash operations
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
endmenu

View File

@ -3,7 +3,7 @@
*/
/*
* SPDX-FileCopyrightText: 2013-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2013-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -93,6 +93,10 @@ static const char* TAG = "quad_psram";
#define _SPI_40M_CLK_DIV 2
#define _SPI_20M_CLK_DIV 4
typedef enum {
PSRAM_VADDR_MODE_NORMAL = 0,
} psram_vaddr_mode_t;
typedef enum {
PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */
PSRAM_CLK_MODE_A1C, /*!< ONE extra clock cycles after CS is set high level */
@ -410,8 +414,9 @@ static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode)
* Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
* Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
*/
esp_err_t IRAM_ATTR esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) //psram init
esp_err_t IRAM_ATTR esp_psram_impl_enable(void) //psram init
{
psram_vaddr_mode_t vaddrmode = PSRAM_VADDR_MODE_NORMAL;
psram_cache_speed_t mode = PSRAM_SPEED;
assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
// GPIO related settings

View File

@ -108,5 +108,14 @@ menu "SPI RAM config"
default 80 if SPIRAM_SPEED_80M
default 40 if SPIRAM_SPEED_40M
config SPIRAM_ECC_ENABLE
bool "Enable SPI RAM ECC"
default n
depends on SPIRAM_MODE_OCT
help
Enable MSPI Error-Correcting Code function when accessing SPIRAM.
If enabled, 1/16 of the SPI RAM total size will be reserved for error-correcting code.
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
endmenu

View File

@ -294,7 +294,7 @@ static void s_configure_psram_ecc(void)
#endif
}
esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode)
esp_err_t esp_psram_impl_enable(void)
{
s_init_psram_pins();
s_set_psram_cs_timing();

View File

@ -303,7 +303,7 @@ static void psram_gpio_config(void)
esp_gpio_reserve_pins(BIT64(cs1_io) | BIT64(wp_io));
}
esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) //psram init
esp_err_t esp_psram_impl_enable(void) //psram init
{
psram_gpio_config();
psram_set_cs_timing();

View File

@ -17,9 +17,9 @@
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "esp_heap_caps_init.h"
#include "hal/mmu_hal.h"
#include "hal/mmu_ll.h"
#include "hal/cache_ll.h"
#include "esp_private/esp_psram_io.h"
#include "esp_private/esp_psram_extram.h"
@ -36,16 +36,6 @@
#endif
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_FREERTOS_UNICORE
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
#else
#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
#endif
#else
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
#endif
/**
* Two types of PSRAM memory regions for now:
* - 8bit aligned
@ -123,7 +113,7 @@ esp_err_t esp_psram_init(void)
}
esp_err_t ret = ESP_FAIL;
ret = esp_psram_impl_enable(PSRAM_MODE);
ret = esp_psram_impl_enable();
if (ret != ESP_OK) {
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
ESP_EARLY_LOGE(TAG, "PSRAM enabled but initialization failed. Bailing out.");
@ -139,10 +129,11 @@ esp_err_t esp_psram_init(void)
ESP_EARLY_LOGI(TAG, "Found %dMB PSRAM device", psram_physical_size / (1024 * 1024));
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
#if CONFIG_IDF_TARGET_ESP32
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
(PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
(PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
(PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
#if CONFIG_FREERTOS_UNICORE
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in normal (1-core) mode.");
#else
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in low/high (2-core) mode.");
#endif
#endif
uint32_t psram_available_size = 0;
@ -196,30 +187,19 @@ esp_err_t esp_psram_init(void)
size_t total_mapped_size = 0;
size_t size_to_map = 0;
size_t byte_aligned_size = 0;
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7495
ret = esp_mmu_map_get_max_consecutive_free_block_size(MMU_MEM_CAP_PSRAM, MMU_TARGET_PSRAM0, &byte_aligned_size);
#else
ret = esp_mmu_map_get_max_consecutive_free_block_size(MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_8BIT | MMU_MEM_CAP_32BIT, MMU_TARGET_PSRAM0, &byte_aligned_size);
#endif
assert(ret == ESP_OK);
size_to_map = MIN(byte_aligned_size, psram_available_size);
const void *v_start_8bit_aligned = NULL;
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7495
ret = esp_mmu_map_reserve_block_with_caps(size_to_map, MMU_MEM_CAP_PSRAM, MMU_TARGET_PSRAM0, &v_start_8bit_aligned);
#else
ret = esp_mmu_map_reserve_block_with_caps(size_to_map, MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_8BIT | MMU_MEM_CAP_32BIT, MMU_TARGET_PSRAM0, &v_start_8bit_aligned);
#endif
assert(ret == ESP_OK);
#if CONFIG_IDF_TARGET_ESP32
s_mapping((int)v_start_8bit_aligned, size_to_map);
#else
uint32_t actual_mapped_len = 0;
#if CONFIG_IDF_TARGET_ESP32P4
//TODO: IDF-7495
#if MMU_LL_MMU_PER_TARGET
mmu_hal_map_region(1, MMU_TARGET_PSRAM0, (intptr_t)v_start_8bit_aligned, MMU_PAGE_TO_BYTES(start_page), size_to_map, &actual_mapped_len);
#else
mmu_hal_map_region(0, MMU_TARGET_PSRAM0, (intptr_t)v_start_8bit_aligned, MMU_PAGE_TO_BYTES(start_page), size_to_map, &actual_mapped_len);

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,20 +20,6 @@ extern "C" {
#define PSRAM_SIZE_32MB (32 * 1024 * 1024)
#define PSRAM_SIZE_64MB (64 * 1024 * 1024)
/*
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
issues but cannot be used when the app CPU cache is disabled.
*/
typedef enum {
PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
PSRAM_VADDR_MODE_LOWHIGH, ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
PSRAM_VADDR_MODE_EVENODD, ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
} psram_vaddr_mode_t;
/**
* @brief To get the physical psram size in bytes.
*
@ -51,13 +37,12 @@ esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes);
/**
* @brief Enable psram and configure it to a ready state
*
* @param vaddrmode Mode the psram cache works in.
* @return
* - ESP_OK: On success
* - ESP_ERR_NOT_SUPPORTED: PSRAM ID / vendor ID check fail
* - ESP_ERR_INVALID_STATE: On esp32, when VSPI peripheral is needed but cannot be claimed
*/
esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode);
esp_err_t esp_psram_impl_enable(void);
/**
* @brief get psram CS IO

View File

@ -13,3 +13,6 @@ entries:
if IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y:
mmu_psram_flash (noflash)
if SPIRAM_MODE_HEX = y:
esp_psram_impl_ap_hex (noflash)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@ -0,0 +1,692 @@
/*
* SPDX-FileCopyrightText: 2023 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 "soc/spi_mem_s_struct.h"
#include "soc/spi_mem_s_reg.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/clk_tree_defs.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_PMS_REGION_NUMS 4
#define PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE (1<<0)
#define PSRAM_CTRLR_LL_PMS_ATTR_READABLE (1<<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;
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;
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)
{
(void)mspi_id;
SPIMEM2.smem_ddr.smem_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 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;
}
/**
* @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.peri_clk_ctrl00.reg_psram_pll_clk_en = en;
}
/**
* @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_SPLL:
clk_val = 2;
break;
case PSRAM_CLK_SRC_CPLL:
clk_val = 3;
break;
default:
HAL_ASSERT(false);
break;
}
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_clk_src_sel = clk_val;
}
/**
* @brief Set PSRAM core clock
*
* @param mspi_id mspi_id
* @param core_clk_mhz core clock mhz
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t core_clk_mhz)
{
//TODO: IDF-7517
}
/**
* @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)
{
(void)mspi_id;
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);
}
}
/**
* @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 spliting 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_pms_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_pms_wr_attr = 0;
SPIMEM2.smem_pmsn_attr[region_id].smem_pms_rd_attr = 0;
if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE) {
SPIMEM2.smem_pmsn_attr[region_id].smem_pms_wr_attr = 1;
}
if (attr_mask & PSRAM_CTRLR_LL_PMS_ATTR_READABLE) {
SPIMEM2.smem_pmsn_attr[region_id].smem_pms_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_pms_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_pms_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_pms_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_pms_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);
}
#ifdef __cplusplus
}
#endif

View File

@ -30,8 +30,9 @@ enum {
SOC_MEMORY_TYPE_STACK_DRAM = 1,
SOC_MEMORY_TYPE_DIRAM = 2,
SOC_MEMORY_TYPE_STACK_DIRAM = 3,
SOC_MEMORY_TYPE_RTCRAM = 4,
SOC_MEMORY_TYPE_TCM = 5,
SOC_MEMORY_TYPE_SPIRAM = 4,
SOC_MEMORY_TYPE_RTCRAM = 5,
SOC_MEMORY_TYPE_TCM = 6,
SOC_MEMORY_TYPE_NUM,
};
@ -44,9 +45,11 @@ const soc_memory_type_desc_t soc_memory_types[SOC_MEMORY_TYPE_NUM] = {
[SOC_MEMORY_TYPE_DIRAM] = { "D/IRAM", { 0, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL | MALLOC_CAP_DEFAULT, MALLOC_CAP_32BIT | MALLOC_CAP_EXEC }, true, false},
// Type 3: DIRAM used for startup stacks
[SOC_MEMORY_TYPE_STACK_DIRAM] = { "STACK/DIRAM", { MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT | MALLOC_CAP_RETENTION, MALLOC_CAP_EXEC | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_32BIT, 0 }, true, true},
// Type 4: RTCRAM // TODO: IDF-5667 Better to rename to LPRAM
// Type 4: SPI SRAM data
[SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT}, false, false},
// Type 5: RTCRAM // TODO: IDF-5667 Better to rename to LPRAM
[SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT }, false, false},
// Type 5: TCM
// Type 6: TCM
[SOC_MEMORY_TYPE_TCM] = {"TCM", {MALLOC_CAP_TCM, MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT}, false, false},
};
@ -75,7 +78,7 @@ const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memor
const soc_memory_region_t soc_memory_regions[] = {
#ifdef CONFIG_SPIRAM
{ SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH, SOC_MEMORY_TYPE_SPIRAM, 0}, //PSRAM, if available
{ SOC_EXTRAM_LOW, SOC_EXTRAM_SIZE, SOC_MEMORY_TYPE_SPIRAM, 0}, //PSRAM, if available
#endif
// base 192k is always avaible, even if we config l2 cache size to 512k
{ 0x4ff00000, 0x30000, SOC_MEMORY_TYPE_DEFAULT, 0x4ff00000},

View File

@ -80,6 +80,9 @@
#include "lwip/sys.h"
#include <string.h>
#include "esp_rom_md5.h"
#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
#include "esp_memory_utils.h"
#endif
#ifdef CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT

View File

@ -79,6 +79,10 @@ config SOC_FLASH_ENC_SUPPORTED
bool
default y
config SOC_SPIRAM_SUPPORTED
bool
default y
config SOC_XTAL_SUPPORT_40M
bool
default y

View File

@ -48,7 +48,7 @@ extern "C" {
* PLL Clocks:
*
* from 40MHz XTAL oscillator frequency multipliers:
* 1) CPLL (400MHz), used for CPU clock source
* 1) CPLL (400MHz), used for CPU, MSPI-Flash, MSPI-PSRAM clock source
* 2) MPLL (500MHz), used for MSPI-PSRAM clock source; and is further divided to PLL_F50M, PLL_F25M, to be used for peripheral's clock sources
* 3) SPLL (480MHz), directly used for MSPI-Flash, MSPI-PSRAM, GPSPI clock sources; and is further divided to PLL_F240M, PLL_F160M, PLL_F120M, PLL_F80M, PLL_F20M, to be used for peripherals' clock sources
* 4) APLL (configurable), can be the clock source for peripherals (GPSPI, I2S, LCD, CAM, etc.)
@ -144,6 +144,9 @@ typedef enum {
SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */
SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */
SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */
SOC_MOD_CLK_CPLL, /*!< CPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 400MHz */
SOC_MOD_CLK_SPLL, /*!< SPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 480MHz */
SOC_MOD_CLK_MPLL, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers, it has a fixed frequency of 500MHz */
SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */
SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */
SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */
@ -328,6 +331,41 @@ typedef enum {
SPI_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as SPI 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_SPLL, SOC_MOD_CLK_MPLL}
/**
* @brief Type of PSRAM clock source.
*/
typedef enum {
PSRAM_CLK_SRC_DEFAULT = SOC_MOD_CLK_SPLL, /*!< Select SOC_MOD_CLK_SPLL 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_SPLL = SOC_MOD_CLK_SPLL, /*!< Select SOC_MOD_CLK_SPLL 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////////////////////////////////////////////////////////////////////
/**
* @brief Array initializer for all supported clock sources of FLASH
*/
#define SOC_FLASH_CLKS {SOC_MOD_CLK_XTAL, SOC_MOD_CLK_CPLL, SOC_MOD_CLK_SPLL}
/**
* @brief Type of FLASH clock source.
*/
typedef enum {
FLASH_CLK_SRC_DEFAULT = SOC_MOD_CLK_SPLL, /*!< Select SOC_MOD_CLK_SPLL as FLASH source clock */
FLASH_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select SOC_MOD_CLK_XTAL as FLASH source clock */
FLASH_CLK_SRC_CPLL = SOC_MOD_CLK_CPLL, /*!< Select SOC_MOD_CLK_CPLL as FLASH source clock */
FLASH_CLK_SRC_SPLL = SOC_MOD_CLK_SPLL, /*!< Select SOC_MOD_CLK_SPLL as FLASH source clock */
} soc_periph_flash_clk_src_t;
//////////////////////////////////////////////////SDM//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////GPIO Glitch Filter////////////////////////////////////////////////////

View File

@ -158,12 +158,9 @@
#define SOC_DROM_LOW 0x40000000
#define SOC_DROM_HIGH 0x44000000
#define SOC_SINGLE_BANK_LOW 0x40000000
#define SOC_SINGLE_BANK_HIGH 0x44000000
#define SOC_EXTRAM_LOW 0x48000000
#define SOC_EXTRAM_HIGH 0x4c000000
#define SOC_EXT_DBRAM_DATA_LOW 0x4a000000
#define SOC_EXT_DBRAM_DATA_HIGH 0x4c000000
#define SOC_EXTRAM_SIZE (SOC_EXTRAM_HIGH - SOC_EXTRAM_LOW)
#define SOC_IROM_MASK_LOW 0x4fc00000
#define SOC_IROM_MASK_HIGH 0x4fc20000

View File

@ -69,7 +69,7 @@
// #define SOC_PMU_SUPPORTED 1 //TODO: IDF-7531
// #define SOC_PAU_SUPPORTED 1 //TODO: IDF-7531
// #define SOC_LP_TIMER_SUPPORTED 1 //TODO: IDF-7532
// #define SOC_SPIRAM_SUPPORTED 1 //TODO: IDF-7495
#define SOC_SPIRAM_SUPPORTED 1
// #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534
// #define SOC_SDMMC_HOST_SUPPORTED 1 //TODO: IDF-6502
// #define SOC_CLK_TREE_SUPPORTED 1 //TODO: IDF-7526

File diff suppressed because it is too large Load Diff

View File

@ -314,7 +314,49 @@ typedef union {
*/
typedef union {
struct {
uint32_t reserved_0:30;
/** mem_axi_req_en : R/W; bitpos: [0]; default: 0;
* For SPI0, AXI master access enable, 1: enable, 0:disable.
*/
uint32_t mem_axi_req_en:1;
/** mem_cache_usr_addr_4byte : R/W; bitpos: [1]; default: 0;
* For SPI0, cache read flash with 4 bytes address, 1: enable, 0:disable.
*/
uint32_t mem_cache_usr_addr_4byte:1;
/** mem_cache_flash_usr_cmd : R/W; bitpos: [2]; default: 0;
* For SPI0, cache read flash for user define command, 1: enable, 0:disable.
*/
uint32_t mem_cache_flash_usr_cmd:1;
/** mem_fdin_dual : R/W; bitpos: [3]; default: 0;
* For SPI0 flash, din phase apply 2 signals. 1: enable 0: disable. The bit is the
* same with spi_mem_s_fread_dio.
*/
uint32_t mem_fdin_dual:1;
/** mem_fdout_dual : R/W; bitpos: [4]; default: 0;
* For SPI0 flash, dout phase apply 2 signals. 1: enable 0: disable. The bit is the
* same with spi_mem_s_fread_dio.
*/
uint32_t mem_fdout_dual:1;
/** mem_faddr_dual : R/W; bitpos: [5]; default: 0;
* For SPI0 flash, address phase apply 2 signals. 1: enable 0: disable. The bit is
* the same with spi_mem_s_fread_dio.
*/
uint32_t mem_faddr_dual:1;
/** mem_fdin_quad : R/W; bitpos: [6]; default: 0;
* For SPI0 flash, din phase apply 4 signals. 1: enable 0: disable. The bit is the
* same with spi_mem_s_fread_qio.
*/
uint32_t mem_fdin_quad:1;
/** mem_fdout_quad : R/W; bitpos: [7]; default: 0;
* For SPI0 flash, dout phase apply 4 signals. 1: enable 0: disable. The bit is the
* same with spi_mem_s_fread_qio.
*/
uint32_t mem_fdout_quad:1;
/** mem_faddr_quad : R/W; bitpos: [8]; default: 0;
* For SPI0 flash, address phase apply 4 signals. 1: enable 0: disable. The bit is
* the same with spi_mem_s_fread_qio.
*/
uint32_t mem_faddr_quad:1;
uint32_t reserved_9:21;
/** same_aw_ar_addr_chk_en : R/W; bitpos: [30]; default: 1;
* Set this bit to check AXI read/write the same address region.
*/
@ -442,6 +484,34 @@ typedef union {
uint32_t val;
} spi_mem_s_clock_reg_t;
/** Type of mem_sram_clk register
* SPI0 external RAM clock control register
*/
typedef union {
struct {
/** mem_sclkcnt_l : R/W; bitpos: [7:0]; default: 3;
* For SPI0 external RAM interface, it must be equal to spi_mem_s_clkcnt_N.
*/
uint32_t mem_sclkcnt_l:8;
/** mem_sclkcnt_h : R/W; bitpos: [15:8]; default: 1;
* For SPI0 external RAM interface, it must be floor((spi_mem_s_clkcnt_N+1)/2-1).
*/
uint32_t mem_sclkcnt_h:8;
/** mem_sclkcnt_n : R/W; bitpos: [23:16]; default: 3;
* For SPI0 external RAM interface, it is the divider of spi_mem_s_clk. So spi_mem_s_clk
* frequency is system/(spi_mem_s_clkcnt_N+1)
*/
uint32_t mem_sclkcnt_n:8;
uint32_t reserved_24:7;
/** mem_sclk_equ_sysclk : R/W; bitpos: [31]; default: 0;
* For SPI0 external RAM interface, 1: spi_mem_s_clk is eqaul to system 0: spi_mem_s_clk
* is divided from system clock.
*/
uint32_t mem_sclk_equ_sysclk:1;
};
uint32_t val;
} spi_mem_s_sram_clk_reg_t;
/** Type of mem_clock_gate register
* SPI0 clock gate register
*/
@ -533,14 +603,162 @@ typedef union {
uint32_t val;
} spi_mem_s_user2_reg_t;
/** Type of mem_rd_status register
* SPI0 read control register.
*/
typedef union {
struct {
uint32_t reserved_0:16;
/** mem_wb_mode : R/W; bitpos: [23:16]; default: 0;
* Mode bits in the flash fast read mode it is combined with spi_mem_s_fastrd_mode bit.
*/
uint32_t mem_wb_mode:8;
uint32_t reserved_24:8;
};
uint32_t val;
} spi_mem_s_rd_status_reg_t;
/** Group: External RAM Control and configuration registers */
/** Type of mem_cache_sctrl register
* SPI0 external RAM control register
*/
typedef union {
struct {
/** mem_cache_usr_saddr_4byte : R/W; bitpos: [0]; default: 0;
* For SPI0, In the external RAM mode, cache read flash with 4 bytes command, 1:
* enable, 0:disable.
*/
uint32_t mem_cache_usr_saddr_4byte:1;
/** mem_usr_sram_dio : R/W; bitpos: [1]; default: 0;
* For SPI0, In the external RAM mode, spi dual I/O mode enable, 1: enable, 0:disable
*/
uint32_t mem_usr_sram_dio:1;
/** mem_usr_sram_qio : R/W; bitpos: [2]; default: 0;
* For SPI0, In the external RAM mode, spi quad I/O mode enable, 1: enable, 0:disable
*/
uint32_t mem_usr_sram_qio:1;
/** mem_usr_wr_sram_dummy : R/W; bitpos: [3]; default: 0;
* For SPI0, In the external RAM mode, it is the enable bit of dummy phase for write
* operations.
*/
uint32_t mem_usr_wr_sram_dummy:1;
/** mem_usr_rd_sram_dummy : R/W; bitpos: [4]; default: 1;
* For SPI0, In the external RAM mode, it is the enable bit of dummy phase for read
* operations.
*/
uint32_t mem_usr_rd_sram_dummy:1;
/** mem_cache_sram_usr_rcmd : R/W; bitpos: [5]; default: 1;
* For SPI0, In the external RAM mode cache read external RAM for user define command.
*/
uint32_t mem_cache_sram_usr_rcmd:1;
/** mem_sram_rdummy_cyclelen : R/W; bitpos: [11:6]; default: 1;
* For SPI0, In the external RAM mode, it is the length in bits of read dummy phase.
* The register value shall be (bit_num-1).
*/
uint32_t mem_sram_rdummy_cyclelen:6;
uint32_t reserved_12:2;
/** mem_sram_addr_bitlen : R/W; bitpos: [19:14]; default: 23;
* For SPI0, In the external RAM mode, it is the length in bits of address phase. The
* register value shall be (bit_num-1).
*/
uint32_t mem_sram_addr_bitlen:6;
/** mem_cache_sram_usr_wcmd : R/W; bitpos: [20]; default: 1;
* For SPI0, In the external RAM mode cache write sram for user define command
*/
uint32_t mem_cache_sram_usr_wcmd:1;
/** mem_sram_oct : R/W; bitpos: [21]; default: 0;
* reserved
*/
uint32_t mem_sram_oct:1;
/** mem_sram_wdummy_cyclelen : R/W; bitpos: [27:22]; default: 1;
* For SPI0, In the external RAM mode, it is the length in bits of write dummy phase.
* The register value shall be (bit_num-1).
*/
uint32_t mem_sram_wdummy_cyclelen:6;
uint32_t reserved_28:4;
};
uint32_t val;
} spi_mem_s_cache_sctrl_reg_t;
/** Type of mem_sram_cmd register
* SPI0 external RAM mode control register
*/
typedef union {
struct {
uint32_t reserved_0:24;
/** mem_sclk_mode : R/W; bitpos: [1:0]; default: 0;
* SPI clock mode bits. 0: SPI clock is off when CS inactive 1: SPI clock is delayed
* one cycle after CS inactive 2: SPI clock is delayed two cycles after CS inactive 3:
* SPI clock is always on.
*/
uint32_t mem_sclk_mode:2;
/** mem_swb_mode : R/W; bitpos: [9:2]; default: 0;
* Mode bits in the external RAM fast read mode it is combined with
* spi_mem_s_fastrd_mode bit.
*/
uint32_t mem_swb_mode:8;
/** mem_sdin_dual : R/W; bitpos: [10]; default: 0;
* For SPI0 external RAM , din phase apply 2 signals. 1: enable 0: disable. The bit is
* the same with spi_mem_s_usr_sram_dio.
*/
uint32_t mem_sdin_dual:1;
/** mem_sdout_dual : R/W; bitpos: [11]; default: 0;
* For SPI0 external RAM , dout phase apply 2 signals. 1: enable 0: disable. The bit
* is the same with spi_mem_s_usr_sram_dio.
*/
uint32_t mem_sdout_dual:1;
/** mem_saddr_dual : R/W; bitpos: [12]; default: 0;
* For SPI0 external RAM , address phase apply 2 signals. 1: enable 0: disable. The
* bit is the same with spi_mem_s_usr_sram_dio.
*/
uint32_t mem_saddr_dual:1;
uint32_t reserved_13:1;
/** mem_sdin_quad : R/W; bitpos: [14]; default: 0;
* For SPI0 external RAM , din phase apply 4 signals. 1: enable 0: disable. The bit is
* the same with spi_mem_s_usr_sram_qio.
*/
uint32_t mem_sdin_quad:1;
/** mem_sdout_quad : R/W; bitpos: [15]; default: 0;
* For SPI0 external RAM , dout phase apply 4 signals. 1: enable 0: disable. The bit
* is the same with spi_mem_s_usr_sram_qio.
*/
uint32_t mem_sdout_quad:1;
/** mem_saddr_quad : R/W; bitpos: [16]; default: 0;
* For SPI0 external RAM , address phase apply 4 signals. 1: enable 0: disable. The
* bit is the same with spi_mem_s_usr_sram_qio.
*/
uint32_t mem_saddr_quad:1;
/** mem_scmd_quad : R/W; bitpos: [17]; default: 0;
* For SPI0 external RAM , cmd phase apply 4 signals. 1: enable 0: disable. The bit is
* the same with spi_mem_s_usr_sram_qio.
*/
uint32_t mem_scmd_quad:1;
/** mem_sdin_oct : R/W; bitpos: [18]; default: 0;
* For SPI0 external RAM , din phase apply 8 signals. 1: enable 0: disable.
*/
uint32_t mem_sdin_oct:1;
/** mem_sdout_oct : R/W; bitpos: [19]; default: 0;
* For SPI0 external RAM , dout phase apply 8 signals. 1: enable 0: disable.
*/
uint32_t mem_sdout_oct:1;
/** mem_saddr_oct : R/W; bitpos: [20]; default: 0;
* For SPI0 external RAM , address phase apply 4 signals. 1: enable 0: disable.
*/
uint32_t mem_saddr_oct:1;
/** mem_scmd_oct : R/W; bitpos: [21]; default: 0;
* For SPI0 external RAM , cmd phase apply 8 signals. 1: enable 0: disable.
*/
uint32_t mem_scmd_oct:1;
/** mem_sdummy_rin : R/W; bitpos: [22]; default: 1;
* In the dummy phase of a MSPI read data transfer when accesses to external RAM, the
* signal level of SPI bus is output by the MSPI controller.
*/
uint32_t mem_sdummy_rin:1;
/** mem_sdummy_wout : R/W; bitpos: [23]; default: 1;
* In the dummy phase of a MSPI write data transfer when accesses to external RAM, the
* signal level of SPI bus is output by the MSPI controller.
*/
uint32_t mem_sdummy_wout:1;
/** smem_wdummy_dqs_always_out : R/W; bitpos: [24]; default: 0;
* In the dummy phase of an MSPI write data transfer when accesses to external RAM,
* the level of SPI_DQS is output by the MSPI controller.
@ -551,7 +769,15 @@ typedef union {
* the level of SPI_IO[7:0] is output by the MSPI controller.
*/
uint32_t smem_wdummy_always_out:1;
uint32_t reserved_26:4;
/** mem_sdin_hex : R/W; bitpos: [26]; default: 0;
* For SPI0 external RAM , din phase apply 16 signals. 1: enable 0: disable.
*/
uint32_t mem_sdin_hex:1;
/** mem_sdout_hex : R/W; bitpos: [27]; default: 0;
* For SPI0 external RAM , dout phase apply 16 signals. 1: enable 0: disable.
*/
uint32_t mem_sdout_hex:1;
uint32_t reserved_28:2;
/** smem_dqs_ie_always_on : R/W; bitpos: [30]; default: 0;
* When accesses to external RAM, 1: the IE signals of pads connected to SPI_DQS are
* always 1. 0: Others.
@ -566,6 +792,46 @@ typedef union {
uint32_t val;
} spi_mem_s_sram_cmd_reg_t;
/** Type of mem_sram_drd_cmd register
* SPI0 external RAM DDR read command control register
*/
typedef union {
struct {
/** mem_cache_sram_usr_rd_cmd_value : R/W; bitpos: [15:0]; default: 0;
* For SPI0,When cache mode is enable it is the read command value of command phase
* for sram.
*/
uint32_t mem_cache_sram_usr_rd_cmd_value:16;
uint32_t reserved_16:12;
/** mem_cache_sram_usr_rd_cmd_bitlen : R/W; bitpos: [31:28]; default: 0;
* For SPI0,When cache mode is enable it is the length in bits of command phase for
* sram. The register value shall be (bit_num-1).
*/
uint32_t mem_cache_sram_usr_rd_cmd_bitlen:4;
};
uint32_t val;
} spi_mem_s_sram_drd_cmd_reg_t;
/** Type of mem_sram_dwr_cmd register
* SPI0 external RAM DDR write command control register
*/
typedef union {
struct {
/** mem_cache_sram_usr_wr_cmd_value : R/W; bitpos: [15:0]; default: 0;
* For SPI0,When cache mode is enable it is the write command value of command phase
* for sram.
*/
uint32_t mem_cache_sram_usr_wr_cmd_value:16;
uint32_t reserved_16:12;
/** mem_cache_sram_usr_wr_cmd_bitlen : R/W; bitpos: [31:28]; default: 0;
* For SPI0,When cache mode is enable it is the in bits of command phase for sram.
* The register value shall be (bit_num-1).
*/
uint32_t mem_cache_sram_usr_wr_cmd_bitlen:4;
};
uint32_t val;
} spi_mem_s_sram_dwr_cmd_reg_t;
/** Type of smem_ddr register
* SPI0 external RAM DDR mode control register
*/
@ -969,106 +1235,106 @@ typedef union {
/** Group: PMS control and configuration registers */
/** Type of fmem_pmsn_attr register
* MSPI flash PMS section n attribute register
* MSPI flash PMS section $n attribute register
*/
typedef union {
struct {
/** fmem_pmsn_rd_attr : R/W; bitpos: [0]; default: 1;
* 1: SPI1 flash PMS section n read accessible. 0: Not allowed.
/** fmem_pms_rd_attr : R/W; bitpos: [0]; default: 1;
* 1: SPI1 flash PMS section $n read accessible. 0: Not allowed.
*/
uint32_t fmem_pmsn_rd_attr:1;
/** fmem_pmsn_wr_attr : R/W; bitpos: [1]; default: 1;
* 1: SPI1 flash PMS section n write accessible. 0: Not allowed.
uint32_t fmem_pms_rd_attr:1;
/** fmem_pms_wr_attr : R/W; bitpos: [1]; default: 1;
* 1: SPI1 flash PMS section $n write accessible. 0: Not allowed.
*/
uint32_t fmem_pmsn_wr_attr:1;
/** fmem_pmsn_ecc : R/W; bitpos: [2]; default: 0;
* SPI1 flash PMS section n ECC mode, 1: enable ECC mode. 0: Disable it. The flash PMS
* section n is configured by registers SPI_MEM_S_FMEM_PMSn_ADDR_REG and
* SPI_MEM_S_FMEM_PMSn_SIZE_REG.
uint32_t fmem_pms_wr_attr:1;
/** fmem_pms_ecc : R/W; bitpos: [2]; default: 0;
* SPI1 flash PMS section $n ECC mode, 1: enable ECC mode. 0: Disable it. The flash
* PMS section $n is configured by registers SPI_MEM_S_FMEM_PMS$n_ADDR_REG and
* SPI_MEM_S_FMEM_PMS$n_SIZE_REG.
*/
uint32_t fmem_pmsn_ecc:1;
uint32_t fmem_pms_ecc:1;
uint32_t reserved_3:29;
};
uint32_t val;
} spi_mem_s_fmem_pmsn_attr_reg_t;
/** Type of fmem_pmsn_addr register
* SPI1 flash PMS section n start address register
* SPI1 flash PMS section $n start address register
*/
typedef union {
struct {
/** fmem_pmsn_addr_s : R/W; bitpos: [26:0]; default: 0;
* SPI1 flash PMS section n start address value
/** fmem_pms_addr_s : R/W; bitpos: [26:0]; default: 0;
* SPI1 flash PMS section $n start address value
*/
uint32_t fmem_pmsn_addr_s:27;
uint32_t fmem_pms_addr_s:27;
uint32_t reserved_27:5;
};
uint32_t val;
} spi_mem_s_fmem_pmsn_addr_reg_t;
/** Type of fmem_pmsn_size register
* SPI1 flash PMS section n start address register
* SPI1 flash PMS section $n start address register
*/
typedef union {
struct {
/** fmem_pmsn_size : R/W; bitpos: [14:0]; default: 4096;
* SPI1 flash PMS section n address region is (SPI_MEM_S_FMEM_PMSn_ADDR_S,
* SPI_MEM_S_FMEM_PMSn_ADDR_S + SPI_MEM_S_FMEM_PMSn_SIZE)
/** fmem_pms_size : R/W; bitpos: [14:0]; default: 4096;
* SPI1 flash PMS section $n address region is (SPI_MEM_S_FMEM_PMS$n_ADDR_S,
* SPI_MEM_S_FMEM_PMS$n_ADDR_S + SPI_MEM_S_FMEM_PMS$n_SIZE)
*/
uint32_t fmem_pmsn_size:15;
uint32_t fmem_pms_size:15;
uint32_t reserved_15:17;
};
uint32_t val;
} spi_mem_s_fmem_pmsn_size_reg_t;
/** Type of smem_pmsn_attr register
* SPI1 flash PMS section n start address register
* SPI1 flash PMS section $n start address register
*/
typedef union {
struct {
/** smem_pmsn_rd_attr : R/W; bitpos: [0]; default: 1;
* 1: SPI1 external RAM PMS section n read accessible. 0: Not allowed.
/** smem_pms_rd_attr : R/W; bitpos: [0]; default: 1;
* 1: SPI1 external RAM PMS section $n read accessible. 0: Not allowed.
*/
uint32_t smem_pmsn_rd_attr:1;
/** smem_pmsn_wr_attr : R/W; bitpos: [1]; default: 1;
* 1: SPI1 external RAM PMS section n write accessible. 0: Not allowed.
uint32_t smem_pms_rd_attr:1;
/** smem_pms_wr_attr : R/W; bitpos: [1]; default: 1;
* 1: SPI1 external RAM PMS section $n write accessible. 0: Not allowed.
*/
uint32_t smem_pmsn_wr_attr:1;
/** smem_pmsn_ecc : R/W; bitpos: [2]; default: 0;
* SPI1 external RAM PMS section n ECC mode, 1: enable ECC mode. 0: Disable it. The
* external RAM PMS section n is configured by registers SPI_MEM_S_SMEM_PMSn_ADDR_REG and
* SPI_MEM_S_SMEM_PMSn_SIZE_REG.
uint32_t smem_pms_wr_attr:1;
/** smem_pms_ecc : R/W; bitpos: [2]; default: 0;
* SPI1 external RAM PMS section $n ECC mode, 1: enable ECC mode. 0: Disable it. The
* external RAM PMS section $n is configured by registers SPI_MEM_S_SMEM_PMS$n_ADDR_REG and
* SPI_MEM_S_SMEM_PMS$n_SIZE_REG.
*/
uint32_t smem_pmsn_ecc:1;
uint32_t smem_pms_ecc:1;
uint32_t reserved_3:29;
};
uint32_t val;
} spi_mem_s_smem_pmsn_attr_reg_t;
/** Type of smem_pmsn_addr register
* SPI1 external RAM PMS section n start address register
* SPI1 external RAM PMS section $n start address register
*/
typedef union {
struct {
/** smem_pmsn_addr_s : R/W; bitpos: [26:0]; default: 0;
* SPI1 external RAM PMS section n start address value
/** smem_pms_addr_s : R/W; bitpos: [26:0]; default: 0;
* SPI1 external RAM PMS section $n start address value
*/
uint32_t smem_pmsn_addr_s:27;
uint32_t smem_pms_addr_s:27;
uint32_t reserved_27:5;
};
uint32_t val;
} spi_mem_s_smem_pmsn_addr_reg_t;
/** Type of smem_pmsn_size register
* SPI1 external RAM PMS section n start address register
* SPI1 external RAM PMS section $n start address register
*/
typedef union {
struct {
/** smem_pmsn_size : R/W; bitpos: [14:0]; default: 4096;
* SPI1 external RAM PMS section n address region is (SPI_MEM_S_SMEM_PMSn_ADDR_S,
* SPI_MEM_S_SMEM_PMSn_ADDR_S + SPI_MEM_S_SMEM_PMSn_SIZE)
/** smem_pms_size : R/W; bitpos: [14:0]; default: 4096;
* SPI1 external RAM PMS section $n address region is (SPI_MEM_S_SMEM_PMS$n_ADDR_S,
* SPI_MEM_S_SMEM_PMS$n_ADDR_S + SPI_MEM_S_SMEM_PMS$n_SIZE)
*/
uint32_t smem_pmsn_size:15;
uint32_t smem_pms_size:15;
uint32_t reserved_15:17;
};
uint32_t val;
@ -2160,7 +2426,14 @@ typedef union {
* MMU PSRAM aux control register
*/
uint32_t mem_aux_ctrl:14;
uint32_t reserved_30:2;
/** mem_rdn_ena : R/W; bitpos: [30]; default: 0;
* ECO register enable bit
*/
uint32_t mem_rdn_ena:1;
/** mem_rdn_result : RO; bitpos: [31]; default: 0;
* MSPI module clock domain and AXI clock domain ECO register result register
*/
uint32_t mem_rdn_result:1;
};
uint32_t val;
} spi_mem_s_mmu_power_ctrl_reg_t;
@ -2195,6 +2468,34 @@ typedef union {
} spi_mem_s_dpa_ctrl_reg_t;
/** Group: ECO registers */
/** Type of mem_registerrnd_eco_high register
* MSPI ECO high register
*/
typedef union {
struct {
/** mem_registerrnd_eco_high : R/W; bitpos: [31:0]; default: 892;
* ECO high register
*/
uint32_t mem_registerrnd_eco_high:32;
};
uint32_t val;
} spi_mem_s_registerrnd_eco_high_reg_t;
/** Type of mem_registerrnd_eco_low register
* MSPI ECO low register
*/
typedef union {
struct {
/** mem_registerrnd_eco_low : R/W; bitpos: [31:0]; default: 892;
* ECO low register
*/
uint32_t mem_registerrnd_eco_low:32;
};
uint32_t val;
} spi_mem_s_registerrnd_eco_low_reg_t;
/** Group: Version control register */
/** Type of mem_date register
* SPI0 version control register
@ -2211,7 +2512,7 @@ typedef union {
} spi_mem_s_date_reg_t;
typedef struct spi_mem_s_dev_s {
typedef struct spi_mem_s_dev_t {
volatile spi_mem_s_cmd_reg_t mem_cmd;
uint32_t reserved_004;
volatile spi_mem_s_ctrl_reg_t mem_ctrl;
@ -2221,13 +2522,17 @@ typedef struct spi_mem_s_dev_s {
volatile spi_mem_s_user_reg_t mem_user;
volatile spi_mem_s_user1_reg_t mem_user1;
volatile spi_mem_s_user2_reg_t mem_user2;
uint32_t reserved_024[4];
uint32_t reserved_024[2];
volatile spi_mem_s_rd_status_reg_t mem_rd_status;
uint32_t reserved_030;
volatile spi_mem_s_misc_reg_t mem_misc;
uint32_t reserved_038;
volatile spi_mem_s_cache_fctrl_reg_t mem_cache_fctrl;
uint32_t reserved_040;
volatile spi_mem_s_cache_sctrl_reg_t mem_cache_sctrl;
volatile spi_mem_s_sram_cmd_reg_t mem_sram_cmd;
uint32_t reserved_048[3];
volatile spi_mem_s_sram_drd_cmd_reg_t mem_sram_drd_cmd;
volatile spi_mem_s_sram_dwr_cmd_reg_t mem_sram_dwr_cmd;
volatile spi_mem_s_sram_clk_reg_t mem_sram_clk;
volatile spi_mem_s_fsm_reg_t mem_fsm;
uint32_t reserved_058[26];
volatile spi_mem_s_int_ena_reg_t mem_int_ena;
@ -2282,10 +2587,14 @@ typedef struct spi_mem_s_dev_s {
volatile spi_mem_s_mmu_item_index_reg_t mem_mmu_item_index;
volatile spi_mem_s_mmu_power_ctrl_reg_t mem_mmu_power_ctrl;
volatile spi_mem_s_dpa_ctrl_reg_t mem_dpa_ctrl;
uint32_t reserved_38c[28];
uint32_t reserved_38c[25];
volatile spi_mem_s_registerrnd_eco_high_reg_t mem_registerrnd_eco_high;
volatile spi_mem_s_registerrnd_eco_low_reg_t mem_registerrnd_eco_low;
uint32_t reserved_3f8;
volatile spi_mem_s_date_reg_t mem_date;
} spi_mem_s_dev_t;
extern spi_mem_s_dev_t SPIMEM2;
#ifndef __cplusplus
_Static_assert(sizeof(spi_mem_s_dev_t) == 0x400, "Invalid size of spi_mem_s_dev_t structure");

View File

@ -12,6 +12,8 @@ PROVIDE ( UART3 = 0x500CD000 );
PROVIDE ( UART4 = 0x500CE000 );
PROVIDE ( SPIMEM0 = 0x5008C000 );
PROVIDE ( SPIMEM1 = 0x5008D000 );
PROVIDE ( SPIMEM2 = 0x5008E000 );
PROVIDE ( SPIMEM3 = 0x5008F000 );
PROVIDE ( I2C0 = 0x500C4000 );
PROVIDE ( I2C1 = 0x500C5000 );
PROVIDE ( UHCI0 = 0x500DF000 );

View File

@ -31,3 +31,9 @@ components/spi_flash/test_apps/mspi_test:
disable:
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_SUPPORTED != 1
- if: CONFIG_NAME == "psram" and IDF_TARGET in ["esp32p4"]
temporary: true
reason: not supported yet #TODO: IDF-7499 for p4
- if: CONFIG_NAME == "xip_psram" and IDF_TARGET in ["esp32p4"]
temporary: true
reason: not supported yet #TODO: IDF-7556 for p4

View File

@ -254,3 +254,6 @@ examples/system/xip_from_psram:
disable:
- if: IDF_TARGET == "esp32"
reason: target esp32 doesn't support this feature.
- if: IDF_TARGET == "esp32p4"
temporary: true
reason: not supported on p4 #TODO: IDF-7556