From ff195f3492b0b86a242b5f7ed21e77121287d4de Mon Sep 17 00:00:00 2001 From: armando Date: Fri, 13 Jun 2025 15:46:17 +0800 Subject: [PATCH] feat(psram): support fallback to use default driver pattern when id isn't match --- .../esp_psram/device/esp_psram_impl_ap_hex.c | 55 +++++++++++++++++-- .../esp_psram/device/esp_psram_impl_ap_quad.c | 49 ++++++++++++++++- .../esp_psram/esp32s3/esp_psram_impl_octal.c | 53 ++++++++++++++++-- 3 files changed, 144 insertions(+), 13 deletions(-) diff --git a/components/esp_psram/device/esp_psram_impl_ap_hex.c b/components/esp_psram/device/esp_psram_impl_ap_hex.c index 5741acef32..acf07e4d73 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_hex.c +++ b/components/esp_psram/device/esp_psram_impl_ap_hex.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,7 +48,8 @@ #define AP_HEX_PSRAM_WR_LATENCY 2 #endif -#define AP_HEX_PSRAM_VENDOR_ID 0xD +#define AP_HEX_PSRAM_VENDOR_ID_AP 0xD +#define AP_HEX_PSRAM_VENDOR_ID_UNILC 0x1A //UnilC shares driver pattern with AP #define AP_HEX_PSRAM_CS_SETUP_TIME 4 #define AP_HEX_PSRAM_CS_HOLD_TIME 4 #define AP_HEX_PSRAM_CS_ECC_HOLD_TIME 4 @@ -56,6 +57,8 @@ #define AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ 400 +#define AP_HEX_PSRAM_REF_DATA 0x5a6b7c8d + typedef struct { union { struct { @@ -257,6 +260,41 @@ static void s_get_psram_mode_reg(int spi_num, hex_psram_mode_reg_t *out_reg) false); } +/** + * Check if PSRAM is connected by write and read + */ +static esp_err_t s_check_psram_connected(int spi_num) +{ + uint32_t addr = 0x80; + uint32_t ref_data = AP_HEX_PSRAM_REF_DATA; + uint32_t exp_data = 0; + int data_bit_len = 32; + + //write + addr = 0x0; + s_psram_common_transaction(spi_num, + AP_HEX_PSRAM_SYNC_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN, + addr, AP_HEX_PSRAM_ADDR_BITLEN, + AP_HEX_PSRAM_WR_DUMMY_BITLEN, + (uint8_t *)&ref_data, data_bit_len, + NULL, 0, + false); + + //read MR4 and MR8 + s_psram_common_transaction(spi_num, + AP_HEX_PSRAM_SYNC_READ, AP_HEX_PSRAM_RD_CMD_BITLEN, + addr, AP_HEX_PSRAM_ADDR_BITLEN, + AP_HEX_PSRAM_RD_DUMMY_BITLEN, + NULL, 0, + (uint8_t *)&exp_data, data_bit_len, + false); + + ESP_EARLY_LOGD(TAG, "exp_data: 0x%08x", exp_data); + ESP_EARLY_LOGD(TAG, "ref_data: 0x%08x", ref_data); + + return (exp_data == ref_data ? ESP_OK : ESP_FAIL); +} + static void s_print_psram_info(hex_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"); @@ -405,12 +443,17 @@ esp_err_t esp_psram_impl_enable(void) mode_reg.mr8.x16 = 0; #endif s_init_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg); - //Print PSRAM info - s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg); - if (mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID) { - ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", mode_reg.mr1.vendor_id); + + if (s_check_psram_connected(PSRAM_CTRLR_LL_MSPI_ID_3) != ESP_OK) { + ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected"); return ESP_ERR_NOT_SUPPORTED; } + + s_get_psram_mode_reg(PSRAM_CTRLR_LL_MSPI_ID_3, &mode_reg); + if (mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != AP_HEX_PSRAM_VENDOR_ID_UNILC) { + ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", mode_reg.mr1.vendor_id); + } + s_print_psram_info(&mode_reg); s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB : mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB : diff --git a/components/esp_psram/device/esp_psram_impl_ap_quad.c b/components/esp_psram/device/esp_psram_impl_ap_quad.c index a269751388..412141fbac 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_quad.c +++ b/components/esp_psram/device/esp_psram_impl_ap_quad.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,8 @@ #include "esp_quad_psram_defs.h" #include "soc/soc_caps.h" +#define AP_HEX_PSRAM_REF_DATA 0x5a6b7c8d + static const char* TAG = "quad_psram"; static uint32_t s_psram_size = 0; //this stands for physical psram size in bytes @@ -172,6 +174,42 @@ static void psram_set_cs_timing(void) psram_ctrlr_ll_set_cs_setup(PSRAM_CTRLR_LL_MSPI_ID_0, PSRAM_CS_SETUP_VAL); } +/** + * Check if PSRAM is connected by write and read + */ +static esp_err_t s_check_psram_connected(int spi_num) +{ + uint32_t addr = 0x0; + uint32_t ref_data = AP_HEX_PSRAM_REF_DATA; + uint32_t exp_data = 0; + int data_bit_len = 32; + + //write + psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, + PSRAM_WRITE, 8, + addr, 24, + 0, + (uint8_t *)&ref_data, data_bit_len, + NULL, 0, + PSRAM_LL_CS_SEL, + false); + + //read MR4 and MR8 + psram_exec_cmd(spi_num, PSRAM_HAL_CMD_SPI, + PSRAM_READ, 8, + addr, 24, + 0, + NULL, 0, + (uint8_t *)&exp_data, data_bit_len, + PSRAM_LL_CS_SEL, + false); + + ESP_EARLY_LOGV(TAG, "exp_data: 0x%08x", exp_data); + ESP_EARLY_LOGV(TAG, "ref_data: 0x%08x", ref_data); + + return (exp_data == ref_data ? ESP_OK : ESP_FAIL); +} + static void psram_gpio_config(void) { //CS1 @@ -250,6 +288,12 @@ esp_err_t esp_psram_impl_enable(void) //We use SPI1 to init PSRAM psram_disable_qio_mode(PSRAM_CTRLR_LL_MSPI_ID_1); + + if (s_check_psram_connected(PSRAM_CTRLR_LL_MSPI_ID_1) != ESP_OK) { + ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected, or wrong PSRAM line mode"); + return ESP_ERR_NOT_SUPPORTED; + } + psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM); if (!PSRAM_IS_VALID(psram_id)) { /* 16Mbit psram ID read error workaround: @@ -258,8 +302,7 @@ esp_err_t esp_psram_impl_enable(void) */ psram_read_id(PSRAM_CTRLR_LL_MSPI_ID_1, (uint8_t *)&psram_id, PSRAM_ID_BITS_NUM); if (!PSRAM_IS_VALID(psram_id)) { - ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", (uint32_t)psram_id); - return ESP_ERR_NOT_SUPPORTED; + ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", (uint32_t)psram_id); } } diff --git a/components/esp_psram/esp32s3/esp_psram_impl_octal.c b/components/esp_psram/esp32s3/esp_psram_impl_octal.c index a801079ac8..1f3254499e 100644 --- a/components/esp_psram/esp32s3/esp_psram_impl_octal.c +++ b/components/esp_psram/esp32s3/esp_psram_impl_octal.c @@ -45,6 +45,8 @@ #define OCT_PSRAM_PAGE_SIZE 2 //2 for 1024B #define OCT_PSRAM_ECC_ENABLE_MASK BIT(8) +#define OCT_PSRAM_REF_DATA 0x5a6b7c8d + typedef struct { union { struct { @@ -222,6 +224,44 @@ static void s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *out_reg) false); } +/** + * Check if PSRAM is connected by write and read + */ +static esp_err_t s_check_psram_connected(int spi_num) +{ + esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE; + int cmd_len = OCT_PSRAM_WR_CMD_BITLEN; + uint32_t addr = 0x0; + int addr_bit_len = OCT_PSRAM_ADDR_BITLEN; + uint32_t ref_data = OCT_PSRAM_REF_DATA; + uint32_t exp_data = 0; + int data_bit_len = 32; + + //write + esp_rom_opiflash_exec_cmd(spi_num, mode, + OPI_PSRAM_SYNC_WRITE, cmd_len, + addr, addr_bit_len, + OCT_PSRAM_WR_DUMMY_BITLEN, + (uint8_t *)&ref_data, data_bit_len, + NULL, 0, + BIT(1), + false); + //read + esp_rom_opiflash_exec_cmd(spi_num, mode, + OPI_PSRAM_SYNC_READ, cmd_len, + addr, addr_bit_len, + OCT_PSRAM_RD_DUMMY_BITLEN, + NULL, 0, + (uint8_t *)&exp_data, data_bit_len, + BIT(1), + false); + + ESP_EARLY_LOGD(TAG, "exp_data: 0x%08x", exp_data); + ESP_EARLY_LOGD(TAG, "ref_data: 0x%08x", ref_data); + + return (exp_data == ref_data ? ESP_OK : ESP_FAIL); +} + static void 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" : (reg_val->mr1.vendor_id == 0x1a ? "UnilC" : "UNKNOWN")); @@ -316,12 +356,17 @@ esp_err_t esp_psram_impl_enable(void) mode_reg.mr8.bl = 3; mode_reg.mr8.bt = 0; s_init_psram_mode_reg(1, &mode_reg); - //Print PSRAM info - s_get_psram_mode_reg(1, &mode_reg); - if (mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_UNILC) { - ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x, PSRAM chip not found or not supported, or wrong PSRAM line mode", mode_reg.mr1.vendor_id); + + if (s_check_psram_connected(1) != ESP_OK) { + ESP_EARLY_LOGE(TAG, "PSRAM chip is not connected, or wrong PSRAM line mode"); return ESP_ERR_NOT_SUPPORTED; } + + s_get_psram_mode_reg(1, &mode_reg); + if (mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_AP && mode_reg.mr1.vendor_id != OCT_PSRAM_VENDOR_ID_UNILC) { + ESP_EARLY_LOGW(TAG, "PSRAM ID read error: 0x%08x, fallback to use default driver pattern", mode_reg.mr1.vendor_id); + } + s_print_psram_info(&mode_reg); s_psram_size = mode_reg.mr2.density == 0x1 ? PSRAM_SIZE_4MB : mode_reg.mr2.density == 0X3 ? PSRAM_SIZE_8MB :