Merge branch 'feature/add_opi_flash_psram_support' into 'master'

spi flash: opi flash psram support and spi timing tuning  support on 727

Closes IDF-3097

See merge request espressif/esp-idf!12946
This commit is contained in:
Michael (XIAO Xufeng)
2021-06-28 01:59:19 +00:00
26 changed files with 1752 additions and 145 deletions

View File

@@ -16,7 +16,7 @@ else()
"esp_crypto_lock.c"
"memprot.c"
"spiram.c"
"spiram_psram.c")
"spi_timing_config.c")
set(include_dirs "include")
set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly
@@ -27,6 +27,12 @@ else()
set(priv_requires app_trace app_update bootloader_support log mbedtls nvs_flash pthread
spi_flash vfs espcoredump esp_common perfmon esp_timer esp_ipc)
if(CONFIG_SPIRAM_MODE_QUAD)
list(APPEND srcs "spiram_psram.c")
elseif(CONFIG_SPIRAM_MODE_OCT)
list(APPEND srcs "opiram_psram.c")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
REQUIRES "${requires}"

View File

@@ -169,8 +169,19 @@ menu "ESP32S3-Specific"
menu "SPI RAM config"
depends on ESP32S3_SPIRAM_SUPPORT
choice SPIRAM_MODE
prompt "Mode (QUAD/OCT) of SPI RAM chip in use"
default SPIRAM_MODE_QUAD
config SPIRAM_MODE_QUAD
bool "Quad Mode PSRAM"
config SPIRAM_MODE_OCT
bool "Octal Mode PSRAM"
endchoice
choice SPIRAM_TYPE
prompt "Type of SPI RAM chip in use"
prompt "Type of SPIRAM chip in use"
default SPIRAM_TYPE_AUTO
config SPIRAM_TYPE_AUTO
@@ -178,12 +189,14 @@ menu "ESP32S3-Specific"
config SPIRAM_TYPE_ESPPSRAM16
bool "ESP-PSRAM16 or APS1604"
depends on SPIRAM_MODE_QUAD
config SPIRAM_TYPE_ESPPSRAM32
bool "ESP-PSRAM32 or IS25WP032"
depends on SPIRAM_MODE_QUAD
config SPIRAM_TYPE_ESPPSRAM64
bool "ESP-PSRAM64 or LY68L6400"
bool "ESP-PSRAM64 , LY68L6400 or APS6408"
endchoice
config SPIRAM_SIZE
@@ -192,6 +205,8 @@ menu "ESP32S3-Specific"
default 2097152 if SPIRAM_TYPE_ESPPSRAM16
default 4194304 if SPIRAM_TYPE_ESPPSRAM32
default 8388608 if SPIRAM_TYPE_ESPPSRAM64
default 16777216 if SPIRAM_TYPE_ESPPSRAM128
default 33554432 if SPIRAM_TYPE_ESPPSRAM256
default 0
menu "PSRAM Clock and CS IO for ESP32S3"
@@ -235,10 +250,6 @@ menu "ESP32S3-Specific"
bool "80MHz clock speed"
config SPIRAM_SPEED_40M
bool "40Mhz clock speed"
config SPIRAM_SPEED_26M
bool "26Mhz clock speed"
config SPIRAM_SPEED_20M
bool "20Mhz clock speed"
endchoice
# insert non-chip-specific items here

View File

