Add SPIRAM to ESP32-S2

This commit is contained in:
Alan C. Assis 2022-03-17 16:00:22 -03:00 committed by Xiang Xiao
parent a66e8f20ee
commit c232be541c
15 changed files with 6253 additions and 14 deletions

View File

@ -92,7 +92,8 @@ config ESP32S2_INSTRUCTION_CACHE_LINE_SIZE
choice ESP32S2_DATA_CACHE_SIZE
prompt "Data cache size"
default ESP32S2_DATA_CACHE_0KB
default ESP32S2_DATA_CACHE_0KB if !ESP32S2_SPIRAM
default ESP32S2_DATA_CACHE_8KB if ESP32S2_SPIRAM
---help---
Data cache size to be set on application startup.
If you use 0KB data cache, the other 16KB will be added to the heap.
@ -100,6 +101,7 @@ choice ESP32S2_DATA_CACHE_SIZE
will be added to the heap.
config ESP32S2_DATA_CACHE_0KB
depends on !ESP32S2_SPIRAM
bool "No DATA CACHE"
---help---
Disable Data Cache
@ -442,6 +444,96 @@ endif
endmenu # SPI Flash Configuration
menu "SPI RAM Configuration"
depends on ESP32S2_SPIRAM
config ESP32S2_DEFAULT_PSRAM_CLK_IO
int "PSRAM CLK pin"
default 30
config ESP32S2_DEFAULT_PSRAM_CS_IO
int "PSRAM CS pin"
default 26
choice ESP32S2_SPIRAM_TYPE
prompt "Type of SPI RAM chip in use"
default ESP32S2_SPIRAM_TYPE_AUTO
config ESP32S2_SPIRAM_TYPE_AUTO
bool "Auto-detect"
config ESP32S2_SPIRAM_TYPE_ESPPSRAM32
bool "ESP-PSRAM32 or IS25WP032"
config ESP32S2_SPIRAM_TYPE_ESPPSRAM64
bool "ESP-PSRAM64 or LY68L6400"
endchoice # ESP32S2_SPIRAM_TYPE
config ESP32S2_SPIRAM_SIZE
int
default -1 if ESP32S2_SPIRAM_TYPE_AUTO
default 4194304 if ESP32S2_SPIRAM_TYPE_ESPPSRAM32
default 8388608 if ESP32S2_SPIRAM_TYPE_ESPPSRAM64
default 0
config ESP32S2_SPIRAM_FETCH_INSTRUCTIONS
bool "Cache fetch instructions from SPI RAM"
default n
---help---
If enabled, instruction in flash will be copied into SPI RAM.
If ESP32S2_SPIRAM_RODATA is also enabled, you can run the instruction
when erasing or programming the flash.
config ESP32S2_SPIRAM_RODATA
bool "Cache load read only data from SPI RAM"
default n
---help---
If enabled, rodata in flash will be copied into SPI RAM.
If ESP32S2_SPIRAM_FETCH_INSTRUCTIONS is also enabled,
you can run the instruction when erasing or programming the
flash.
choice ESP32S2_SPIRAM_SPEED
prompt "Set RAM clock speed"
default ESP32S2_SPIRAM_SPEED_40M
---help---
Select the speed for the SPI RAM chip.
config ESP32S2_SPIRAM_SPEED_40M
bool "40MHz clock speed"
config ESP32S2_SPIRAM_SPEED_80M
bool "80MHz clock speed"
endchoice # ESP32S2_SPIRAM_SPEED
config ESP32S2_SPIRAM_SPEED
int
default 80 if ESP32S2_SPIRAM_SPEED_80M
default 40 if ESP32S2_SPIRAM_SPEED_40M
config ESP32S2_SPIRAM_BOOT_INIT
bool "Initialize SPI RAM during startup"
default "y"
---help---
If this is enabled, the SPI RAM will be enabled during initial
boot. Unless you have specific requirements, you'll want to leave
this enabled so memory allocated during boot-up can also be
placed in SPI RAM.
config ESP32S2_SPIRAM_IGNORE_NOTFOUND
bool "Ignore PSRAM when not found"
default "n"
depends on ESP32S2_SPIRAM_BOOT_INIT && !BOOT_SDRAM_DATA
---help---
Normally, if PSRAM initialization is enabled during compile time
but not found at runtime, it is seen as an error making the CPU
panic. If this is enabled, booting will complete but no PSRAM
will be available.
endmenu # SPI RAM Configuration
menu "Real-Time Timer Configuration"
depends on ESP32S2_RT_TIMER

View File

@ -110,3 +110,8 @@ ifeq ($(CONFIG_ONESHOT),y)
CHIP_CSRCS += esp32s2_oneshot_lowerhalf.c
endif
endif
ifeq ($(CONFIG_ESP32S2_SPIRAM),y)
CHIP_CSRCS += esp32s2_spiram.c
CHIP_CSRCS += esp32s2_psram.c
endif

View File

