xtensa/esp32s3: Fix some ESP32S3 module reboot and QVL issues

1. Increase the data length in timing tuning.
2. Add MSPI Error-Correcting Code function when accessing SPIRAM.
3. Add delay before timing tuning.
This commit is contained in:
chenwen@espressif.com 2023-10-24 10:31:30 +08:00 committed by Xiang Xiao
parent 8494fd2097
commit 54b71de23a
4 changed files with 123 additions and 4 deletions

View File

@ -861,6 +861,14 @@ config ESP32S3_SPIRAM_SPEED
default 80 if ESP32S3_SPIRAM_SPEED_80M
default 40 if ESP32S3_SPIRAM_SPEED_40M
config ESP32S3_SPIRAM_ECC_ENABLE
bool "Enable SPI RAM ECC"
default n
depends on ESP32S3_SPIRAM_MODE_OCT
---help---
Enable MSPI Error-Correcting Code function when accessing SPIRAM.
If enabled, 1/16 of the SPI RAM total size will be reserved for error-correcting code.
config ESP32S3_SPIRAM_BOOT_INIT
bool "Initialize SPI RAM during startup"
depends on ESP32S3_SPIRAM

View File

@ -37,6 +37,7 @@
#include "hardware/esp32s3_iomux.h"
#include "hardware/esp32s3_gpio.h"
#include "hardware/esp32s3_gpio_sigmap.h"
#include "hardware/esp32s3_syscon.h"
#include "rom/esp32s3_spiflash.h"
#include "rom/esp32s3_opi_flash.h"
@ -56,8 +57,12 @@
#define OCT_PSRAM_CS_SETUP_TIME 3
#define OCT_PSRAM_CS_HOLD_TIME 3
#define OCT_PSRAM_CS_ECC_HOLD_TIME 3
#define OCT_PSRAM_CS_HOLD_DELAY 2
#define OCT_PSRAM_PAGE_SIZE 2
#define OCT_PSRAM_ECC_ENABLE_MASK BIT(8)
/****************************************************************************
* Private Types
****************************************************************************/
@ -151,6 +156,7 @@ struct opi_psram_reg
****************************************************************************/
extern void cache_resume_dcache(uint32_t val);
extern void ets_delay_us(uint32_t us);
/****************************************************************************
* Private Data
@ -218,6 +224,37 @@ static void IRAM_ATTR set_psram_reg(int spi_num,
NULL, 0,
BIT(1),
false);
#if CONFIG_ESP32S3_SPIRAM_ECC_ENABLE
addr = 0x8;
data_bit_len = 8;
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_READ,
cmd_len,
addr,
addr_bit_len,
dummy,
NULL, 0,
&psram_reg.mr8.val,
data_bit_len,
BIT(1),
false);
psram_reg.mr8.bt = in_reg->mr8.bt;
psram_reg.mr8.bl = in_reg->mr8.bl;
esp_rom_opiflash_exec_cmd(spi_num, mode,
OPI_PSRAM_REG_WRITE,
cmd_len,
addr,
addr_bit_len,
0,
&psram_reg.mr8.val,
16,
NULL, 0,
BIT(1),
false);
#endif
}
/****************************************************************************
@ -302,6 +339,47 @@ static void IRAM_ATTR get_psram_reg(int spi_num,
false);
}
/****************************************************************************
* Name: configure_psram_ecc
*
* Description:
* Enable error correcting code feature, Can add an input parameter for
* selecting ECC mode if needed.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
static void IRAM_ATTR configure_psram_ecc(void)
{
#if CONFIG_ESP32S3_SPIRAM_ECC_ENABLE
/* Clear this bit to use ECC 16to17 mode */
CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0),
SPI_MEM_SPI_SMEM_ECC_16TO18_BYTE_EN_M);
SET_PERI_REG_BITS(SYSCON_SPI_MEM_ECC_CTRL_REG,
SYSCON_SRAM_PAGE_SIZE_V,
OCT_PSRAM_PAGE_SIZE,
SYSCON_SRAM_PAGE_SIZE_S);
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0),
SPI_MEM_SPI_SMEM_ECC_SKIP_PAGE_CORNER_M);
/* Enable ECC region 0 (ACE0)
* Default: ACE0 range: 0 ~ 256MB
* Current Octal PSRAM is 8MB, ACE0 is enough
*/
SET_PERI_REG_MASK(SYSCON_SRAM_ACE0_ATTR_REG, OCT_PSRAM_ECC_ENABLE_MASK);
minfo("PSRAM ECC is enabled\n");
#else
CLEAR_PERI_REG_MASK(SYSCON_SRAM_ACE0_ATTR_REG, OCT_PSRAM_ECC_ENABLE_MASK);
#endif
}
/****************************************************************************
* Name: print_psram_reg
*
@ -383,6 +461,12 @@ static void IRAM_ATTR init_cs_timing(void)
SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V,
OCT_PSRAM_CS_SETUP_TIME,
SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S);
#if CONFIG_ESP32S3_SPIRAM_ECC_ENABLE
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0),
SPI_MEM_SPI_SMEM_ECC_CS_HOLD_TIME_V,
OCT_PSRAM_CS_ECC_HOLD_TIME,
SPI_MEM_SPI_SMEM_ECC_CS_HOLD_TIME_S);
#endif
/* CS1 high time */
@ -598,8 +682,10 @@ int IRAM_ATTR psram_enable(int mode, int vaddrmode)
psram_reg.mr0.drive_str = 0;
set_psram_reg(1, &psram_reg);
get_psram_reg(1, &psram_reg);
print_psram_reg(&psram_reg);
/* workaround: some chips are unstable without delay */
ets_delay_us(50000);
g_psram_size = psram_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB :
psram_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :
psram_reg.mr2.density == 0x5 ? PSRAM_SIZE_16MB :
@ -611,6 +697,17 @@ int IRAM_ATTR psram_enable(int mode, int vaddrmode)
esp32s3_spi_timing_set_mspi_psram_tuning();
esp32s3_spi_timing_set_mspi_low_speed(true);
/* Enable ecc after timing tuning */
configure_psram_ecc();
psram_reg.mr8.bl = 3;
psram_reg.mr8.bt = 0;
set_psram_reg(1, &psram_reg);
get_psram_reg(1, &psram_reg);
print_psram_reg(&psram_reg);
/* Back to the high speed mode. Flash/PSRAM clocks are set to the clock
* that user selected. SPI0/1 registers are all set correctly.
*/
@ -634,6 +731,11 @@ int IRAM_ATTR psram_enable(int mode, int vaddrmode)
int psram_get_physical_size(uint32_t *out_size_bytes)
{
if (!out_size_bytes)
{
return -EINVAL;
}
*out_size_bytes = g_psram_size;
return g_psram_size > 0 ? OK : -EINVAL;
}
@ -642,6 +744,15 @@ int psram_get_physical_size(uint32_t *out_size_bytes)
int psram_get_available_size(uint32_t *out_size_bytes)
{
if (!out_size_bytes)
{
return -EINVAL;
}
#if CONFIG_ESP32S3_SPIRAM_ECC_ENABLE
*out_size_bytes = g_psram_size * 15 / 16;
#else
*out_size_bytes = g_psram_size;
#endif
return (g_psram_size ? OK : -EINVAL);
}

View File

@ -171,7 +171,7 @@
#define MSPI_TIMING_FLASH_DTR_MODE CONFIG_ESP32S3_FLASH_SAMPLE_MODE_DTR
#define MSPI_TIMING_FLASH_STR_MODE CONFIG_ESP32S3_FLASH_SAMPLE_MODE_STR
#define MSPI_TIMING_TEST_DATA_LEN 64
#define MSPI_TIMING_TEST_DATA_LEN 1024
#define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0
#define MSPI_TIMING_FLASH_TEST_DATA_ADDR 0
@ -1356,7 +1356,7 @@ static void do_tuning(const uint8_t *reference_data,
*
****************************************************************************/
void esp32s3_spi_timing_set_pin_drive_strength(void)
void IRAM_ATTR esp32s3_spi_timing_set_pin_drive_strength(void)
{
const uint32_t regs[] =
{

View File

@ -76,7 +76,7 @@ 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`
* than the physical size. See `CONFIG_ESP32S3_SPIRAM_ECC_ENABLE`
*
* @return Size in bytes, or 0 if no external RAM chip support compiled in.
*/