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:
parent
8494fd2097
commit
54b71de23a
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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[] =
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user