@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
//Octal FLASH: core clock 160M, module clock 40M, DTR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE {{1, 0, 0}, {0, 0, 0}, {2, 1, 1}, {2, 0, 1}, {2, 2, 2}, {2, 1, 2}, {1, 0, 1}, {0, 0, 1}}
#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE 8
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE 2
//Octal FLASH: core clock 160M, module clock 80M, DTR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{0, 0, 0}, {4, 2, 2}, {2, 1, 2}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 2, 3}, {2, 1, 3}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 2, 4}}
#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 14
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 1
//Octal FLASH: core clock 240M, module clock 120M, DTR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE {{0, 0, 0}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 1, 4}, {1, 0, 3}, {4, 0, 4}, {0, 0, 3}, {4, 1, 5}}
#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 14
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 1
//Octal FLASH: core clock 160M, module clock 80M, STR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE {{1, 0, 0}, {0, 0, 0}, {2, 1, 1}, {2, 0, 1}, {2, 2, 2}, {2, 1, 2}, {1, 0, 1}, {0, 0, 1}}
#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE 8
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE 2
//Octal FLASH: core clock 120M, module clock 120M, STR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {1, 0, 1}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {1, 0, 2}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {1, 0, 3}}
#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2
//Octal PSRAM: core clock 80M, module clock 40M, DTR mode
#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE {{1, 0, 0}, {2, 1, 1}, {2, 0, 1}, {0, 0, 0}, {3, 1, 1}, {3, 0, 1}, {1, 0, 1}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {3, 1, 2}, {3, 0, 2}}
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE 12
#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE 4
//Octal PSRAM: core clock 160M, module clock 80M, DTR mode
#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{1, 0, 0}, {0, 0, 0}, {3, 0, 1}, {1, 0, 1}, {0, 0, 1}, {3, 0, 2}, {1, 0, 2}, {0, 0, 2}, {3, 0, 3}, {1, 0, 3}, {0, 0, 3}, {3, 0, 4}, {1, 0, 4}, {0, 0, 4}}
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 14
#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 1

View File