@ -0,0 +1,725 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_psram.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include "esp32s2_gpio.h"
#include "esp32s2_psram.h"
#include "rom/esp32s2_spiflash.h"
#include "rom/esp32s2_opi_flash.h"
#include "hardware/esp32s2_efuse.h"
#include "hardware/esp32s2_spi.h"
#include "hardware/esp32s2_spi_mem_reg.h"
#include "hardware/esp32s2_iomux.h"
#include "hardware/esp32s2_gpio_sigmap.h"
/****************************************************************************
* Pre-processor Prototypes
****************************************************************************/
/* EFUSE */
#define ESP_ROM_EFUSE_FLASH_DEFAULT_SPI (0)
/* Commands for PSRAM chip */
#define PSRAM_READ 0x03
#define PSRAM_FAST_READ 0x0B
#define PSRAM_FAST_READ_QUAD 0xEB
#define PSRAM_WRITE 0x02
#define PSRAM_QUAD_WRITE 0x38
#define PSRAM_ENTER_QMODE 0x35
#define PSRAM_EXIT_QMODE 0xF5
#define PSRAM_RESET_EN 0x66
#define PSRAM_RESET 0x99
#define PSRAM_SET_BURST_LEN 0xC0
#define PSRAM_DEVICE_ID 0x9F
#define PSRAM_FAST_READ_DUMMY 4
#define PSRAM_FAST_READ_QUAD_DUMMY 6
/* ID */
#define PSRAM_ID_KGD_M 0xff
#define PSRAM_ID_KGD_S 8
#define PSRAM_ID_KGD 0x5d
#define PSRAM_ID_EID_M 0xff
#define PSRAM_ID_EID_S 16
/* Use the [7:5](bit7~bit5) of EID to distinguish the psram size:
*
* BIT7 | BIT6 | BIT5 | SIZE(MBIT)
* -------------------------------------
* 0 | 0 | 0 | 16
* 0 | 0 | 1 | 32
* 0 | 1 | 0 | 64
*/
#define PSRAM_EID_SIZE_M 0x07
#define PSRAM_EID_SIZE_S 5
#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M)
#define PSRAM_EID(id) (((id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M)
#define PSRAM_SIZE_ID(id) ((PSRAM_EID(id) >> PSRAM_EID_SIZE_S) & PSRAM_EID_SIZE_M)
#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD)
/* For the old version 32Mbit PSRAM, using the special driver */
#define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20)
#define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID(id) == 0x26)
/* IO-pins for PSRAM.
* WARNING: PSRAM shares all but the CS and CLK pins with the flash, so
* these defines hardcode the flash pins as well, making this code
* incompatible with either a setup that has the flash on non-standard
* pins or ESP32S2s with built-in flash.
*/
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
/* PSRAM clock and cs IO should be configured based on hardware design. */
#define PSRAM_CLK_IO CONFIG_ESP32S2_DEFAULT_PSRAM_CLK_IO /* Default value is 30 */
#define PSRAM_CS_IO CONFIG_ESP32S2_DEFAULT_PSRAM_CS_IO /* Default value is 26 */
#define PSRAM_SPIQ_SD0_IO SPI_Q_GPIO_NUM
#define PSRAM_SPID_SD1_IO SPI_D_GPIO_NUM
#define PSRAM_SPIWP_SD3_IO SPI_WP_GPIO_NUM
#define PSRAM_SPIHD_SD2_IO SPI_HD_GPIO_NUM
#define CS_PSRAM_SEL SPI_MEM_CS1_DIS_M
#define CS_FLASH_SEL SPI_MEM_CS0_DIS_M
#define PSRAM_IO_MATRIX_DUMMY_20M 0
#define PSRAM_IO_MATRIX_DUMMY_40M 0
#define PSRAM_IO_MATRIX_DUMMY_80M 0
#define _SPI_CACHE_PORT 0
#define _SPI_FLASH_PORT 1
#define _SPI_80M_CLK_DIV 1
#define _SPI_40M_CLK_DIV 2
#define _SPI_20M_CLK_DIV 4
/****************************************************************************
* Private Types
****************************************************************************/
typedef enum
{
PSRAM_CLK_MODE_NORM = 0, /* Normal SPI mode */
PSRAM_CLK_MODE_A1C, /* ONE extra clock cycles after CS is set high level */
PSRAM_CLK_MODE_A2C, /* Two extra clock cycles after CS is set high level */
PSRAM_CLK_MODE_ALON, /* clock always on */
PSRAM_CLK_MODE_MAX,
} psram_clk_mode_t;
typedef enum
{
PSRAM_EID_SIZE_16MBITS = 0,
PSRAM_EID_SIZE_32MBITS = 1,
PSRAM_EID_SIZE_64MBITS = 2,
} psram_eid_size_t;
typedef struct
{
uint8_t flash_clk_io;
uint8_t flash_cs_io;
uint8_t psram_clk_io;
uint8_t psram_cs_io;
uint8_t psram_spiq_sd0_io;
uint8_t psram_spid_sd1_io;
uint8_t psram_spiwp_sd3_io;
uint8_t psram_spihd_sd2_io;
} psram_io_t;
#define PSRAM_IO_CONF_DEFAULT() { \
.flash_clk_io = FLASH_CLK_IO, \
.flash_cs_io = FLASH_CS_IO, \
.psram_clk_io = PSRAM_CLK_IO, \
.psram_cs_io = PSRAM_CS_IO, \
.psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO, \
.psram_spid_sd1_io = PSRAM_SPID_SD1_IO, \
.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO, \
.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO, \
}
typedef enum
{
PSRAM_SPI_1 = 0x1,
PSRAM_SPI_MAX ,
} psram_spi_num_t;
typedef enum
{
PSRAM_CMD_QPI,
PSRAM_CMD_SPI,
} psram_cmd_mode_t;
static uint32_t g_psram_id;
static uint8_t g_psram_cs_io = UINT8_MAX;
extern uint32_t esp_rom_efuse_get_flash_gpio_info(void);
extern uint32_t esp_rom_efuse_get_flash_wp_gpio(void);
/****************************************************************************
* Private Functions
****************************************************************************/
static void IRAM_ATTR psram_cache_init(int psram_cache_mode, int vaddrmode);
uint8_t psram_get_cs_io(void)
{
return g_psram_cs_io;
}
static void psram_set_op_mode(int spi_num, int mode)
{
if (mode == PSRAM_CMD_QPI)
{
esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_QIO_MODE);
SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M);
}
else if (mode == PSRAM_CMD_SPI)
{
esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_SLOWRD_MODE);
}
}
static void _psram_exec_cmd(int spi_num,
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits, uint8_t *mosi_data,
int mosi_bit_len, uint8_t *miso_data,
int miso_bit_len)
{
esp_rom_spi_cmd_t conf;
uint32_t _addr = addr;
conf.addr = &_addr;
conf.addr_bit_len = addr_bit_len;
conf.cmd = cmd;
conf.cmd_bit_len = cmd_bit_len;
conf.dummy_bit_len = dummy_bits; /* There is a hw approach on chip723 */
conf.tx_data = (uint32_t *)mosi_data;
conf.tx_data_bit_len = mosi_bit_len;
conf.rx_data = (uint32_t *)miso_data;
conf.rx_data_bit_len = miso_bit_len;
esp_rom_spi_cmd_config(spi_num, &conf);
}
void psram_exec_cmd(int spi_num, int mode,
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits, uint8_t *mosi_data,
int mosi_bit_len, uint8_t *miso_data,
int miso_bit_len, uint32_t cs_mask,
bool is_write_erase_operation)
{
uint32_t backup_usr = READ_PERI_REG(SPI_MEM_USER_REG(spi_num));
uint32_t backup_usr1 = READ_PERI_REG(SPI_MEM_USER1_REG(spi_num));
uint32_t backup_usr2 = READ_PERI_REG(SPI_MEM_USER2_REG(spi_num));
uint32_t backup_ctrl = READ_PERI_REG(SPI_MEM_CTRL_REG(spi_num));
psram_set_op_mode(spi_num, mode);
_psram_exec_cmd(spi_num, cmd, cmd_bit_len, addr,
addr_bit_len, dummy_bits, mosi_data,
mosi_bit_len, miso_data, miso_bit_len);
esp_rom_spi_cmd_start(spi_num, miso_data, miso_bit_len / 8,
cs_mask, is_write_erase_operation);
WRITE_PERI_REG(SPI_MEM_USER_REG(spi_num), backup_usr);
WRITE_PERI_REG(SPI_MEM_USER1_REG(spi_num), backup_usr1);
WRITE_PERI_REG(SPI_MEM_USER2_REG(spi_num), backup_usr2);
WRITE_PERI_REG(SPI_MEM_CTRL_REG(spi_num), backup_ctrl);
}
/* exit QPI mode(set back to SPI mode) */
static void psram_disable_qio_mode(int spi_num)
{
psram_exec_cmd(spi_num, PSRAM_CMD_QPI,
PSRAM_EXIT_QMODE, 8, /* command and command bit len */
0, 0, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
NULL, 0, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* if is program/erase operation */
}
/* switch psram burst length(32 bytes or 1024 bytes)
* datasheet says it should be 1024 bytes by default
*/
static void psram_set_wrap_burst_length(int spi_num, psram_cmd_mode_t mode)
{
psram_exec_cmd(spi_num, mode,
PSRAM_SET_BURST_LEN, 8, /* command and command bit len */
0, 0, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
NULL, 0, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* if is program/erase operation */
}
/* send reset command to psram, in spi mode */
static void psram_reset_mode(int spi_num)
{
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
PSRAM_RESET_EN, 8, /* command and command bit len */
0, 0, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
NULL, 0, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* whether is program/erase operation */
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
PSRAM_RESET, 8, /* command and command bit len */
0, 0, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
NULL, 0, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* whether is program/erase operation */
}
/****************************************************************************
* Public Functions
****************************************************************************/
int psram_enable_wrap(uint32_t wrap_size)
{
static uint32_t current_wrap_size;
if (current_wrap_size == wrap_size)
{
return OK;
}
switch (wrap_size)
{
case 0:
case 32:
psram_set_wrap_burst_length(PSRAM_SPI_1, PSRAM_CMD_QPI);
current_wrap_size = wrap_size;
return OK;
case 16:
case 64:
default:
return -EFAULT;
}
}
bool psram_support_wrap_size(uint32_t wrap_size)
{
switch (wrap_size)
{
case 0:
case 32:
return true;
case 16:
case 64:
default:
return false;
}
}
/* Read ID operation only supports SPI CMD and mode, should issue
* `psram_disable_qio_mode` before calling this
*/
static void psram_read_id(int spi_num, uint32_t *dev_id)
{
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
PSRAM_DEVICE_ID, 8, /* command and command bit len */
0, 24, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
(uint8_t *) dev_id, 24, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* whether is program/erase operation */
}
/* enter QPI mode */
static void IRAM_ATTR psram_enable_qio_mode(int spi_num)
{
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
PSRAM_ENTER_QMODE, 8, /* command and command bit len */
0, 0, /* address and address bit len */
0, /* dummy bit len */
NULL, 0, /* tx data and tx bit len */
NULL, 0, /* rx data and rx bit len */
CS_PSRAM_SEL, /* cs bit mask */
false); /* whether is program/erase operation */
}
static void psram_set_spi1_cmd_cs_timing(psram_clk_mode_t clk_mode)
{
if (clk_mode == PSRAM_CLK_MODE_NORM)
{
/* SPI1 Flash Operation port */
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT),
SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT),
SPI_MEM_CS_SETUP_TIME_V, 0,
SPI_MEM_CS_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT),
SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
}
else
{
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT),
SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
}
}
static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode)
{
if (clk_mode == PSRAM_CLK_MODE_NORM)
{
/* SPI0 SRAM Cache port */
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT),
SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 1,
SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT),
SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0,
SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT),
SPI_MEM_SPI_SMEM_CS_HOLD_M |
SPI_MEM_SPI_SMEM_CS_SETUP_M);
/* SPI0 Flash Cache port */
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT),
SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT),
SPI_MEM_CS_SETUP_TIME_V, 0,
SPI_MEM_CS_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT),
SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
}
else
{
CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT),
SPI_CS_HOLD_M | SPI_CS_SETUP_M);
}
}
/* psram gpio init, different working frequency we have different
* solutions
*/
static void IRAM_ATTR psram_gpio_config(void)
{
psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT();
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI)
{
/* FLASH pins(except wp / hd) are all configured via IO_MUX in rom. */
}
else
{
/* FLASH pins are all configured via GPIO matrix in ROM. */
psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig);
psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig);
psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig);
psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig);
psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig);
psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio();
}
esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig);
g_psram_cs_io = psram_io.psram_cs_io;
}
int psram_get_size(void)
{
int psram_size = PSRAM_SIZE_ID(g_psram_id);
if (PSRAM_IS_64MBIT_TRIAL(g_psram_id))
{
return PSRAM_SIZE_8MB;
}
switch (psram_size)
{
case PSRAM_EID_SIZE_64MBITS:
return PSRAM_SIZE_8MB;
case PSRAM_EID_SIZE_32MBITS:
return PSRAM_SIZE_4MB;
case PSRAM_EID_SIZE_16MBITS:
return PSRAM_SIZE_2MB;
default:
return PSRAM_SIZE_16MB;
}
}
/* used in UT only */
bool psram_is_32mbit_ver0(void)
{
return PSRAM_IS_32MBIT_VER0(g_psram_id);
}
static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode)
{
if (spi_num == _SPI_CACHE_PORT)
{
REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, clk_mode);
}
else
if (spi_num == _SPI_FLASH_PORT)
{
REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, 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.
*/
int IRAM_ATTR psram_enable(int mode, int vaddrmode)
{
int spi_num = PSRAM_SPI_1;
psram_clk_mode_t clk_mode = PSRAM_CLK_MODE_MAX;
DEBUGASSERT(mode < PSRAM_CACHE_MAX);
/* GPIO related settings */
psram_gpio_config();
/* SPI1: set spi1 clk mode, in order to send commands on SPI1 */
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_A1C);
/* SPI1: set cs timing(hold time) in order to send commands on SPI1 */
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_A1C);
psram_disable_qio_mode(spi_num);
psram_read_id(spi_num, &g_psram_id);
if (!PSRAM_IS_VALID(g_psram_id))
{
/* 16Mbit psram ID read error workaround:
* treat the first read id as a dummy one as the pre-condition,
* Send Read ID command again
*/
psram_read_id(spi_num, &g_psram_id);
if (!PSRAM_IS_VALID(g_psram_id))
{
merr("PSRAM ID read error: 0x%08x", g_psram_id);
return -ENODEV;
}
}
if (psram_is_32mbit_ver0())
{
/* SPI1: keep clock mode and cs timing for spi1 */
clk_mode = PSRAM_CLK_MODE_A1C;
}
else
{
/* For other psram, we don't need any extra clock cycles after
* cs get back to high level
*/
clk_mode = PSRAM_CLK_MODE_NORM;
/* SPI1: set clock mode and cs timing to normal mode */
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM);
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM);
}
/* SPI1: send psram reset command */
psram_reset_mode(PSRAM_SPI_1);
/* SPI1: send QPI enable command */
psram_enable_qio_mode(PSRAM_SPI_1);
/* after sending commands, set spi1 clock mode and cs timing to
* normal mode. Since all the operations are sent via SPI0 Cache
*/
/* SPI1: set clock mode to normal mode. */
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM);
/* SPI1: set cs timing to normal */
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM);
/* SPI0: set spi0 clock mode */
psram_set_clk_mode(_SPI_CACHE_PORT, clk_mode);
/* SPI0: set spi0 flash/cache cs timing */
psram_set_spi0_cache_cs_timing(clk_mode);
/* SPI0: init SPI commands for Cache */
psram_cache_init(mode, vaddrmode);
return OK;
}
static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv)
{
uint32_t freqbits;
if (1 >= freqdiv)
{
WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK);
}
else
{
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);
}
}
/* register initialization for sram cache params and r/w commands */
static void IRAM_ATTR psram_cache_init(int psram_cache_mode,
int vaddrmode)
{
int extra_dummy = 0;
switch (psram_cache_mode)
{
case PSRAM_CACHE_S80M:
psram_clock_set(0, 1);
extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
break;
case PSRAM_CACHE_S40M:
psram_clock_set(0, 2);
extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
break;
case PSRAM_CACHE_S26M:
psram_clock_set(0, 3);
extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M;
break;
case PSRAM_CACHE_S20M:
psram_clock_set(0, 4);
extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M;
break;
default:
psram_clock_set(0, 2);
break;
}
/* disable dio mode for cache command */
CLEAR_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0),
SPI_MEM_USR_SRAM_DIO_M);
/* enable qio mode for cache command */
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_QIO_M);
/* enable cache read command */
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0),
SPI_MEM_CACHE_SRAM_USR_RCMD_M);
/* enable cache write command */
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0),
SPI_MEM_CACHE_SRAM_USR_WCMD_M);
/* write address for cache command */
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0),
SPI_MEM_SRAM_ADDR_BITLEN_V, 23,
SPI_MEM_SRAM_ADDR_BITLEN_S);
/* enable cache read dummy */
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M);
/* config sram cache r/w command */
SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0),
SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
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, PSRAM_QUAD_WRITE,
SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE_S); /* 0x38 */
SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0),
SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
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,
PSRAM_FAST_READ_QUAD,
SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_S); /* 0x0b */
/* dummy, psram cache : 40m--+1dummy,80m--+2dummy */
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0),
SPI_MEM_SRAM_RDUMMY_CYCLELEN_V,
PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
SPI_MEM_SRAM_RDUMMY_CYCLELEN_S);
/* ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM) */
CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(0), SPI_MEM_CS1_DIS_M);
}

