diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 02053e1af..545b99b4d 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -180,6 +180,9 @@ menu "ESP32-specific" #Note that this is limited to 62 banks, as esp_spiram_writeback_cache needs some kind of mapping of #some banks below that mark to work. We cannot at this moment guarantee this to exist when himem is #enabled. + + If spiram 2T mode is enabled, the size of 64Mbit psram will be changed as 32Mbit, so himem will be + unusable. config SPIRAM_BANKSWITCH_RESERVE int "Amount of 32K pages to reserve for bank switching" depends on SPIRAM_BANKSWITCH_ENABLE @@ -349,6 +352,20 @@ menu "ESP32-specific" For ESP32-PICO chip, the default value of this config should be 7. + config SPIRAM_2T_MODE + bool "Enable SPI PSRAM 2T mode" + depends on SPIRAM_SUPPORT + default "n" + help + Enable this option to fix single bit errors inside 64Mbit PSRAM. + + Some 64Mbit PSRAM chips have a hardware issue in the RAM which causes bit errors at multiple + fixed bit positions. + + Note: If this option is enabled, the 64Mbit PSRAM chip will appear to be 32Mbit in size. + Applications will not be affected unless the use the esp_himem APIs, which are not supported + in 2T mode. + endmenu # "SPI RAM config" config MEMMAP_TRACEMEM diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index c6715ebb9..abeb95a63 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -173,7 +173,8 @@ typedef enum { static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX; static psram_clk_mode_t s_clk_mode = PSRAM_CLK_MODE_DCLK; -static uint32_t s_psram_id = 0; +static uint64_t s_psram_id = 0; +static bool s_2t_mode_enabled = false; /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; @@ -398,11 +399,12 @@ static void psram_disable_qio_mode(psram_spi_num_t spi_num) } //read psram id -static void psram_read_id(uint32_t* dev_id) +static void psram_read_id(uint64_t* dev_id) { psram_spi_num_t spi_num = PSRAM_SPI_1; psram_disable_qio_mode(spi_num); uint32_t dummy_bits = 0 + extra_dummy; + uint32_t psram_id[2] = {0}; psram_cmd_t ps_cmd; uint32_t addr = 0; @@ -426,14 +428,15 @@ static void psram_read_id(uint32_t* dev_id) ps_cmd.addr = &addr; ps_cmd.txDataBitLen = 0; ps_cmd.txData = NULL; - ps_cmd.rxDataBitLen = 4 * 8; - ps_cmd.rxData = dev_id; + ps_cmd.rxDataBitLen = 8 * 8; + ps_cmd.rxData = psram_id; ps_cmd.dummyBitLen = dummy_bits; psram_cmd_config(spi_num, &ps_cmd); psram_clear_spi_fifo(spi_num); psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI); psram_cmd_end(spi_num); + *dev_id = (uint64_t)(((uint64_t)psram_id[1] << 32) | psram_id[0]); } //enter QPI mode @@ -468,6 +471,182 @@ static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num) return ESP_OK; } +#if CONFIG_SPIRAM_2T_MODE +// use SPI user mode to write psram +static void spi_user_psram_write(psram_spi_num_t spi_num, uint32_t address, uint32_t *data_buffer, uint32_t data_len) +{ + uint32_t addr = (PSRAM_QUAD_WRITE << 24) | (address & 0x7fffff); + psram_cmd_t ps_cmd; + ps_cmd.cmdBitLen = 0; + ps_cmd.cmd = 0; + ps_cmd.addr = &addr; + ps_cmd.addrBitLen = 4 * 8; + ps_cmd.txDataBitLen = 32 * 8; + ps_cmd.txData = NULL; + ps_cmd.rxDataBitLen = 0; + ps_cmd.rxData = NULL; + ps_cmd.dummyBitLen = 0; + + for(uint32_t i=0; i