@@ -0,0 +1,172 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_flash_partitions.h"
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/opi_flash.h"
#include "esp32s3/mspi_timing_tuning_configs.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SPI_TIMING_CONFIG_NUM_DEFAULT 20 //This should be larger than the max available timing config num
#define SPI_TIMING_TEST_DATA_LEN 64
#define SPI_TIMING_PSRAM_TEST_DATA_ADDR 0
#define SPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET
//-------------------------------------------FLASH Operation Mode and Corresponding Timing Tuning Parameter Table --------------------------------------//
#define SPI_TIMING_FLASH_DTR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR)
#define SPI_TIMING_FLASH_STR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_STR || CONFIG_ESPTOOLPY_FLASHMODE_OOUT_STR)
/* Determine A feasible core clock below: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ*/
//OCTAL FLASH
#if CONFIG_ESPTOOLPY_OCT_FLASH
// OCT FLASH 40M DTR
#if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_40M
_Static_assert(!CONFIG_ESPTOOLPY_FLASHFREQ_40M, "Octal FLASH 40MHz DDR is not supported. TODO: IDF-1630");
#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160
#endif
//OCT FLASH 80M DTR
#if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M
#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160
#endif
//OCT FLASH 120M DTR
#if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M
#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240
#endif
//OCT FLASH 80M STR
#if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M
#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160
#endif
//OCT FLASH 120M STR
#if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M
#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120
#endif
#endif //#if CONFIG_ESPTOOLPY_OCT_FLASH
/* QUAD FLASH Operation Mode should be added here if needed */
//---------------------------------------PSRAM Operation Mode and Corresponding Timing Tuning Parameter Table--------------------------------------//
#define SPI_TIMING_PSRAM_DTR_MODE 1 //Currently we only support DTR Octal PSRAM
#define SPI_TIMING_PSRAM_STR_MODE 0
//OCTAL PSRAM
#if CONFIG_SPIRAM_MODE_OCT
//OCT 40M PSRAM
#if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_40M
#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80
#endif
//OCT 80M PSRAM
#if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M
#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160
#endif
#endif //#if CONFIG_SPIRAM_MODE_OCT
/* QUAD PSRAM Operation Mode should be added here if needed */
//------------------------------------------Get the timing tuning config-----------------------------------------------//
#ifdef SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
//FLASH needs tuning, and it expects this core clock: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
#define SPI_TIMING_FLASH_NEEDS_TUNING 1
#endif
#ifdef SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
//PSRAM needs tuning, and it expects this core clock: SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
#define SPI_TIMING_PSRAM_NEEDS_TUNING 1
#endif
//If both FLASH and PSRAM need tuning, the core clock should be same
#if SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING
_Static_assert(SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ, "FLASH and PSRAM Mode configuration are not supported");
#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
//If only FLASH needs tuning, the core clock could be as FLASH expected
#elif SPI_TIMING_FLASH_NEEDS_TUNING && !SPI_TIMING_PSRAM_NEEDS_TUNING
#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
//If only PSRAM needs tuning, the core clock could be as PSRAM expected
#elif !SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING
#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
#else
#define SPI_TIMING_CORE_CLOCK_MHZ 80
#endif
//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------//
#define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \
(spi_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, \
.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 SPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
#define SPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode)
/**
* SPI timing tuning registers. The macro `SPI_TIMING_FLASH_CONFIG_TABLE` below is the corresponding register value table.
* Upper layer rely on these 3 registers to tune the timing.
*/
typedef struct {
uint8_t spi_din_mode; /*!< input signal delay mode*/
uint8_t spi_din_num; /*!< input signal delay number */
uint8_t extra_dummy_len; /*!< extra dummy length*/
} spi_timing_tuning_param_t;
typedef struct {
spi_timing_tuning_param_t tuning_config_table[SPI_TIMING_CONFIG_NUM_DEFAULT]; //available timing tuning configs
uint32_t available_config_num;
uint32_t default_config_id; //If tuning fails, we use this one as default
} spi_timing_config_t;
/**
* The SPI FLASH module clock and SPI PSRAM module clock is divided from the SPI core clock, core clock is from system clock:
*
* PLL ----| |---- FLASH Module Clock
* XTAL ----|----> Core Clock ---->|
* RTC8M ----| |---- PSRAM Module Clock
*
*/
typedef enum {
SPI_TIMING_CONFIG_CORE_CLOCK_80M,
SPI_TIMING_CONFIG_CORE_CLOCK_120M,
SPI_TIMING_CONFIG_CORE_CLOCK_160M,
SPI_TIMING_CONFIG_CORE_CLOCK_240M
} spi_timing_config_core_clock_t;
spi_timing_config_core_clock_t spi_timing_config_get_core_clock(void);
void spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_config_core_clock_t core_clock);
void spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv);
void spi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num);
void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy);
void spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len);
void spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv);
void spi_timing_config_psram_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num);
void spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy);
void spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len);
void spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,291 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "string.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "spiram_psram.h"
#include "esp32s3/rom/ets_sys.h"
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/opi_flash.h"
#include "esp32s3/rom/gpio.h"
#include "esp32s3/rom/cache.h"
#include "soc/io_mux_reg.h"
#include "soc/dport_reg.h"
#include "soc/apb_ctrl_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/efuse_reg.h"
#include "driver/gpio.h"
#include "driver/spi_common.h"
#include "driver/periph_ctrl.h"
#if CONFIG_SPIRAM_MODE_OCT
#include "soc/rtc.h"
#include "spi_flash_private.h"
#define OPI_PSRAM_SYNC_READ 0x0000
#define OPI_PSRAM_SYNC_WRITE 0x8080
#define OPI_PSRAM_REG_READ 0x4040
#define OPI_PSRAM_REG_WRITE 0xC0C0
#define OCT_PSRAM_RD_CMD_BITLEN 16
#define OCT_PSRAM_WR_CMD_BITLEN 16
#define OCT_PSRAM_ADDR_BITLEN 32
#define OCT_PSRAM_RD_DUMMY_BITLEN (2*(10-1))
#define OCT_PSRAM_WR_DUMMY_BITLEN (2*(5-1))
#define OCT_PSRAM_CS1_IO 26
typedef struct {
union {
struct {
uint8_t drive_str: 2;
uint8_t read_latency: 3;
uint8_t lt: 1;
uint8_t rsvd0_1: 2;
};
uint8_t val;
} mr0;
union {
struct {
uint8_t vendor_id: 5;
uint8_t rsvd0_2: 3;
};
uint8_t val;
} mr1;
union {
struct {
uint8_t density: 3;
uint8_t dev_id: 2;
uint8_t rsvd1_2: 2;
uint8_t gb: 1;
};
uint8_t val;
} mr2;
union {
struct {
uint8_t rsvd3_7: 5;
uint8_t srf: 1;
uint8_t vcc: 1;
uint8_t rsvd0: 1;
};
uint8_t val;
} mr3;
union {
struct {
uint8_t pasr: 3;
uint8_t rf: 1;
uint8_t rsvd3: 1;
uint8_t wr_latency: 3;
};
uint8_t val;
} mr4;
union {
struct {
uint8_t bl: 2;
uint8_t bt: 1;
uint8_t rsvd0_4: 5;
};
uint8_t val;
} mr8;
} opi_psram_mode_reg_t;
static const char* TAG = "opi psram";
static DRAM_ATTR psram_size_t s_psram_size;
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
/**
* Initialise mode registers of the PSRAM
*/
static void IRAM_ATTR s_init_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *mode_reg_config)
{
esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
int cmd_len = 16;
uint32_t addr = 0x0;
int addr_bit_len = 32;
int dummy = OCT_PSRAM_RD_DUMMY_BITLEN;
opi_psram_mode_reg_t mode_reg = {0};
int data_bit_len = 16;
//read
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
dummy,
NULL, 0,
&mode_reg.mr0.val, data_bit_len,
BIT(1),
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
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
0,
&mode_reg.mr0.val, 16,
NULL, 0,
BIT(1),
false);
}
static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *out_reg)
{
esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
int cmd_len = 16;
int addr_bit_len = 32;
int dummy = OCT_PSRAM_RD_DUMMY_BITLEN;
int data_bit_len = 16;
//Read MR0 register
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ, cmd_len,
0x0, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr0.val, data_bit_len,
BIT(1),
false);
//Read MR2 register
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ, cmd_len,
0x2, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr2.val, data_bit_len,
BIT(1),
false);
//Read MR4 register
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ, cmd_len,
0x4, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr4.val, data_bit_len,
BIT(1),
false);
//Read MR8 register
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ, cmd_len,
0x8, addr_bit_len,
dummy,
NULL, 0,
&out_reg->mr8.val, data_bit_len,
BIT(1),
false);
}
static void IRAM_ATTR s_print_psram_info(opi_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, "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.gb, reg_val->mr2.gb == 1 ? "Pass" : "Fail");
ESP_EARLY_LOGI(TAG, "Latency : 0x%02x (%s)", reg_val->mr0.lt, reg_val->mr0.lt == 1 ? "Fixed" : "Variable");
ESP_EARLY_LOGI(TAG, "VCC : 0x%02x (%s)", reg_val->mr3.vcc, reg_val->mr3.vcc == 1 ? "3V" : "1.8V");
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 : 1024);
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);
}
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)
{
// enable CS signal
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1);
//enter MSPI slow mode to init PSRAM device registers
spi_timing_enter_mspi_low_speed_mode();
//set to variable dummy mode
SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
esp_rom_spi_set_dtr_swap_mode(1, false, false);
#endif
//Set PSRAM read latency and drive strength
static DRAM_ATTR opi_psram_mode_reg_t mode_reg = {0};
mode_reg.mr0.lt = 1;
mode_reg.mr0.read_latency = 2;
mode_reg.mr0.drive_str = 0;
s_init_psram_mode_reg(1, &mode_reg);
//Print PSRAM info
s_get_psram_mode_reg(1, &mode_reg);
s_print_psram_info(&mode_reg);
s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_32MBITS :
mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_64MBITS :
mode_reg.mr2.density == 0x5 ? PSRAM_SIZE_128MBITS :
mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_256MBITS : 0;
#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
esp_rom_spi_set_dtr_swap_mode(1, true, true);
#endif
spi_timing_psram_tuning();
spi_timing_enter_mspi_high_speed_mode();
/**
* Tuning may change SPI1 regs, whereas legacy spi_flash APIs rely on these regs.
* This function is to restore SPI1 init state.
*/
spi_flash_set_rom_required_regs();
psram_cache_init(mode, vaddrmode);
return ESP_OK;
}
//register initialization for sram cache params and r/w commands
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
{
//Config Write CMD phase for SPI0 to access PSRAM
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M);
SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, OCT_PSRAM_WR_CMD_BITLEN - 1, SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE, OPI_PSRAM_SYNC_WRITE, SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE_S);
//Config Read CMD phase for SPI0 to access PSRAM
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_RCMD_M);
SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V, OCT_PSRAM_RD_CMD_BITLEN - 1, SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_V, OPI_PSRAM_SYNC_READ, SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_S);
//Config ADDR phase
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_ADDR_BITLEN_V, OCT_PSRAM_ADDR_BITLEN - 1, SPI_MEM_SRAM_ADDR_BITLEN_S);
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_USR_SCMD_4BYTE_M);
//Config RD/WR Dummy phase
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M | SPI_MEM_USR_WR_SRAM_DUMMY_M);
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, OCT_PSRAM_RD_DUMMY_BITLEN - 1, SPI_MEM_SRAM_RDUMMY_CYCLELEN_S);
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_DDR_REG(0), SPI_MEM_SPI_SMEM_VAR_DUMMY_M);
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_WDUMMY_CYCLELEN_V, OCT_PSRAM_WR_DUMMY_BITLEN - 1, SPI_MEM_SRAM_WDUMMY_CYCLELEN_S);
CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_DDR_REG(0), SPI_MEM_SPI_SMEM_DDR_WDAT_SWP_M | SPI_MEM_SPI_SMEM_DDR_RDAT_SWP_M);
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_DDR_REG(0), SPI_MEM_SPI_SMEM_DDR_EN_M);
SET_PERI_REG_MASK(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SDUMMY_OUT_M | SPI_MEM_SCMD_OCT_M | SPI_MEM_SADDR_OCT_M | SPI_MEM_SDOUT_OCT_M | SPI_MEM_SDIN_OCT_M);
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_OCT_M);
Cache_Resume_DCache(0);
}
psram_size_t psram_get_size()
{
return s_psram_size;
}
#endif //#if CONFIG_SPIRAM_MODE_OCT