View File

@ -0,0 +1,139 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_psram.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_PSRAM_H
#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_PSRAM_H
#define PSRAM_SIZE_2MB (2 * 1024 * 1024)
#define PSRAM_SIZE_4MB (4 * 1024 * 1024)
#define PSRAM_SIZE_8MB (8 * 1024 * 1024)
#define PSRAM_SIZE_16MB (16 * 1024 * 1024)
#define PSRAM_SIZE_32MB (32 * 1024 * 1024)
#define PSRAM_SIZE_16MBITS 0
#define PSRAM_SIZE_32MBITS 1
#define PSRAM_SIZE_64MBITS 2
#define PSRAM_SIZE_MAX 3
#define PSRAM_CACHE_S80M 1
#define PSRAM_CACHE_S40M 2
#define PSRAM_CACHE_S26M 3
#define PSRAM_CACHE_S20M 4
#define PSRAM_CACHE_MAX 5
#define SPIRAM_WRAP_MODE_16B 0
#define SPIRAM_WRAP_MODE_32B 1
#define SPIRAM_WRAP_MODE_64B 2
#define SPIRAM_WRAP_MODE_DISABLE 3
/* See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the
* definitions of these modes. Important is that NORMAL works with the
* cache disabled.
*/
#define PSRAM_VADDR_MODE_NORMAL 0 /* CPU use their own flash
* cache for external RAM access
*/
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/****************************************************************************
* Name: psram_get_physical_size
*
* Description:
* Get the physical psram size in bytes.
*
****************************************************************************/
int psram_get_physical_size(uint32_t *out_size_bytes);
/****************************************************************************
* Name: psram_get_available_size
*
* Description:
* Get the available physical psram size in bytes.
*
* If ECC is enabled, available PSRAM size will be 15/16 times its
* physical size. If not, it equals to the physical psram size.
* Note: For now ECC is only enabled on ESP32S2 Octal PSRAM
*
* Input Parameters:
* out_size_bytes - availabe physical psram size in bytes.
*
* Returned Value:
* 0 if success or a negative value if fail.
*
****************************************************************************/
int psram_get_available_size(uint32_t *out_size_bytes);
/****************************************************************************
* Name: psram_get_available_size
*
* Description:
* Enable psram cache
*
* Esp-idf uses this to initialize cache for psram, mapping it into the
* main memory address space.
*
* Input Parameters:
* mode - SPI mode to access psram in.
* vaddrmode - Mode the psram cache works in.
*
* Returned Value:
* 0 if success or a negative value if fail.
*
****************************************************************************/
int psram_enable(int mode, int vaddrmode);
/****************************************************************************
* Name: psram_get_cs_io
*
* Description:
* Get the psram CS IO
*
* Returned Value:
* The psram CS IO pin.
*
****************************************************************************/
uint8_t psram_get_cs_io(void);
/****************************************************************************
* Name: psram_get_size
*
* Description:
* Return size of PSRAM in bytes
*
* Returned Value:
* PSRAM size in bytes
*
****************************************************************************/
int psram_get_size(void);
#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_PSRAM_H */

View File

@ -0,0 +1,380 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_spiram.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <string.h>
#include <sys/param.h>
#include <nuttx/config.h>
#include <nuttx/spinlock.h>
#include "xtensa.h"
#include "xtensa_attr.h"
#include "esp32s2_psram.h"
#include "esp32s2_spiram.h"
#include "hardware/esp32s2_soc.h"
#include "hardware/esp32s2_cache_memory.h"
#include "hardware/esp32s2_extmem.h"
#include "hardware/esp32s2_iomux.h"
/****************************************************************************
* Pre-processor Prototypes
****************************************************************************/
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
#if defined(CONFIG_ESP32S2_SPIRAM)
#define MMU_PAGE_TO_BYTES(page_id) ((page_id) << 16)
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
#if defined(CONFIG_ESP32S2_SPIRAM_SPEED_40M)
# define PSRAM_SPEED PSRAM_CACHE_S40M
#else /* #if CONFIG_ESP32S2_SPIRAM_SPEED_80M */
# define PSRAM_SPEED PSRAM_CACHE_S80M
#endif
/****************************************************************************
* Private Types
****************************************************************************/
static bool g_spiram_inited;
/* These variables are in bytes */
static uint32_t g_allocable_vaddr_start;
static uint32_t g_allocable_vaddr_end;
static DRAM_ATTR uint32_t g_mapped_vaddr_start;
#if defined(CONFIG_ESP32S2_SPIRAM_FETCH_INSTRUCTIONS)
static int g_instr_flash2spiram_offs;
static uint32_t g_instr_start_page;
static uint32_t g_instr_end_page;
#endif
#if defined(CONFIG_ESP32S2_SPIRAM_RODATA)
static int g_rodata_flash2spiram_offs;
static uint32_t g_rodata_start_page;
static uint32_t g_rodata_end_page;
#endif
#if defined(CONFIG_ESP32S2_SPIRAM_FETCH_INSTRUCTIONS) || \
defined(CONFIG_ESP32S2_SPIRAM_RODATA)
static uint32_t page0_mapped;
static uint32_t page0_page = INVALID_PHY_PAGE;
#endif
/* Let's export g_mapped_size to export heap */
DRAM_ATTR uint32_t g_mapped_size;
/****************************************************************************
* ROM Function Prototypes
****************************************************************************/
extern void cache_writeback_all(void);
extern uint32_t cache_suspend_dcache(void);
extern void cache_resume_dcache(uint32_t val);
extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
uint32_t paddr, uint32_t psize,
uint32_t num, uint32_t fixed);
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mmu_map_psram
*
* Description:
* Map the PSRAM to MMU
*
* Input Parameters:
* start_paddr - start of physical PSRAM address
* end_paddr - end of physical PSRAM address
* out_start_vaddr - start of virtual address
*
* Returned Value:
* Zero value (OK) on success or a negative error.
*
****************************************************************************/
int mmu_map_psram(uint32_t start_paddr, uint32_t end_paddr,
uint32_t *out_start_vaddr)
{
/* For now, this function should only run when virtual address is enough
* Decide these logics when there's a real PSRAM with larger size
*/
uint32_t map_length = end_paddr - start_paddr;
if (map_length > SOC_EXTRAM_DATA_SIZE)
{
/* Decide these logics when there's a real PSRAM with larger size */
merr("PSRAM physical size is too large, not support mapping it yet!");
return -ENOMEM;
}
/* should be MMU page aligned */
assert((start_paddr % MMU_PAGE_SIZE) == 0);
uint32_t start_vaddr = DPORT_CACHE_ADDRESS_LOW;
uint32_t end_vaddr = start_vaddr + map_length;
uint32_t cache_bus_mask = 0;
cache_bus_mask |= (end_vaddr > 0) ? EXTMEM_PRO_DCACHE_MASK_DPORT : 0;
cache_bus_mask |= (end_vaddr >= DPORT_ADDRESS_HIGH) ?
EXTMEM_PRO_DCACHE_MASK_DRAM1 : 0;
cache_bus_mask |= (end_vaddr >= DRAM1_ADDRESS_HIGH) ?
EXTMEM_PRO_DCACHE_MASK_DRAM0 : 0;
assert(end_vaddr <= DRAM0_CACHE_ADDRESS_HIGH);
minfo("start_paddr is %x, map_length is %xB, %d pages",
start_paddr, map_length, BYTES_TO_MMU_PAGE(map_length));
/* No need to disable cache, this file is put in Internal RAM */
cache_dbus_mmu_set(MMU_ACCESS_SPIRAM, start_vaddr, start_paddr, 64,
BYTES_TO_MMU_PAGE(map_length), 0);
REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, cache_bus_mask);
*out_start_vaddr = start_vaddr;
return OK;
}
/****************************************************************************
* Name: mmu_map_psram
*
* Description:
* Initialize the CACHE to use with PSRAM
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void IRAM_ATTR esp_spiram_init_cache(void)
{
int ret;
uint32_t start_page = 0;
g_mapped_size = esp_spiram_get_size();
/* Map the PSRAM physical range to MMU */
ret = mmu_map_psram(MMU_PAGE_TO_BYTES(start_page),
MMU_PAGE_TO_BYTES(start_page) +
g_mapped_size, &g_mapped_vaddr_start);
if (ret < 0)
{
merr("MMU PSRAM mapping wrong!");
abort();
}
/* After mapping, we DON'T care about the PSRAM PHYSICAL
* ADDRESSS ANYMORE!
*/
g_allocable_vaddr_start = g_mapped_vaddr_start;
g_allocable_vaddr_end = g_mapped_vaddr_start + g_mapped_size;
}
/****************************************************************************
* Name: esp_spiram_test
*
* Description:
* Simple RAM test. Writes a word every 32 bytes. Takes about a second
* to complete for 4MiB. Returns true when RAM seems OK, false when test
* fails. WARNING: Do not run this before the 2nd cpu has been initialized
* (in a two-core system) or after the heap allocator has taken ownership
* of the memory.
*
* Input Parameters:
* None
*
* Returned Value:
* True on success or False on failure
*
****************************************************************************/
bool esp_spiram_test(void)
{
volatile int *spiram = (volatile int *)g_mapped_vaddr_start;
size_t s = g_mapped_size;
size_t p;
int errct = 0;
int initial_err = -1;
for (p = 0; p < (s / sizeof(int)); p += 8)
{
spiram[p] = p ^ 0xaaaaaaaa;
}
for (p = 0; p < (s / sizeof(int)); p += 8)
{
if (spiram[p] != (p ^ 0xaaaaaaaa))
{
errct++;
if (errct == 1)
{
initial_err = p * sizeof(int);
}
if (errct < 4)
{
merr("SPI SRAM error @ %08x:%08x/%08x \n", &spiram[p],
spiram[p], p ^ 0xaaaaaaaa);
}
}
}
if (errct != 0)
{
merr("SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n",
errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
return false;
}
else
{
minfo("SPI SRAM memory test OK!");
return true;
}
}
#if defined(CONFIG_ESP32S2_SPIRAM_RODATA)
void rodata_flash_page_info_init(void)
{
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end -
((uint32_t)&_rodata_reserved_start &
~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) /
MMU_PAGE_SIZE;
g_rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE +
CACHE_DROM_MMU_START);
g_rodata_start_page &= MMU_ADDRESS_MASK;
g_rodata_end_page = g_rodata_start_page + rodata_page_cnt - 1;
}
uint32_t IRAM_ATTR rodata_flash_start_page_get(void)
{
return g_rodata_start_page;
}
uint32_t IRAM_ATTR rodata_flash_end_page_get(void)
{
return g_rodata_end_page;
}
int IRAM_ATTR g_rodata_flash2spiram_offset(void)
{
return g_rodata_flash2spiram_offs;
}
#endif
int esp_spiram_init(void)
{
int r;
size_t spiram_size;
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
if (r != OK)
{
merr("SPI RAM enabled but initialization failed. Bailing out.\n");
return r;
}
g_spiram_inited = true;
spiram_size = esp_spiram_get_size();
#if defined(CONFIG_ESP32S2_SPIRAM_SIZE) && (CONFIG_ESP32S2_SPIRAM_SIZE != -1)
if (spiram_size != CONFIG_ESP32S2_SPIRAM_SIZE)
{
merr("Expected %dMB chip but found %dMB chip. Bailing out..",
(CONFIG_ESP32S2_SPIRAM_SIZE / 1024 / 1024),
(spiram_size / 1024 / 1024));
return;
}
#endif
minfo("Found %dMB SPI RAM device\n", spiram_size / (1024 * 1024));
minfo("Speed: %dMHz\n", CONFIG_ESP32S2_SPIRAM_SPEED);
minfo("Initialized, cache is in normal (1-core) mode.\n");
return OK;
}
size_t esp_spiram_get_size(void)
{
if (!g_spiram_inited)
{
merr("SPI RAM not initialized");
abort();
}
return psram_get_size();
}
/* Before flushing the cache, if psram is enabled as a memory-mapped thing,
* we need to write back the data in the cache to the psram first, otherwise
* it will get lost. For now, we just read 64/128K of random PSRAM memory to
* do this.
*/
void IRAM_ATTR esp_spiram_writeback_cache(void)
{
cache_writeback_all();
}
/**
* @brief If SPI RAM(PSRAM) has been initialized
*
* @return true SPI RAM has been initialized successfully
* @return false SPI RAM hasn't been initialized or initialized failed
*/
bool esp_spiram_is_initialized(void)
{
return g_spiram_inited;
}
uint8_t esp_spiram_get_cs_io(void)
{
return psram_get_cs_io();
}
#endif