View File

@@ -0,0 +1,197 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "string.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "soc/spi_mem_reg.h"
#include "esp32s3/spi_timing_config.h"
#define OPI_PSRAM_SYNC_READ 0x0000
#define OPI_PSRAM_SYNC_WRITE 0x8080
#define OCT_PSRAM_RD_DUMMY_NUM (2*(10-1))
#define OCT_PSRAM_WR_DUMMY_NUM (2*(5-1))
/////////////////////////////////////////TIMING TUNING IS NEEDED//////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING //If one of the FLASH / PSRAM or both of them need timing tuning, we should build following code
spi_timing_config_core_clock_t IRAM_ATTR spi_timing_config_get_core_clock(void)
{
switch (SPI_TIMING_CORE_CLOCK_MHZ) {
case 80:
return SPI_TIMING_CONFIG_CORE_CLOCK_80M;
case 120:
return SPI_TIMING_CONFIG_CORE_CLOCK_120M;
case 160:
return SPI_TIMING_CONFIG_CORE_CLOCK_160M;
case 240:
return SPI_TIMING_CONFIG_CORE_CLOCK_240M;
default:
abort();
}
}
void IRAM_ATTR spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_config_core_clock_t core_clock)
{
uint32_t reg_val = 0;
switch (core_clock) {
case SPI_TIMING_CONFIG_CORE_CLOCK_80M:
reg_val = 0;
break;
case SPI_TIMING_CONFIG_CORE_CLOCK_120M:
reg_val = 1;
break;
case SPI_TIMING_CONFIG_CORE_CLOCK_160M:
reg_val = 2;
break;
case SPI_TIMING_CONFIG_CORE_CLOCK_240M:
reg_val = 3;
break;
default:
abort();
}
REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(spi_num), SPI_MEM_CORE_CLK_SEL, reg_val);
}
//-------------------------------------FLASH timing tuning-------------------------------------//
void IRAM_ATTR spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv)
{
assert(freqdiv > 0);
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), SPI_MEM_CLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), freqbits);
}
}
void IRAM_ATTR spi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
{
uint32_t reg_val = 0;
reg_val = (REG_READ(SPI_MEM_DIN_MODE_REG(spi_num)) & (~(SPI_MEM_DIN0_MODE_M | SPI_MEM_DIN1_MODE_M | SPI_MEM_DIN2_MODE_M | SPI_MEM_DIN3_MODE_M | SPI_MEM_DIN4_MODE_M | SPI_MEM_DIN5_MODE_M | SPI_MEM_DIN6_MODE_M | SPI_MEM_DIN7_MODE_M | SPI_MEM_DINS_MODE_M)))
| (din_mode << SPI_MEM_DIN0_MODE_S) | (din_mode << SPI_MEM_DIN1_MODE_S) | (din_mode << SPI_MEM_DIN2_MODE_S) | (din_mode << SPI_MEM_DIN3_MODE_S)
| (din_mode << SPI_MEM_DIN4_MODE_S) | (din_mode << SPI_MEM_DIN5_MODE_S) | (din_mode << SPI_MEM_DIN6_MODE_S) | (din_mode << SPI_MEM_DIN7_MODE_S) | (din_mode << SPI_MEM_DINS_MODE_S);
REG_WRITE(SPI_MEM_DIN_MODE_REG(spi_num), reg_val);
reg_val = (REG_READ(SPI_MEM_DIN_NUM_REG(spi_num)) & (~(SPI_MEM_DIN0_NUM_M | SPI_MEM_DIN1_NUM_M | SPI_MEM_DIN2_NUM_M | SPI_MEM_DIN3_NUM_M | SPI_MEM_DIN4_NUM_M | SPI_MEM_DIN5_NUM_M | SPI_MEM_DIN6_NUM_M | SPI_MEM_DIN7_NUM_M | SPI_MEM_DINS_NUM_M)))
| (din_num << SPI_MEM_DIN0_NUM_S) | (din_num << SPI_MEM_DIN1_NUM_S) | (din_num << SPI_MEM_DIN2_NUM_S) | (din_num << SPI_MEM_DIN3_NUM_S)
| (din_num << SPI_MEM_DIN4_NUM_S) | (din_num << SPI_MEM_DIN5_NUM_S) | (din_num << SPI_MEM_DIN6_NUM_S) | (din_num << SPI_MEM_DIN7_NUM_S) | (din_num << SPI_MEM_DINS_NUM_S);
REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
}
void IRAM_ATTR spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
{
if (extra_dummy > 0) {
SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy,
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0,
SPI_MEM_EXTRA_DUMMY_CYCLELEN_S);
}
}
//-------------------------------------PSRAM timing tuning-------------------------------------//
void IRAM_ATTR spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv)
{
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv-1)<<SPI_MEM_SCLKCNT_N_S)) | (((freqdiv/2-1)<<SPI_MEM_SCLKCNT_H_S)) | ((freqdiv-1)<<SPI_MEM_SCLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), freqbits);
}
}
void IRAM_ATTR spi_timing_config_psram_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
{
uint32_t reg_val = 0;
reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_MODE_M | SPI_MEM_SPI_SMEM_DIN1_MODE_M | SPI_MEM_SPI_SMEM_DIN2_MODE_M | SPI_MEM_SPI_SMEM_DIN3_MODE_M | SPI_MEM_SPI_SMEM_DIN4_MODE_M | SPI_MEM_SPI_SMEM_DIN5_MODE_M | SPI_MEM_SPI_SMEM_DIN6_MODE_M | SPI_MEM_SPI_SMEM_DIN7_MODE_M | SPI_MEM_SPI_SMEM_DINS_MODE_M)))
| (din_mode << SPI_MEM_SPI_SMEM_DIN0_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN1_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN2_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN3_MODE_S)
| (din_mode << SPI_MEM_SPI_SMEM_DIN4_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN5_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN6_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN7_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DINS_MODE_S);
REG_WRITE(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num), reg_val);
reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_NUM_M | SPI_MEM_SPI_SMEM_DIN1_NUM_M | SPI_MEM_SPI_SMEM_DIN2_NUM_M | SPI_MEM_SPI_SMEM_DIN3_NUM_M | SPI_MEM_SPI_SMEM_DIN4_NUM_M | SPI_MEM_SPI_SMEM_DIN5_NUM_M | SPI_MEM_SPI_SMEM_DIN6_NUM_M | SPI_MEM_SPI_SMEM_DIN7_NUM_M | SPI_MEM_SPI_SMEM_DINS_NUM_M)))
| (din_num << SPI_MEM_SPI_SMEM_DIN0_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN1_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN2_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN3_NUM_S)
| (din_num << SPI_MEM_SPI_SMEM_DIN4_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN5_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN6_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN7_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DINS_NUM_S);
REG_WRITE(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num), reg_val);
}
void IRAM_ATTR spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
{
if (extra_dummy > 0) {
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy,
SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0,
SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S);
}
}
//-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------//
void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
{
#if CONFIG_ESPTOOLPY_OCT_FLASH
// note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
// but after we change the timing settings, we might not read correct idle status via RDSR.
// so, here we should use a read API that won't check idle status.
for (int i = 0; i < 16; i++) {
REG_WRITE(SPI_MEM_W0_REG(1) + i*4, 0);
}
esp_rom_opiflash_read_raw(addr, buf, len);
#else
abort();
#endif
}
void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len)
{
#if CONFIG_ESPTOOLPY_OCT_FLASH
uint32_t cmd = OPI_PSRAM_SYNC_WRITE;
int dummy = OCT_PSRAM_WR_DUMMY_NUM;
esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
cmd, 16,
addr, 32,
dummy,
buf, 8 * len,
NULL, 0,
BIT(1),
false);
#else
abort();
#endif
}
void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len)
{
#if CONFIG_ESPTOOLPY_OCT_FLASH
uint32_t cmd = OPI_PSRAM_SYNC_READ;
int dummy = OCT_PSRAM_RD_DUMMY_NUM;
esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
cmd, 16,
addr, 32,
dummy,
NULL, 0,
buf, 8 * len,
BIT(1),
false);
#else
abort();
#endif
}
#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING

View File

@@ -50,7 +50,7 @@ static const char *TAG = "spiram";
#define PSRAM_SPEED PSRAM_CACHE_S20M
#endif
static bool spiram_inited = false;
static bool s_spiram_inited = false;
/*
@@ -245,8 +245,7 @@ esp_err_t esp_spiram_init(void)
#endif
return r;
}
spiram_inited = true;
s_spiram_inited = true;
#if (CONFIG_SPIRAM_SIZE != -1)
if (esp_spiram_get_size() != CONFIG_SPIRAM_SIZE) {
ESP_EARLY_LOGE(TAG, "Expected %dKiB chip but found %dKiB chip. Bailing out..", CONFIG_SPIRAM_SIZE / 1024, esp_spiram_get_size() / 1024);
@@ -296,7 +295,7 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size)
size_t esp_spiram_get_size(void)
{
if (!spiram_inited) {
if (!s_spiram_inited) {
ESP_EARLY_LOGE(TAG, "SPI RAM not initialized");
abort();
}
@@ -311,6 +310,12 @@ size_t esp_spiram_get_size(void)
if (size == PSRAM_SIZE_64MBITS) {
return 8 * 1024 * 1024;
}
if (size == PSRAM_SIZE_128MBITS) {
return 16 * 1024 * 1024;
}
if (size == PSRAM_SIZE_256MBITS) {
return 32 * 1024 * 1024;
}
return CONFIG_SPIRAM_SIZE;
}

View File

@@ -45,7 +45,7 @@
#include "driver/periph_ctrl.h"
#include "bootloader_common.h"
#if CONFIG_SPIRAM
#if CONFIG_SPIRAM_MODE_QUAD
#include "soc/rtc.h"
static const char* TAG = "psram";

View File

@@ -28,9 +28,11 @@ typedef enum {
} psram_cache_mode_t;
typedef enum {
PSRAM_SIZE_16MBITS = 0,
PSRAM_SIZE_32MBITS = 1,
PSRAM_SIZE_64MBITS = 2,
PSRAM_SIZE_16MBITS = 0,
PSRAM_SIZE_32MBITS = 1,
PSRAM_SIZE_64MBITS = 2,
PSRAM_SIZE_128MBITS = 3,
PSRAM_SIZE_256MBITS = 4,
PSRAM_SIZE_MAX,
} psram_size_t;