View File

@ -0,0 +1,206 @@
/****************************************************************************
* arch/xtensa/src/esp32s2/esp32s2_spiram.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIRAM_H
#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPIRAM_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* @brief Initialize spiram interface/hardware. Normally called from
* cpu_start.c.
*
* @return ESP_OK on success
*/
int esp_spiram_init(void);
/**
* @brief Configure Cache/MMU for access to external SPI RAM.
*
* Normally this function is called from cpu_start, if
* CONFIG_SPIRAM_BOOT_INIT option is enabled. Applications which need to
* enable SPI RAM at run time can disable CONFIG_SPIRAM_BOOT_INIT, and
* call this function later.
*
* @attention this function must be called with flash cache disabled.
*/
void esp_spiram_init_cache(void);
/**
* @brief Memory test for SPI RAM. Should be called after SPI RAM is
* initialized and (in case of a dual-core system) the app CPU is online.
* This test overwrites the memory with crap, so do not call after e.g. the
* heap allocator has stored important stuff in SPI RAM.
*
* @return true on success, false on failed memory test
*/
bool esp_spiram_test(void);
/**
* @brief Add the initialized SPI RAM to the heap allocator.
*/
int esp_spiram_add_to_heapalloc(void);
/**
* @brief Get the available physical size of the attached SPI RAM chip
*
* @note If ECC is enabled, the available physical size would be smaller
* than the physical size. See `CONFIG_SPIRAM_ECC_ENABLE`
*
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
*/
size_t esp_spiram_get_size(void);
/**
* @brief Force a writeback of the data in the SPI RAM cache. This is to be
* called whenever cache is disabled, because disabling cache on the ESP32
* discards the data in the SPI RAM cache.
*
* This is meant for use from within the SPI flash code.
*/
void esp_spiram_writeback_cache(void);
/**
* @brief If SPI RAM(PSRAM) has been initialized
*
* @return
* - true SPI RAM has been initialized successfully
* - false SPI RAM hasn't been initialized or initialized failed
*/
bool esp_spiram_is_initialized(void);
/**
* @brief get psram CS IO
*
* This interface should be called after PSRAM is enabled, otherwise it will
* return an invalid value -1/0xff.
*
* @return psram CS IO or -1/0xff if psram not enabled
*/
uint8_t esp_spiram_get_cs_io(void);
/**
* @brief Reserve a pool of internal memory for specific DMA/internal
* allocations
*
* @param size Size of reserved pool in bytes
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM when no memory available for pool
*/
int esp_spiram_reserve_dma_pool(size_t size);
/**
* @brief If SPI RAM(PSRAM) has been initialized
*
* @return
* - true SPI RAM has been initialized successfully
* - false SPI RAM hasn't been initialized or initialized failed
*/
bool esp_spiram_is_initialized(void);
#if defined(CONFIG_ESP32S2_SPIRAM_FETCH_INSTRUCTIONS)
extern int _instruction_reserved_start;
extern int _instruction_reserved_end;
/**
* @brief Get the start page number of the instruction in SPI flash
*
* @return start page number
*/
uint32_t instruction_flash_start_page_get(void);
/**
* @brief Get the end page number of the instruction in SPI flash
*
* @return end page number
*/
uint32_t instruction_flash_end_page_get(void);
/**
* @brief Get the offset of instruction from SPI flash to SPI RAM
*
* @return instruction offset
*/
int instruction_flash2spiram_offset(void);
#endif
#if defined(CONFIG_SPIRAM_RODATA)
extern int _rodata_reserved_start;
extern int _rodata_reserved_end;
/**
* @brief Get the start page number of the rodata in SPI flash
*
* @return start page number
*/
uint32_t rodata_flash_start_page_get(void);
/**
* @brief Get the end page number of the rodata in SPI flash
*
* @return end page number
*/
uint32_t rodata_flash_end_page_get(void);
/**
* @brief Get the offset number of rodata from SPI flash to SPI RAM
*
* @return rodata offset
*/
int rodata_flash2spiram_offset(void);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -37,6 +37,7 @@
#include "hardware/esp32s2_extmem.h"
#include "esp32s2_clockconfig.h"
#include "esp32s2_region.h"
#include "esp32s2_spiram.h"
#include "esp32s2_start.h"
#include "esp32s2_lowputc.h"
#include "esp32s2_wdt.h"
@ -110,6 +111,9 @@ typedef enum
CACHE_LINE_SIZE_64B = 2, /* 64 Byte cache line size */
} cache_line_size_t;
#define CACHE_SIZE_8KB CACHE_SIZE_HALF
#define CACHE_SIZE_16KB CACHE_SIZE_FULL
/****************************************************************************
* ROM Function Prototypes
****************************************************************************/
@ -123,13 +127,18 @@ extern int cache_ibus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
extern uint32_t cache_suspend_icache(void);
extern void cache_resume_icache(uint32_t val);
extern void cache_invalidate_dcache_all(void);
extern void cache_invalidate_icache_all(void);
extern void cache_set_dcache_mode(cache_size_t cache_size, cache_ways_t ways,
cache_line_size_t cache_line_size);
extern void cache_set_icache_mode(cache_size_t cache_size, cache_ways_t ways,
cache_line_size_t cache_line_size);
extern void cache_allocate_sram(cache_layout_t sram0_layout,
cache_layout_t sram1_layout,
cache_layout_t sram2_layout,
cache_layout_t sram3_layout);
extern void esp_config_data_cache_mode(void);
extern void cache_enable_dcache(uint32_t autoload);
/****************************************************************************
* Private Function Prototypes
@ -160,6 +169,62 @@ uint32_t g_idlestack[IDLETHREAD_STACKWORDS]
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp_config_data_cache_mode
*
* Description:
* Configure the data cache mode to use with PSRAM.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
IRAM_ATTR void esp_config_data_cache_mode(void)
{
cache_size_t cache_size;
cache_ways_t cache_ways;
cache_line_size_t cache_line_size;
#if defined(CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB)
#if defined(CONFIG_ESP32S2_DATA_CACHE_8KB)
cache_allocate_sram(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW,
CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_8KB;
#else
cache_allocate_sram(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW,
CACHE_MEMORY_DCACHE_HIGH, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_16KB;
#endif
#else
#if defined(CONFIG_ESP32S2_DATA_CACHE_8KB)
cache_allocate_sram(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH,
CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_8KB;
#else
cache_allocate_sram(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH,
CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH);
cache_size = CACHE_SIZE_16KB;
#endif
#endif
cache_ways = CACHE_4WAYS_ASSOC;
#if defined(CONFIG_ESP32S2_DATA_CACHE_LINE_16B)
cache_line_size = CACHE_LINE_SIZE_16B;
#else
cache_line_size = CACHE_LINE_SIZE_32B;
#endif
merr("Data cache \t\t: size %dKB, %dWays, cache line size %dByte",
cache_size == CACHE_SIZE_8KB ? 8 : 16, 4,
cache_line_size == CACHE_LINE_SIZE_16B ? 16 : 32);
cache_set_dcache_mode(cache_size, cache_ways, cache_line_size);
cache_invalidate_dcache_all();
}
/****************************************************************************
* Name: configure_cpu_caches
*
@ -196,7 +261,7 @@ static void IRAM_ATTR configure_cpu_caches(void)
cache_ways = CACHE_4WAYS_ASSOC;
#ifdef CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B
#if defined(CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B)
cache_line_size = CACHE_LINE_SIZE_16B;
#else
cache_line_size = CACHE_LINE_SIZE_32B;
@ -206,6 +271,11 @@ static void IRAM_ATTR configure_cpu_caches(void)
cache_set_icache_mode(cache_size, cache_ways, cache_line_size);
cache_invalidate_icache_all();
cache_resume_icache(0);
#if defined(CONFIG_ESP32S2_SPIRAM_BOOT_INIT)
esp_config_data_cache_mode();
cache_enable_dcache(0);
#endif
}
/****************************************************************************
@ -285,6 +355,22 @@ static void noreturn_function IRAM_ATTR __esp32s2_start(void)
showprogress('A');
#if defined(CONFIG_ESP32S2_SPIRAM_BOOT_INIT)
if (esp_spiram_init() != OK)
{
# if defined(CONFIG_ESP32S2_SPIRAM_IGNORE_NOTFOUND)
mwarn("SPIRAM Initialization failed!\n");
# else
PANIC();
# endif
}
else
{
esp_spiram_init_cache();
esp_spiram_test();
}
#endif
/* Initialize onboard resources */
esp32s2_board_initialize();

View File

@ -3279,4 +3279,27 @@
#define EFUSE_EFUSE_DATE_V 0xFFFFFFFF
#define EFUSE_EFUSE_DATE_S 0
#define EFUSE_SPICONFIG_SPI_DEFAULTS 0
#define EFUSE_SPICONFIG_HSPI_DEFAULTS 1
#define EFUSE_SPICONFIG_RET_SPICLK_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPICLK_SHIFT 0
#define EFUSE_SPICONFIG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICLK_SHIFT) & EFUSE_SPICONFIG_RET_SPICLK_MASK)
#define EFUSE_SPICONFIG_RET_SPIQ_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPIQ_SHIFT 6
#define EFUSE_SPICONFIG_RET_SPIQ(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIQ_SHIFT) & EFUSE_SPICONFIG_RET_SPIQ_MASK)
#define EFUSE_SPICONFIG_RET_SPID_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPID_SHIFT 12
#define EFUSE_SPICONFIG_RET_SPID(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPID_SHIFT) & EFUSE_SPICONFIG_RET_SPID_MASK)
#define EFUSE_SPICONFIG_RET_SPICS0_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPICS0_SHIFT 18
#define EFUSE_SPICONFIG_RET_SPICS0(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICS0_SHIFT) & EFUSE_SPICONFIG_RET_SPICS0_MASK)
#define EFUSE_SPICONFIG_RET_SPIHD_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPIHD_SHIFT 24
#define EFUSE_SPICONFIG_RET_SPIHD(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIHD_SHIFT) & EFUSE_SPICONFIG_RET_SPIHD_MASK)
#endif /* __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_EFUSE_H */

View File

@ -66,4 +66,36 @@
#define EXTMEM_PRO_ICACHE_MASK_IRAM1 EXTMEM_PRO_ICACHE_MASK_BUS1
#define EXTMEM_PRO_ICACHE_MASK_DROM0 EXTMEM_PRO_ICACHE_MASK_BUS2
#define EXTMEM_PRO_DCACHE_CTRL1_REG (DR_REG_EXTMEM_BASE + 0x004)
/* EXTMEM_PRO_DCACHE_MASK_BUS2 : R/W ;bitpos:[2] ;default: 1'b1 ; */
/* Description: The bit is used to disable dbus2 0: enable 1: disable */
#define EXTMEM_PRO_DCACHE_MASK_BUS2 (BIT(2))
#define EXTMEM_PRO_DCACHE_MASK_BUS2_M (BIT(2))
#define EXTMEM_PRO_DCACHE_MASK_BUS2_V 0x1
#define EXTMEM_PRO_DCACHE_MASK_BUS2_S 2
/* EXTMEM_PRO_DCACHE_MASK_BUS1 : R/W ;bitpos:[1] ;default: 1'b1 ; */
/* Description: The bit is used to disable dbus1 0: enable 1: disable */
#define EXTMEM_PRO_DCACHE_MASK_BUS1 (BIT(1))
#define EXTMEM_PRO_DCACHE_MASK_BUS1_M (BIT(1))
#define EXTMEM_PRO_DCACHE_MASK_BUS1_V 0x1
#define EXTMEM_PRO_DCACHE_MASK_BUS1_S 1
/* EXTMEM_PRO_DCACHE_MASK_BUS0 : R/W ;bitpos:[0] ;default: 1'b1 ; */
/* description: The bit is used to disable dbus0 0: enable 1: disable */
#define EXTMEM_PRO_DCACHE_MASK_BUS0 (BIT(0))
#define EXTMEM_PRO_DCACHE_MASK_BUS0_M (BIT(0))
#define EXTMEM_PRO_DCACHE_MASK_BUS0_V 0x1
#define EXTMEM_PRO_DCACHE_MASK_BUS0_S 0
#define EXTMEM_PRO_DCACHE_MASK_DRAM0 EXTMEM_PRO_DCACHE_MASK_BUS0
#define EXTMEM_PRO_DCACHE_MASK_DRAM1 EXTMEM_PRO_DCACHE_MASK_BUS1
#define EXTMEM_PRO_DCACHE_MASK_DPORT EXTMEM_PRO_DCACHE_MASK_BUS2
#endif /* __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_EXTMEM_H */

View File

@ -299,6 +299,8 @@
#define SOC_EXTRAM_DATA_LOW 0x3f500000
#define SOC_EXTRAM_DATA_HIGH 0x3ff80000
#define SOC_EXTRAM_DATA_SIZE (SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW)
/* Virtual address 0 */
#define VADDR0_START_ADDR SOC_DROM_LOW

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/*****************************************************************************
* arch/xtensa/src/esp32s2/rom/esp32s2_opi_flash.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*****************************************************************************/
#ifndef __ARCH_XTENSA_SRC_ESP32S2_ROM_ESP32S2_OPI_FLASH_H
#define __ARCH_XTENSA_SRC_ESP32S2_ROM_ESP32S2_OPI_FLASH_H
/*****************************************************************************
* Included Files
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
uint16_t cmd; /* !< Command value */
uint16_t cmd_bit_len; /* !< Command byte length */
uint32_t *addr; /* !< Point to address value */
uint32_t addr_bit_len; /* !< Address byte length */
uint32_t *tx_data; /* !< Point to send data buffer */
uint32_t tx_data_bit_len; /* !< Send data byte length. */
uint32_t *rx_data; /* !< Point to recevie data buffer */
uint32_t rx_data_bit_len; /* !< Recevie Data byte length. */
uint32_t dummy_bit_len;
} esp_rom_spi_cmd_t;
#define ESP_ROM_OPIFLASH_MUX_TAKE()
#define ESP_ROM_OPIFLASH_MUX_GIVE()
#define ESP_ROM_OPIFLASH_SEL_CS0 (BIT(0))
#define ESP_ROM_OPIFLASH_SEL_CS1 (BIT(1))
/* Definition of MX25UM25645G Octa Flash
* SPI status register
*/
#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0
#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1
#define ESP_ROM_SPIFLASH_BP0 BIT2
#define ESP_ROM_SPIFLASH_BP1 BIT3
#define ESP_ROM_SPIFLASH_BP2 BIT4
#define ESP_ROM_SPIFLASH_QE BIT9
#define FLASH_OP_MODE_RDCMD_DOUT 0x3B
#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000
#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000
#define ESP_ROM_FLASH_PAGE_SIZE 256
/* FLASH commands */
#define ROM_FLASH_CMD_RDID 0x9F
#define ROM_FLASH_CMD_WRSR 0x01
#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define ROM_FLASH_CMD_WREN 0x06
#define ROM_FLASH_CMD_WRDI 0x04
#define ROM_FLASH_CMD_RDSR 0x05
#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define ROM_FLASH_CMD_ERASE_SEC 0x20
#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52
#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8
#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
#define ROM_FLASH_CMD_RSTEN 0x66
#define ROM_FLASH_CMD_RST 0x99
#define ROM_FLASH_CMD_SE4B 0x21
#define ROM_FLASH_CMD_SE4B_OCT 0xDE21
#define ROM_FLASH_CMD_BE4B 0xDC
#define ROM_FLASH_CMD_BE4B_OCT 0x23DC
#define ROM_FLASH_CMD_RSTEN_OCT 0x9966
#define ROM_FLASH_CMD_RST_OCT 0x6699
#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC
#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE
#define ROM_FLASH_CMD_FSTRD4B 0x0C
#define ROM_FLASH_CMD_PP4B 0x12
#define ROM_FLASH_CMD_PP4B_OCT 0xED12
#define ROM_FLASH_CMD_RDID_OCT 0x609F
#define ROM_FLASH_CMD_WREN_OCT 0xF906
#define ROM_FLASH_CMD_RDSR_OCT 0xFA05
#define ROM_FLASH_CMD_RDCR2 0x71
#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71
#define ROM_FLASH_CMD_WRCR2 0x72
#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72
/* Definitions for GigaDevice GD25LX256E Flash */
#define ROM_FLASH_CMD_RDFSR_GD 0x70
#define ROM_FLASH_CMD_RD_GD 0x03
#define ROM_FLASH_CMD_RD4B_GD 0x13
#define ROM_FLASH_CMD_FSTRD_GD 0x0B
#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C
#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B
#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C
#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB
#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC
#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD
#define ROM_FLASH_CMD_PP_GD 0x02
#define ROM_FLASH_CMD_PP4B_GD 0x12
#define ROM_FLASH_CMD_PP_OOUT_GD 0x82
#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84
#define ROM_FLASH_CMD_PP_OIO_GD 0xC2
#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E
#define ROM_FLASH_CMD_SE_GD 0x20
#define ROM_FLASH_CMD_SE4B_GD 0x21
#define ROM_FLASH_CMD_BE32K_GD 0x52
#define ROM_FLASH_CMD_BE32K4B_GD 0x5C
#define ROM_FLASH_CMD_BE64K_GD 0xD8
#define ROM_FLASH_CMD_BE64K4B_GD 0xDC
#define ROM_FLASH_CMD_EN4B_GD 0xB7
#define ROM_FLASH_CMD_DIS4B_GD 0xE9
/* spi user mode command config */
/**
* @brief Config the spi user command
* @param spi_num spi port
* @param pcmd pointer to accept the spi command struct
*/
void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t *pcmd);
/**
* @brief Start a spi user command sequence
* @param spi_num spi port
* @param rx_buf buffer pointer to receive data
* @param rx_len receive data length in byte
* @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1
* @param is_write_erase to indicate whether this is a write or erase
* operation, since the CPU would check permission
*/
void esp_rom_spi_cmd_start(int spi_num, uint8_t *rx_buf, uint16_t rx_len,
uint8_t cs_en_mask, bool is_write_erase);
/**
* @brief Config opi flash pads according to efuse settings.
*/
void esp_rom_opiflash_pin_config(void);
/**
* @brief Set SPI operation mode
* @param spi_num spi port
* @param mode Flash Read Mode
*/
void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
/**
* @brief Set data swap mode in DTR(DDR) mode
* @param spi_num spi port
* @param wr_swap to decide whether to swap fifo data in dtr write operation
* @param rd_swap to decide whether to swap fifo data in dtr read operation
*/
void esp_rom_spi_set_dtr_swap_mode(int spi, bool wr_swap, bool rd_swap);
/**
* @brief to send reset command in spi/opi-str/opi-dtr mode(for MX25UM25645G)
* @param spi_num spi port
*/
void esp_rom_opiflash_mode_reset(int spi_num);
#if 0
/* MX25UM25645G opi flash interface */
/**
* @brief To execute a flash operation command
* @param spi_num spi port
* @param mode Flash Read Mode
* @param cmd data to send in command field
* @param cmd_bit_len bit length of command field
* @param addr data to send in address field
* @param addr_bit_len bit length of address field
* @param dummy_bits bit length of dummy field
* @param mosi_data data buffer to be sent in mosi field
* @param mosi_bit_len bit length of data buffer to be sent in mosi field
* @param miso_data data buffer to accept data in miso field
* @param miso_bit_len bit length of data buffer to accept data in miso field
* @param cs_mark decide which cs pin to use. 0: cs0, 1: cs1
* @param is_write_erase_operation to indicate whether this a write or erase
* flash operation
*/
void esp_rom_opiflash_exec_cmd(int spi_num, esp_rom_spiflash_read_mode_t mode,
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits,
uint8_t *mosi_data, int mosi_bit_len,
uint8_t *miso_data, int miso_bit_len,
uint32_t cs_mask,
bool is_write_erase_operation);
/**
* @brief send reset command to opi flash
* @param spi_num spi port
* @param mode Flash Operation Mode
*/
void esp_rom_opiflash_soft_reset(int spi_num,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to read opi flash ID
* @note command format would be defined in initialization
* @param[out] out_id buffer to accept id
* @return flash operation result
*/
uint32_t esp_rom_opiflash_read_id(int spi_num,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to read opi flash status register(for MX25UM25645G)
* @param spi_num spi port
* @param mode Flash Operation Mode
* @return opi flash status value
*/
uint8_t esp_rom_opiflash_rdsr(int spi_num, esp_rom_spiflash_read_mode_t mode);
/**
* @brief wait opi flash status register to be idle
* @param spi_num spi port
* @param mode Flash Operation Mode
*/
void esp_rom_opiflash_wait_idle(int spi_num,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to read the config register2(for MX25UM25645G)
* @param spi_num spi port
* @param mode Flash Operation Mode
* @param addr the address of configure register
* @return value of config register2
*/
uint8_t esp_rom_opiflash_rdcr2(int spi_num,
esp_rom_spiflash_read_mode_t mode,
uint32_t addr);
/**
* @brief to write the config register2(for MX25UM25645G)
* @param spi_num spi port
* @param mode Flash Operation Mode
* @param addr the address of config register
* @param val the value to write
*/
void esp_rom_opiflash_wrcr2(int spi_num, esp_rom_spiflash_read_mode_t mode,
uint32_t addr, uint8_t val);
/**
* @brief to erase flash sector(for MX25UM25645G)
* @param spi_num spi port
* @param address the sector address to be erased
* @param mode Flash operation mode
* @return flash operation result
*/
esp_rom_spiflash_result_t
esp_rom_opiflash_erase_sector(int spi_num, uint32_t address,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to erase flash block(for MX25UM25645G)
* @param spi_num spi port
* @param address the block address to be erased
* @param mode Flash operation mode
* @return flash operation result
*/
esp_rom_spiflash_result_t
esp_rom_opiflash_erase_block_64k(int spi_num, uint32_t address,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to erase a flash area define by start address and length
* (for MX25UM25645G)
* @param spi_num spi port
* @param start_addr the start address to be erased
* @param area_len the erea length to be erased
* @param mode flash operation mode
* @return flash operation result
*/
esp_rom_spiflash_result_t
esp_rom_opiflash_erase_area(int spi_num, uint32_t start_addr,
uint32_t area_len,
esp_rom_spiflash_read_mode_t mode);
/**
* @brief to read data from opi flash(for MX25UM25645G)
* @param spi_num spi port
* @param mode flash operation mode
* @param flash_addr flash address to read data from
* @param data_addr data buffer to accept the data
* @param len data length to be read
* @return flash operation result
*/
esp_rom_spiflash_result_t
esp_rom_opiflash_read(int spi_num, esp_rom_spiflash_read_mode_t mode,
uint32_t flash_addr, uint8_t *data_addr, int len);
/**
* @brief to write data to opi flash(for MX25UM25645G)
* @param spi_num spi port
* @param mode flash operation mode
* @param flash_addr flash address to write data to
* @param data_addr data buffer to write to flash
* @param len data length to write
* @return flash operation result
*/
esp_rom_spiflash_result_t
esp_rom_opiflash_write(int spi_num, esp_rom_spiflash_read_mode_t mode,
uint32_t flash_addr, uint8_t *data_addr,
uint32_t len);
/**
* @brief to set opi flash operation mode(for MX25UM25645G)
* @param spi_num spi port
* @param cur_mode current operation mode
* @param target the target operation mode to be set
*/
void esp_rom_opiflash_set_mode(int spi_num,
esp_rom_spiflash_read_mode_t cur_mode,
esp_rom_spiflash_read_mode_t target_mode);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ARCH_XTENSA_SRC_ESP32S2_ROM_ESP32S2_OPI_FLASH_H */

File diff suppressed because it is too large Load Diff

View File

@ -52,12 +52,6 @@ ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
ARCHWARNINGSXX = -Wall -Wshadow -Wundef
ARCHPICFLAGS = -fpic
# if SPIRAM/PSRAM is used then we need to include a workaround
ifeq ($(CONFIG_ESP32S2_SPIRAM),y)
ARCHCFLAGS += -mfix-esp32s2-psram-cache-issue
endif
CFLAGS := $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe
CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe

View File

@ -18,7 +18,7 @@ PROVIDE ( Cache_Clean_Items = 0x40018250 );
PROVIDE ( Cache_Config_DCache_Autoload = 0x40018794 );
PROVIDE ( Cache_Config_ICache_Autoload = 0x40018664 );
PROVIDE ( Cache_Count_Flash_Pages = 0x40018f70 );
PROVIDE ( Cache_Dbus_MMU_Set = 0x40018eb0 );
PROVIDE ( cache_dbus_mmu_set = 0x40018eb0 );
PROVIDE ( Cache_DCache_Preload_Done = 0x40018630 );
PROVIDE ( Cache_Disable_DCache = 0x40018c68 );
PROVIDE ( Cache_Disable_DCache_Autoload = 0x4001888c );
@ -26,7 +26,7 @@ PROVIDE ( Cache_Disable_DCache_PreLock = 0x40018a5c );
PROVIDE ( Cache_Disable_ICache = 0x40018c2c );
PROVIDE ( Cache_Disable_ICache_Autoload = 0x4001875c );
PROVIDE ( Cache_Disable_ICache_PreLock = 0x4001892c );
PROVIDE ( Cache_Enable_DCache = 0x40018d58 );
PROVIDE ( cache_enable_dcache = 0x40018d58 );
PROVIDE ( Cache_Enable_DCache_Autoload = 0x40018874 );
PROVIDE ( Cache_Enable_DCache_PreLock = 0x400189f0 );
PROVIDE ( Cache_Enable_Defalut_DCache_Mode = 0x40018170 );
@ -46,7 +46,7 @@ PROVIDE ( Cache_Get_Virtual_Addr = 0x40019210 );
PROVIDE ( cache_ibus_mmu_set = 0x40018df4 );
PROVIDE ( Cache_ICache_Preload_Done = 0x4001859c );
PROVIDE ( cache_invalidate_addr = 0x400182e4 );
PROVIDE ( Cache_Invalidate_DCache_All = 0x4001842c );
PROVIDE ( cache_invalidate_dcache_all = 0x4001842c );
PROVIDE ( Cache_Invalidate_DCache_Items = 0x40018208 );
PROVIDE ( cache_invalidate_icache_all = 0x40018420 );
PROVIDE ( Cache_Invalidate_ICache_Items = 0x400181b8 );
@ -60,7 +60,7 @@ PROVIDE ( Cache_Resume_DCache = 0x40018d3c );
PROVIDE ( Cache_Resume_DCache_Autoload = 0x4001850c );
PROVIDE ( cache_resume_icache = 0x40018cdc );
PROVIDE ( Cache_Resume_ICache_Autoload = 0x400184c4 );
PROVIDE ( Cache_Set_DCache_Mode = 0x40018074 );
PROVIDE ( cache_set_dcache_mode = 0x40018074 );
PROVIDE ( Cache_Set_Default_Mode = 0x4001810c );
PROVIDE ( cache_set_icache_mode = 0x4001803c );
PROVIDE ( Cache_Start_DCache_Preload = 0x400185c4 );
@ -74,8 +74,8 @@ PROVIDE ( Cache_Unlock_Addr = 0x40018b9c );
PROVIDE ( Cache_Unlock_DCache_Items = 0x40018ac8 );
PROVIDE ( Cache_Unlock_ICache_Items = 0x40018998 );
PROVIDE ( Cache_UnMask_Drom0 = 0x40018480 );
PROVIDE ( Cache_WriteBack_Addr = 0x400183c8 );
PROVIDE ( Cache_WriteBack_All = 0x40018444 );
PROVIDE ( cache_writeback_addr = 0x400183c8 );
PROVIDE ( cache_writeback_all = 0x40018444 );
PROVIDE ( Cache_WriteBack_Items = 0x40018298 );
PROVIDE ( cacl_rtc_memory_crc = 0x4000ffa0 );
PROVIDE ( cdc_acm_class_handle_req = 0x40013050 );
@ -211,6 +211,9 @@ PROVIDE ( esp_rom_spi_flash_update_id = 0x40016e44 );
PROVIDE ( esp_rom_spi_reset_rw_mode = 0x40017984 );
PROVIDE ( esp_rom_spi_set_dtr_swap_mode = 0x40017b60 );
PROVIDE ( esp_rom_spi_set_op_mode = 0x400179e8 );
PROVIDE ( esp_rom_efuse_get_flash_gpio_info = ets_efuse_get_spiconfig );
PROVIDE ( esp_rom_efuse_get_flash_wp_gpio = ets_efuse_get_wp_pad );
PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO );
PROVIDE ( _etext = 0x4001bed0 );
PROVIDE ( ets_aes_block = 0x4000d610 );
PROVIDE ( ets_aes_disable = 0x4000d4f8 );